]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: free crypt_device object before trying to activate with unique name
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 17 Sep 2022 00:01:46 +0000 (09:01 +0900)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 18 Sep 2022 09:19:33 +0000 (11:19 +0200)
Otherwise we get error from libcryptsetup like the following:
systemd[1234]: Cannot use device /dev/loop5 which is in use (already mapped or mounted).

src/shared/dissect-image.c

index 5e4883a7a7c6028bb933b4a3b1f0329f83dc746d..ec7b5e9516167b1be47eecfe832bc4cb72fb9ec4 100644 (file)
@@ -1979,7 +1979,7 @@ static int verity_partition(
                  * Improvements in libcrypsetup can ensure this never happens:
                  * https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */
                 if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
-                        return verity_partition(designator, m, v, verity, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
+                        break;
                 if (r < 0 && !IN_SET(r,
                                      -EEXIST, /* Volume is already open and ready to be used */
                                      -EBUSY,  /* Volume is being opened but not ready, crypt_init_by_name can fetch details */
@@ -2004,7 +2004,7 @@ static int verity_partition(
                         r = verity_can_reuse(verity, name, &existing_cd);
                         /* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */
                         if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
-                                return verity_partition(designator, m, v, verity, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
+                                break;
                         if (r < 0 && !IN_SET(r, -ENODEV, -ENOENT, -EBUSY))
                                 return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node);
                         if (r >= 0) {
@@ -2012,7 +2012,7 @@ static int verity_partition(
                                  * created. Check and wait for the udev event in that case. */
                                 r = device_wait_for_devlink(node, "block", verity_timeout(), NULL);
                                 /* Fallback to activation with a unique device if it's taking too long */
-                                if (r == -ETIMEDOUT)
+                                if (r == -ETIMEDOUT && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
                                         break;
                                 if (r < 0)
                                         return r;
@@ -2027,9 +2027,18 @@ static int verity_partition(
                 (void) usleep(2 * USEC_PER_MSEC);
         }
 
-        /* All trials failed. Let's try to activate with a unique name. */
-        if (FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
+        /* All trials failed or a conflicting verity device exists. Let's try to activate with a unique name. */
+        if (FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) {
+                /* Before trying to activate with unique name, we need to free crypt_device object.
+                 * Otherwise, we get error from libcryptsetup like the following:
+                 * ------
+                 * systemd[1234]: Cannot use device /dev/loop5 which is in use (already mapped or mounted).
+                 * ------
+                 */
+                sym_crypt_free(cd);
+                cd = NULL;
                 return verity_partition(designator, m, v, verity, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
+        }
 
         return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), "All attempts to activate verity device %s failed.", name);