]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
verity: use <roothash>-verity as the device mapper name instead of libmnt_<image>
authorLuca Boccassi <bluca@debian.org>
Thu, 10 Aug 2023 23:18:22 +0000 (00:18 +0100)
committerLuca Boccassi <bluca@debian.org>
Fri, 11 Aug 2023 15:09:34 +0000 (16:09 +0100)
If the roothash is the same among two volumes, then the images are guaranteed
to be equivalent. The filename of the image on the other hand does not imply
that the images are equivalent.
In systemd we open verity devices as '<roothash>-verity', so that we know for
sure we can reuse them. Do the same here, so that we are a bit more confident
that images can be reused before the safety check, and also so that we can
take advantage of the kernel refcounting together with images used by systemd,
as setting up verity is expensive.

Signed-off-by: Luca Boccassi <bluca@debian.org>
libmount/src/hook_veritydev.c

index f91778ad95bcd58ae321cbe0785513a09bca6b13..e4805a4e73b813f643622c2d8e9cd5ea252d36ae 100644 (file)
@@ -349,25 +349,8 @@ static int setup_veritydev(        struct libmnt_context *cxt,
        backing_file = mnt_fs_get_srcpath(cxt->fs);
        if (!backing_file)
                return -EINVAL;
-       else {
-               /* To avoid clashes, prefix libmnt_ to all mapper devices */
-               char *p, *path = strdup(backing_file);
-               if (!path)
-                       return -ENOMEM;
-
-               p = stripoff_last_component(path);
-               if (p)
-                       mapper_device = calloc(strlen(p) + sizeof("libmnt_"), sizeof(char));
-               if (mapper_device) {
-                       strcat(mapper_device, "libmnt_");
-                       strcat(mapper_device, p);
-               }
-               free(path);
-               if (!mapper_device)
-                       return -ENOMEM;
-       }
 
-       DBG(HOOK, ul_debugobj(hs, "verity: setup for %s [%s]", backing_file, mapper_device));
+       DBG(HOOK, ul_debugobj(hs, "verity: setup for %s", backing_file));
 
        /* verity.hashdevice= */
        if (!rc && (opt = mnt_optlist_get_opt(ol, MNT_MS_HASH_DEVICE, cxt->map_userspace)))
@@ -467,6 +450,13 @@ static int setup_veritydev(        struct libmnt_context *cxt,
                rc = -EINVAL;
        }
 
+       /* To avoid clashes, use the roothash as the device name. This allows us to reuse already open devices, saving
+        * a lot of time and resources when there are duplicated mounts. If the roothash is the same, then the volumes
+        * are also guaranteed to be identical. This is what systemd also does, so we can deduplicate across the whole
+        * system. */
+       if (asprintf(&mapper_device, "%s-verity", root_hash) < 0)
+               rc = -ENOMEM;
+
        if (!rc)
                rc = verity_call( crypt_init_data_device(&crypt_dev, hash_device, backing_file) );
        if (rc)
@@ -506,7 +496,9 @@ static int setup_veritydev( struct libmnt_context *cxt,
         * If the mapper device already exists, and if libcryptsetup supports it, get the root
         * hash associated with the existing one and compare it with the parameter passed by
         * the user. If they match, then we can be sure the user intended to mount the exact
-        * same device, and simply reuse it and return success.
+        * same device, and simply reuse it and return success. Although we use the roothash
+        * as the device mapper name, and root privileges are required to open them, better be
+        * safe than sorry, so double check that the actual root hash used matches.
         * The kernel does the refcounting for us.
         * If libcryptsetup does not support getting the root hash out of an existing device,
         * then return an error and tell the user that the device is already in use.