libfstools: avoid segfault in find_mount_point
[project/fstools.git] / block.c
diff --git a/block.c b/block.c
index f094216447391d8fc9be9e28b9e0a2afc0906c54..9f5cebf28f5adddbf42791fa9b6b00bff11b567b 100644 (file)
--- a/block.c
+++ b/block.c
@@ -483,19 +483,27 @@ static int config_load(char *cfg)
 
 static struct probe_info* _probe_path(char *path)
 {
-       struct probe_info *pr;
+       struct probe_info *pr, *epr;
        char tmppath[64];
 
-       /* skip ubi device if ubiblock device is present */
+       pr = probe_path(path);
+       if (!pr)
+               return NULL;
+
        if (path[5] == 'u' && path[6] == 'b' && path[7] == 'i' &&
            path[8] >= '0' && path[8] <= '9' ) {
+               /* skip ubi device if not UBIFS (as it requires ubiblock) */
+               if (strcmp("ubifs", pr->type))
+                       return NULL;
+
+               /* skip ubi device if ubiblock device is present */
                snprintf(tmppath, sizeof(tmppath), "/dev/ubiblock%s", path + 8);
-               list_for_each_entry(pr, &devices, list)
-                       if (!strcasecmp(pr->dev, tmppath))
+               list_for_each_entry(epr, &devices, list)
+                       if (!strcmp(epr->dev, tmppath))
                                return NULL;
        }
 
-       return probe_path(path);
+       return pr;
 }
 
 static int _cache_load(const char *path)
@@ -533,7 +541,7 @@ static void cache_load(int mtd)
        _cache_load("/dev/nvme*");
        _cache_load("/dev/vd*");
        _cache_load("/dev/xvd*");
-       _cache_load("/dev/mapper/*");
+       _cache_load("/dev/dm-*");
 }
 
 
@@ -923,6 +931,8 @@ static int handle_mount(const char *source, const char *target,
                err = exec_mount(source, target, fstype, mount_opts);
        }
 
+       free(mount_opts);
+
        return err;
 }
 
@@ -994,7 +1004,7 @@ static int mount_device(struct probe_info *pr, int type)
 {
        struct mount *m;
        struct stat st;
-       char _target[32];
+       char *_target = NULL;
        char *target;
        char *device;
        char *mp;
@@ -1021,7 +1031,7 @@ static int mount_device(struct probe_info *pr, int type)
 
        mp = find_mount_point(pr->dev);
        if (mp) {
-               if (m && m->type == TYPE_MOUNT && strcmp(m->target, mp)) {
+               if (m && m->type == TYPE_MOUNT && m->target && strcmp(m->target, mp)) {
                        ULOG_ERR("%s is already mounted on %s\n", pr->dev, mp);
                        err = -1;
                } else
@@ -1053,16 +1063,22 @@ static int mount_device(struct probe_info *pr, int type)
                }
 
                if (m->autofs) {
-                       snprintf(_target, sizeof(_target), "/tmp/run/blockd/%s", device);
+                       if (asprintf(&_target, "/tmp/run/blockd/%s", device) == -1)
+                               exit(ENOMEM);
+
                        target = _target;
                } else if (m->target) {
                        target = m->target;
                } else {
-                       snprintf(_target, sizeof(_target), "/mnt/%s", device);
+                       if (asprintf(&_target, "/mnt/%s", device) == -1)
+                               exit(ENOMEM);
+
                        target = _target;
                }
        } else if (anon_mount) {
-               snprintf(_target, sizeof(_target), "/mnt/%s", device);
+               if (asprintf(&_target, "/mnt/%s", device) == -1)
+                       exit(ENOMEM);
+
                target = _target;
        } else {
                /* No reason to mount this device */
@@ -1082,9 +1098,16 @@ static int mount_device(struct probe_info *pr, int type)
        if (err) {
                ULOG_ERR("mounting %s (%s) as %s failed (%d) - %m\n",
                                pr->dev, pr->type, target, errno);
+
+               if (_target)
+                       free(_target);
+
                return err;
        }
 
+       if (_target)
+               free(_target);
+
        handle_swapfiles(true);
 
        if (type != TYPE_AUTOFS)
@@ -1095,15 +1118,25 @@ static int mount_device(struct probe_info *pr, int type)
 
 static int umount_device(char *path, int type, bool all)
 {
-       char *mp;
+       char *mp, *devpath;
        int err;
 
-       mp = find_mount_point(path);
+       if (strlen(path) > 5 && !strncmp("/dev/", path, 5)) {
+               mp = find_mount_point(path);
+       } else {
+               devpath = malloc(strlen(path) + 6);
+               strcpy(devpath, "/dev/");
+               strcat(devpath, path);
+               mp = find_mount_point(devpath);
+               free(devpath);
+       }
+
        if (!mp)
                return -1;
-       if (!strcmp(mp, "/") && !all)
+       if (!strcmp(mp, "/") && !all) {
+               free(mp);
                return 0;
-
+       }
        if (type != TYPE_AUTOFS)
                blockd_notify("umount", basename(path), NULL, NULL);
 
@@ -1122,17 +1155,17 @@ static int umount_device(char *path, int type, bool all)
 
 static int mount_action(char *action, char *device, int type)
 {
-       char path[32];
+       char *path = NULL;
+       struct probe_info *pr;
 
        if (!action || !device)
                return -1;
-       snprintf(path, sizeof(path), "/dev/%s", device);
 
        if (!strcmp(action, "remove")) {
                if (type == TYPE_HOTPLUG)
                        blockd_notify("hotplug", device, NULL, NULL);
 
-               umount_device(path, type, true);
+               umount_device(device, type, true);
 
                return 0;
        } else if (strcmp(action, "add")) {
@@ -1143,7 +1176,15 @@ static int mount_action(char *action, char *device, int type)
 
        if (config_load(NULL))
                return -1;
-       cache_load(0);
+
+       cache_load(1);
+
+       list_for_each_entry(pr, &devices, list)
+               if (!strcmp(basename(pr->dev), device))
+                       path = pr->dev;
+
+       if (!path)
+               return -1;
 
        return mount_device(find_block_info(NULL, NULL, path), type);
 }
@@ -1166,7 +1207,7 @@ static int main_autofs(int argc, char **argv)
                if (config_load(NULL))
                        return -1;
 
-               cache_load(0);
+               cache_load(1);
                list_for_each_entry(pr, &devices, list) {
                        struct mount *m;
                        char *mp;
@@ -1609,7 +1650,7 @@ static int main_umount(int argc, char **argv)
 
        handle_swapfiles(false);
 
-       cache_load(0);
+       cache_load(1);
 
        if (argc == 3)
                all = !strcmp(argv[2], "-a");