From ecf2329e14f1c554e2a3c240290cb9116546597f Mon Sep 17 00:00:00 2001 From: Michael Ferrari Date: Mon, 30 Mar 2026 02:48:48 +0200 Subject: [PATCH] Initialize roothash when populating sig partition This allows one to specify `CopyBlocks=` on both the `Verity=` data and hash partition and the signature is recreated correctly. --- src/repart/repart.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/repart/repart.c b/src/repart/repart.c index fd1f16d4de3..1512c1a0d6c 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -5788,21 +5788,41 @@ static int sign_verity_roothash( #endif } -static const VeritySettings *lookup_verity_settings_by_uuid_pair(sd_id128_t data_uuid, sd_id128_t hash_uuid) { - uint8_t root_hash_key[sizeof(sd_id128_t) * 2]; +static int iovec_roothash_from_uuid_pair( + sd_id128_t data_uuid, + sd_id128_t hash_uuid, + struct iovec *ret_roothash) { + + uint8_t roothash_bytes[sizeof(sd_id128_t) * 2]; + + assert(ret_roothash); if (sd_id128_is_null(data_uuid) || sd_id128_is_null(hash_uuid)) - return NULL; + return -EINVAL; /* As per the https://uapi-group.org/specifications/specs/discoverable_partitions_specification/ the * UUIDs of the data and verity partitions are respectively the first and second halves of the * dm-verity roothash, so we can use them to match the signature to the right partition. */ - memcpy(root_hash_key, data_uuid.bytes, sizeof(sd_id128_t)); - memcpy(root_hash_key + sizeof(sd_id128_t), hash_uuid.bytes, sizeof(sd_id128_t)); + memcpy(roothash_bytes, data_uuid.bytes, sizeof(sd_id128_t)); + memcpy(roothash_bytes + sizeof(sd_id128_t), hash_uuid.bytes, sizeof(sd_id128_t)); + + if (!iovec_memdup(&IOVEC_MAKE(roothash_bytes, sizeof(roothash_bytes)), ret_roothash)) + return -ENOMEM; + + return 0; +} + +static const VeritySettings *lookup_verity_settings_by_uuid_pair(sd_id128_t data_uuid, sd_id128_t hash_uuid) { + _cleanup_(iovec_done) struct iovec roothash = {}; + int r; + + r = iovec_roothash_from_uuid_pair(data_uuid, hash_uuid, &roothash); + if (r < 0) + return NULL; VeritySettings key = { - .root_hash = IOVEC_MAKE(root_hash_key, sizeof(root_hash_key)), + .root_hash = roothash, }; return set_get(arg_verity_settings, &key); @@ -5834,6 +5854,14 @@ static int partition_format_verity_sig(Context *context, Partition *p) { assert_se(rp = p->siblings[VERITY_DATA]); assert(!rp->dropped); + /* Currently only set while formatting the hash partition. But if this is skipped via CopyBlocks= + * we just derive the roothash from the UUIDs from the data + hash partition. */ + if (!iovec_is_set(&hp->roothash)) { + r = iovec_roothash_from_uuid_pair(rp->new_uuid, hp->new_uuid, &hp->roothash); + if (r < 0) + return log_error_errno(r, "Unable to derive roothash: %m"); + } + verity_settings = lookup_verity_settings_by_uuid_pair(rp->current_uuid, hp->current_uuid); if (!verity_settings) { -- 2.47.3