veritysetup: make root-hash-signature=auto optional

systemd-gpt-auto-generator always passes root-hash-signature=auto for
the root and /usr partitions. The data device doesn't have the
ID_DISSECT_PART_ROOTHASH_SIG udev property if the image has no signature
partition. In that case, systemd-veritysetup fails, and the system can't
boot from a verity image that isn't signed. If a signature exists but
neither the kernel nor userspace validates it, we activate the device
without the signature.

The image builder controls whether the image has a signature partition.
Whether the boot requires a signature thus depends on the image
contents. The failure gives no protection, because an image with a
signature that doesn't validate boots. Anyone can avoid the failure by
adding a signature partition with any well-formed signature. Whether a
signature is required must come from the host.
systemd-gpt-auto-generator enables root-hash-signature-required= if
systemd.image_policy= requires a signature. With that option, activation
fails if the signature is missing or invalid.

Let's activate the device without a signature if the property is
missing and root-hash-signature-required= isn't enabled.
This commit is contained in:
Daan De Meyer committed 2026-11-01 21:04:58 +01:00
1 parent 1c6bcc4f51
commit 9a8a4428bb
4 files changed
+30 -13

No files matched your search

+7 -5
View File
@@ -79,11 +79,13 @@ CHANGES WITH 263 in spe:
* systemd-portabled now asks polkit before it inspects extension
images that are specified by path.
* systemd-veritysetup gained a root-hash-signature-required= option,
which systemd-gpt-auto-generator enables if systemd.image_policy=
requires a signature. If the kernel can't validate the root hash
signature, systemd-veritysetup now validates it in userspace with
the certificates in /etc/verity.d/, like systemd-dissect does.
* systemd-veritysetup no longer fails if root-hash-signature=auto
finds no signature. It gained a root-hash-signature-required=
option, which systemd-gpt-auto-generator enables if
systemd.image_policy= requires a signature. If the kernel can't
validate the root hash signature, systemd-veritysetup now
validates it in userspace with the certificates in
/etc/verity.d/, like systemd-dissect does.
* systemd-networkd and networkctl have been merged into a single
multi-call binary, with the former becoming a symlink to the latter.
+3 -2
View File
@@ -221,8 +221,9 @@ This is based on crypttab(5).
<literal>base64:</literal>, or an absolute path to a root hash signature file used to verify the root
hash (in kernel). If the special string <literal>auto</literal> is specified, the root hash signature
is attempted to be read from the udev property <literal>ID_DISSECT_PART_ROOTHASH_SIG=</literal> (in
Base64 format) of the data device. This feature requires Linux kernel version 5.4 or more
recent.</para>
Base64 format) of the data device. If the data device doesn't have this property, the device is
activated without a root hash signature, unless <option>root-hash-signature-required=yes</option> is
specified. This feature requires Linux kernel version 5.4 or more recent.</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
+9 -6
View File
@@ -366,12 +366,15 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
const char *t;
r = sd_device_get_property_value(ASSERT_PTR(datadev), "ID_DISSECT_PART_ROOTHASH_SIG", &t);
if (r < 0)
return log_error_errno(r, "Automatic root hash signature pick up requested, and device doesn't carry ID_DISSECT_PART_ROOTHASH_SIG property, cannot determine root hash signature.");
r = unbase64mem(t, &arg_root_hash_signature.iov_base, &arg_root_hash_signature.iov_len);
if (r < 0)
return log_error_errno(r, "Failed to decode root hash signature data from udev data device: %m");
if (r == -ENOENT)
log_debug("Data device doesn't have the ID_DISSECT_PART_ROOTHASH_SIG property, activating without root hash signature.");
else if (r < 0)
return log_error_errno(r, "Failed to read ID_DISSECT_PART_ROOTHASH_SIG property of data device: %m");
else {
r = unbase64mem(t, &arg_root_hash_signature.iov_base, &arg_root_hash_signature.iov_len);
if (r < 0)
return log_error_errno(r, "Failed to decode root hash signature data from udev data device: %m");
}
}
if (arg_root_hash_signature_required && !iovec_is_set(&arg_root_hash_signature))
+11
View File
@@ -264,6 +264,17 @@ cp /tmp/test-50-unknown.crt /run/verity.d/test-50-unknown.crt
root-hash-signature=/tmp/test-50-unknown.p7s,root-hash-signature-required=yes
/usr/lib/systemd/systemd-veritysetup detach test-50-required
rm /run/verity.d/test-50-mkosi.crt /run/verity.d/test-50-unknown.crt /tmp/test-50-unknown.key /tmp/test-50-unknown.crt /tmp/test-50-unknown.p7s /tmp/test-50-garbage.p7s
# A loop device of the plain file system image has no ID_DISSECT_PART_ROOTHASH_SIG property. With
# root-hash-signature=auto, systemd-veritysetup activates it without a signature. If
# root-hash-signature-required=yes is set as well, systemd-veritysetup refuses to activate it.
loop="$(losetup --show -r -f "$MINIMAL_IMAGE.raw")"
udevadm wait --timeout=60 --settle "$loop"
(! /usr/lib/systemd/systemd-veritysetup attach test-50-auto "$loop" "$MINIMAL_IMAGE.verity" "$MINIMAL_IMAGE_ROOTHASH" \
root-hash-signature=auto,root-hash-signature-required=yes)
/usr/lib/systemd/systemd-veritysetup attach test-50-auto "$loop" "$MINIMAL_IMAGE.verity" "$MINIMAL_IMAGE_ROOTHASH" \
root-hash-signature=auto
/usr/lib/systemd/systemd-veritysetup detach test-50-auto
losetup -d "$loop"
# Test BindLogSockets=
systemd-run --wait -p RootImage="$MINIMAL_IMAGE.raw" mountpoint /run/systemd/journal/socket