From d3a6606cea2929c209e7da3118dafc8d29b0ce19 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 2 Jun 2025 19:27:33 +0200 Subject: [PATCH] repart: try harder to find verity-sig partitions for CopyBlocks=auto verity-sig partitions are not kernel concepts, hence dm-verity won't link them for us from the slaves/ subdir in sysfs. Hence let's instead look up the partition via udev's database. Hence: when we search for the data+verity+verity-sig partitions then search for the first two as usual, but search for the latter by looking up the udev props on the first two, and then following the paths provided therein. Fixes: #34835 --- src/repart/repart.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/src/repart/repart.c b/src/repart/repart.c index 5fe195c033..b8bfeb87e8 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -7250,6 +7250,82 @@ static int resolve_copy_blocks_auto_candidate( return true; } +static int resolve_copy_blocks_auto_candidate_harder( + dev_t start_devno, + GptPartitionType partition_type, + dev_t restrict_devno, + dev_t *ret_found_devno, + sd_id128_t *ret_uuid) { + + _cleanup_(sd_device_unrefp) sd_device *d = NULL, *nd = NULL; + int r; + + /* A wrapper around resolve_copy_blocks_auto_candidate(), but looks for verity/verity-sig associated + * partitions, too. i.e. if the input is a data or verity partition, will try to find the + * verity/verity-sig partition for it, based on udev metadata. */ + + const char *property; + if (partition_designator_is_verity(partition_type.designator)) + property = "ID_DISSECT_PART_VERITY_DEVICE"; + else if (partition_designator_is_verity_sig(partition_type.designator)) + property = "ID_DISSECT_PART_VERITY_SIG_DEVICE"; + else + goto not_found; + + r = sd_device_new_from_devnum(&d, 'b', start_devno); + if (r < 0) + return log_error_errno(r, "Failed to allocate device object for " DEVNUM_FORMAT_STR ": %m", DEVNUM_FORMAT_VAL(start_devno)); + + const char *node; + r = sd_device_get_property_value(d, property, &node); + if (r == -ENOENT) { + log_debug_errno(r, "Property %s not set on " DEVNUM_FORMAT_STR ", skipping.", property, DEVNUM_FORMAT_VAL(start_devno)); + goto not_found; + } + if (r < 0) + return log_error_errno(r, "Failed to read property %s from device " DEVNUM_FORMAT_STR ": %m", property, DEVNUM_FORMAT_VAL(start_devno)); + + r = sd_device_new_from_devname(&nd, node); + if (ERRNO_IS_NEG_DEVICE_ABSENT(r)) { + log_debug_errno(r, "Device %s referenced in %s property not found, skipping: %m", node, property); + goto not_found; + } + if (r < 0) + return log_error_errno(r, "Failed to allocate device object for '%s': %m", node); + + r = device_in_subsystem(nd, "block"); + if (r < 0) + return log_error_errno(r, "Failed to determine if '%s' is a block device: %m", node); + if (r == 0) { + log_debug("Device referenced by %s property of %s does not refer to block device, refusing.", property, node); + goto not_found; + } + + dev_t found_devno = 0; + r = sd_device_get_devnum(nd, &found_devno); + if (r < 0) + return log_error_errno(r, "Failed to get device number for '%s': %m", node); + + r = resolve_copy_blocks_auto_candidate(found_devno, partition_type, restrict_devno, ret_uuid); + if (r < 0) + return r; + if (r == 0) + goto not_found; + + if (ret_found_devno) + *ret_found_devno = found_devno; + + return 1; + +not_found: + if (ret_found_devno) + *ret_found_devno = 0; + if (ret_uuid) + *ret_uuid = SD_ID128_NULL; + + return 0; +} + static int find_backing_devno( const char *path, const char *root, @@ -7391,7 +7467,7 @@ static int resolve_copy_blocks_auto( return r; if (r > 0) { /* We found a matching one! */ - if (found != 0) + if (found != 0 && found != sl) return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ), "Multiple matching partitions found for partition type %s, refusing.", partition_designator_to_string(type.designator)); @@ -7399,6 +7475,20 @@ static int resolve_copy_blocks_auto( found = sl; found_uuid = u; } + + dev_t harder_devno = 0; + r = resolve_copy_blocks_auto_candidate_harder(sl, type, restrict_devno, &harder_devno, &u); + if (r < 0) + return r; + if (r > 0) { + /* We found a matching one! */ + if (found != 0 && found != harder_devno) + return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ), + "Multiple matching partitions found, refusing."); + + found = harder_devno; + found_uuid = u; + } } } else if (errno != ENOENT) return log_error_errno(errno, "Failed open %s: %m", p);