]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Initialize roothash when populating sig partition 41393/head
authorMichael Ferrari <nekkodroid404@gmail.com>
Mon, 30 Mar 2026 00:48:48 +0000 (02:48 +0200)
committerMichael Ferrari <nekkodroid404@gmail.com>
Thu, 2 Apr 2026 11:21:08 +0000 (13:21 +0200)
This allows one to specify `CopyBlocks=` on both the `Verity=` data and
hash partition and the signature is recreated correctly.

src/repart/repart.c

index fd1f16d4de38ea2ed2452fd8e45fb964864a0373..1512c1a0d6c63bee91235beb171cc1925456ea68 100644 (file)
@@ -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) {