]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: turn verity device sharing into opt-in
authorLennart Poettering <lennart@poettering.net>
Fri, 19 Sep 2025 15:57:37 +0000 (17:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 13 Oct 2025 20:13:53 +0000 (22:13 +0200)
Sharing verity volumes is problematic for a veriety of reasons, for
example because it might pin the wrong backing device at the wrong time.

Let's hence turn this around: unless verity sharing is enabled, leave it
off, and turn $SYSTEMD_VERITY_SHARING into a true boolean that can be
set both ways.

The primary usecase for verity sharing is RootImage=, where it probably
makes sense to leave on, hence set the flag there.

This is crucial when putting together installers which install an OS on
a second disk: if verity sharing is always on we might mount the wrong
of the two disks at the wrong time.

docs/ENVIRONMENT.md
src/core/namespace.c
src/shared/dissect-image.c
test/units/TEST-50-DISSECT.dissect.sh

index eeb7be0ac18eb90e7f7bfdf774cb938cf8d8fcce..3a35c1b9aa0f5bdb5833cc3ef48c66d9ef067d5d 100644 (file)
@@ -123,8 +123,12 @@ All tools:
 * `$SYSTEMD_NETLINK_DEFAULT_TIMEOUT` — specifies the default timeout of waiting
   replies for netlink messages from the kernel. Defaults to 25 seconds.
 
-* `$SYSTEMD_VERITY_SHARING=0` — if set, sharing dm-verity devices by
-  using a stable `<ROOTHASH>-verity` device mapper name will be disabled.
+* `$SYSTEMD_VERITY_SHARING=` — takes a boolean. If set, overrides whether
+  dm-verity devices shall be shared between multiple components by using a
+  stable `<ROOTHASH>-verity` device mapper name. The default for this depends
+  on the subsystem in question. Usually,
+  RootImage=/ExtensionImages=/MountImages= in unit files default to enabled,
+  while other uses default to disabled for this.
 
 `systemctl`:
 
index a90711f5cebbe86ff8592bdd153e0ee99bf878b7..725f954679c929ae7f43a672299ad6edf8d70618 100644 (file)
@@ -2523,7 +2523,8 @@ int setup_namespace(const NamespaceParameters *p, char **reterr_path) {
                 DISSECT_IMAGE_GROWFS |
                 DISSECT_IMAGE_ADD_PARTITION_DEVICES |
                 DISSECT_IMAGE_PIN_PARTITION_DEVICES |
-                DISSECT_IMAGE_ALLOW_USERSPACE_VERITY;
+                DISSECT_IMAGE_ALLOW_USERSPACE_VERITY |
+                DISSECT_IMAGE_VERITY_SHARE;
         int r;
 
         assert(p);
index 44c44080797a494aa70481542c1179fc9d49c94c..60e10b5747a38d86dc7124f11b352c271545b085 100644 (file)
@@ -3064,8 +3064,8 @@ int dissected_image_decrypt(
 
 #if HAVE_LIBCRYPTSETUP
         _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL;
-        int r;
 #endif
+        int r;
 
         assert(m);
         assert(!verity || verity->root_hash || verity->root_hash_size == 0);
@@ -3085,6 +3085,10 @@ int dissected_image_decrypt(
         if (!m->encrypted && !m->verity_ready)
                 return 0;
 
+        r = secure_getenv_bool("SYSTEMD_VERITY_SHARING");
+        if (r >= 0)
+                SET_FLAG(flags, DISSECT_IMAGE_VERITY_SHARE, r);
+
 #if HAVE_LIBCRYPTSETUP
         r = decrypted_image_new(&d);
         if (r < 0)
@@ -3103,8 +3107,6 @@ int dissected_image_decrypt(
 
                 k = partition_verity_hash_of(i);
                 if (k >= 0) {
-                        flags |= getenv_bool("SYSTEMD_VERITY_SHARING") != 0 ? DISSECT_IMAGE_VERITY_SHARE : 0;
-
                         r = verity_partition(i, p, m->partitions + k, verity, flags, d);
                         if (r < 0)
                                 return r;
@@ -4379,7 +4381,8 @@ int verity_dissect_and_mount(
                 (relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0) |
                 DISSECT_IMAGE_ADD_PARTITION_DEVICES |
                 DISSECT_IMAGE_PIN_PARTITION_DEVICES |
-                DISSECT_IMAGE_ALLOW_USERSPACE_VERITY;
+                DISSECT_IMAGE_ALLOW_USERSPACE_VERITY |
+                DISSECT_IMAGE_VERITY_SHARE;
 
         /* Note that we don't use loop_device_make here, as the FD is most likely O_PATH which would not be
          * accepted by LOOP_CONFIGURE, so just let loop_device_make_by_path reopen it as a regular FD. */
index bd0ce438a0d8a05f998dc9745eb52278b9ec8d78..d25a4cb02d4dbe3a49a9742223288b01ac86a744 100755 (executable)
@@ -69,12 +69,12 @@ mv "$MINIMAL_IMAGE.fooverity" "$MINIMAL_IMAGE.verity"
 mv "$MINIMAL_IMAGE.foohash" "$MINIMAL_IMAGE.roothash"
 
 mkdir -p "$IMAGE_DIR/mount" "$IMAGE_DIR/mount2"
-systemd-dissect --mount "$MINIMAL_IMAGE.raw" "$IMAGE_DIR/mount"
+SYSTEMD_VERITY_SHARING=1 systemd-dissect --mount "$MINIMAL_IMAGE.raw" "$IMAGE_DIR/mount"
 grep -q -F -f "$OS_RELEASE" "$IMAGE_DIR/mount/usr/lib/os-release"
 grep -q -F -f "$OS_RELEASE" "$IMAGE_DIR/mount/etc/os-release"
 grep -q -F "MARKER=1" "$IMAGE_DIR/mount/usr/lib/os-release"
 # Verity volume should be shared (opened only once)
-systemd-dissect --mount "$MINIMAL_IMAGE.raw" "$IMAGE_DIR/mount2"
+SYSTEMD_VERITY_SHARING=1 systemd-dissect --mount "$MINIMAL_IMAGE.raw" "$IMAGE_DIR/mount2"
 verity_count=$(find /dev/mapper/ -name "*verity*" | wc -l)
 # In theory we should check that count is exactly one. In practice, libdevmapper
 # randomly and unpredictably fails with an unhelpful EINVAL when a device is open