]> git.ozlabs.org Git - petitboot/blobdiff - discover/device-handler.c
discover/device-handler: Fix use-after-free when unmounting
[petitboot] / discover / device-handler.c
index cd9c41386ea07bdaa9762f75ac3ec81648c5b280..94abb514ab02f4ecd7c6f53aca81a94f7b8afb2f 100644 (file)
@@ -520,6 +520,7 @@ struct discover_context *device_handler_discover_context_create(
        ctx = talloc(handler, struct discover_context);
        ctx->device = device;
        ctx->conf_url = NULL;
+       ctx->test_data = NULL;
        list_init(&ctx->boot_options);
 
        return ctx;
@@ -586,13 +587,16 @@ int device_handler_discover(struct device_handler *handler,
                struct discover_device *dev, enum conf_method method)
 {
        struct discover_context *ctx;
+       int rc;
 
        process_boot_option_queue(handler);
 
        /* create our context */
        ctx = device_handler_discover_context_create(handler, dev);
 
-       mount_device(dev);
+       rc = mount_device(dev);
+       if (rc)
+               goto out;
 
        /* run the parsers. This will populate the ctx's boot_option list. */
        iterate_parsers(ctx, method);
@@ -600,6 +604,7 @@ int device_handler_discover(struct device_handler *handler,
        /* add discovered stuff to the handler */
        device_handler_discover_context_commit(handler, ctx);
 
+out:
        talloc_free(ctx);
 
        return 0;
@@ -716,12 +721,15 @@ static bool check_existing_mount(struct discover_device *dev)
                        continue;
 
                if (mntstat.st_rdev == devstat.st_rdev) {
-                       pb_debug("%s: %s is already mounted at %s\n"
-                                       __func__, dev->device_path,
-                                       mnt->mnt_dir);
                        dev->mount_path = talloc_strdup(dev, mnt->mnt_dir);
+                       dev->mounted_rw = !!hasmntopt(mnt, "rw");
                        dev->mounted = true;
                        dev->unmount = false;
+
+                       pb_debug("%s: %s is already mounted (r%c) at %s\n",
+                                       __func__, dev->device_path,
+                                       dev->mounted_rw ? 'w' : 'o',
+                                       mnt->mnt_dir);
                        break;
                }
        }
@@ -758,6 +766,7 @@ static int mount_device(struct discover_device *dev)
                        "-o", "ro", NULL);
        if (!rc) {
                dev->mounted = true;
+               dev->mounted_rw = false;
                dev->unmount = true;
                return 0;
        }
@@ -768,6 +777,7 @@ static int mount_device(struct discover_device *dev)
 
        if (!rc) {
                dev->mounted = true;
+               dev->mounted_rw = true;
                dev->unmount = true;
                return 0;
        }
@@ -793,13 +803,47 @@ static int umount_device(struct discover_device *dev)
                return -1;
 
        dev->mounted = false;
+
+       pb_rmdir_recursive(mount_base(), dev->mount_path);
+
        talloc_free(dev->mount_path);
        dev->mount_path = NULL;
 
-       pb_rmdir_recursive(mount_base(), dev->mount_path);
+       return 0;
+}
+
+int device_request_write(struct discover_device *dev, bool *release)
+{
+       int rc;
+
+       *release = false;
+
+       if (!dev->mounted)
+               return -1;
 
+       if (dev->mounted_rw)
+               return 0;
+
+       rc = process_run_simple(dev, pb_system_apps.mount, dev->mount_path,
+                       "-o", "remount,rw", NULL);
+       if (rc)
+               return -1;
+
+       dev->mounted_rw = true;
+       *release = true;
        return 0;
 }
+
+void device_release_write(struct discover_device *dev, bool release)
+{
+       if (!release)
+               return;
+
+       process_run_simple(dev, pb_system_apps.mount, dev->mount_path,
+                       "-o", "remount,ro", NULL);
+       dev->mounted_rw = false;
+}
+
 #else
 
 static int umount_device(struct discover_device *dev __attribute__((unused)))
@@ -813,5 +857,17 @@ static int __attribute__((unused)) mount_device(
        return 0;
 }
 
+int device_request_write(struct discover_device *dev __attribute__((unused)),
+               bool *release)
+{
+       *release = true;
+       return 0;
+}
+
+void device_release_write(struct discover_device *dev __attribute__((unused)),
+       bool release __attribute__((unused)))
+{
+}
+
 #endif