From: Lennart Poettering Date: Fri, 19 Sep 2025 15:57:37 +0000 (+0200) Subject: dissect-image: turn verity device sharing into opt-in X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=57d1ceffb3d98f69c2da511ed59a420a1cfa7e40;p=thirdparty%2Fsystemd.git dissect-image: turn verity device sharing into opt-in 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. --- diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index eeb7be0ac18..3a35c1b9aa0 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -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 `-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 `-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`: diff --git a/src/core/namespace.c b/src/core/namespace.c index a90711f5ceb..725f954679c 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -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); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 44c44080797..60e10b5747a 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -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. */ diff --git a/test/units/TEST-50-DISSECT.dissect.sh b/test/units/TEST-50-DISSECT.dissect.sh index bd0ce438a0d..d25a4cb02d4 100755 --- a/test/units/TEST-50-DISSECT.dissect.sh +++ b/test/units/TEST-50-DISSECT.dissect.sh @@ -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