diff --git a/src/repart/repart.c b/src/repart/repart.c index 5fe195c033..de138c15d3 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -2612,9 +2612,7 @@ static int partition_read_definition(Partition *p, const char *path, const char } /* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */ - if ((IN_SET(p->type.designator, - PARTITION_ROOT_VERITY, - PARTITION_USR_VERITY) || p->verity == VERITY_DATA) && p->read_only < 0) + if ((partition_designator_is_verity(p->type.designator) || p->verity == VERITY_DATA) && p->read_only < 0) p->read_only = true; /* Default to "growfs" on, unless read-only */ @@ -5325,7 +5323,7 @@ static int context_copy_blocks(Context *context) { continue; /* For offline signing case */ - if (!set_isempty(arg_verity_settings) && IN_SET(p->type.designator, PARTITION_ROOT_VERITY_SIG, PARTITION_USR_VERITY_SIG)) + if (!set_isempty(arg_verity_settings) && partition_designator_is_verity_sig(p->type.designator)) return partition_format_verity_sig(context, p); if (p->copy_blocks_fd < 0) @@ -6298,7 +6296,7 @@ static int context_mkfs(Context *context) { continue; /* For offline signing case */ - if (!set_isempty(arg_verity_settings) && IN_SET(p->type.designator, PARTITION_ROOT_VERITY_SIG, PARTITION_USR_VERITY_SIG)) + if (!set_isempty(arg_verity_settings) && partition_designator_is_verity_sig(p->type.designator)) return partition_format_verity_sig(context, p); /* Minimized partitions will use the copy blocks logic so skip those here. */ @@ -7250,6 +7248,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 +7465,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 +7473,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); diff --git a/src/shared/gpt.h b/src/shared/gpt.h index 9e5ace35a4..3261d0001b 100644 --- a/src/shared/gpt.h +++ b/src/shared/gpt.h @@ -31,15 +31,19 @@ typedef enum PartitionDesignator { bool partition_designator_is_versioned(PartitionDesignator d) _const_; -static inline bool partition_designator_is_verity_sig(PartitionDesignator d) { - return IN_SET(d, PARTITION_ROOT_VERITY_SIG, PARTITION_USR_VERITY_SIG); -} - PartitionDesignator partition_verity_of(PartitionDesignator p) _const_; PartitionDesignator partition_verity_sig_of(PartitionDesignator p) _const_; PartitionDesignator partition_verity_to_data(PartitionDesignator d) _const_; PartitionDesignator partition_verity_sig_to_data(PartitionDesignator d) _const_; +static inline bool partition_designator_is_verity(PartitionDesignator d) { + return partition_verity_to_data(d) >= 0; +} + +static inline bool partition_designator_is_verity_sig(PartitionDesignator d) { + return partition_verity_sig_to_data(d) >= 0; +} + const char* partition_designator_to_string(PartitionDesignator d) _const_; PartitionDesignator partition_designator_from_string(const char *name) _pure_; diff --git a/src/udev/udev-builtin-dissect_image.c b/src/udev/udev-builtin-dissect_image.c index 02aa8fcbea..444b0fce37 100644 --- a/src/udev/udev-builtin-dissect_image.c +++ b/src/udev/udev-builtin-dissect_image.c @@ -124,6 +124,11 @@ static int verb_probe(UdevEvent *event, sd_device *dev) { return 0; } + uint64_t diskseq; + r = sd_device_get_diskseq(dev, &diskseq); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get diskseq of '%s': %m", devnode); + r = blockdev_partscan_enabled(dev); if (r < 0) return log_device_debug_errno(dev, r, "Failed to determine if block device '%s' supports partitions: %m", devnode); @@ -262,11 +267,22 @@ static int verb_probe(UdevEvent *event, sd_device *dev) { /* Indicate whether this partition has verity protection */ PartitionDesignator dv = partition_verity_of(d); if (dv >= 0 && image->partitions[dv].found) { + /* Add one property that indicates as a boolean whether Verity is available at all for this */ _cleanup_free_ char *f = NULL; if (asprintf(&f, "ID_DISSECT_PART%i_HAS_VERITY", p->partno) < 0) return log_oom_debug(); (void) udev_builtin_add_property(event, f, "1"); + + /* Add a second property that indicates where the block device is found with the + * Verity data. We maintain this in an independent property, since Verity data might + * be available from other sources too, not just block devices, and we'd like to keep + * the props somewhat open for that. */ + f = mfree(f); + if (asprintf(&f, "ID_DISSECT_PART%i_VERITY_DEVICE", p->partno) < 0) + return log_oom_debug(); + + (void) udev_builtin_add_propertyf(event, f, "/dev/disk/by-diskseq/%" PRIu64 "-part%i", diskseq, image->partitions[dv].partno); } dv = partition_verity_sig_of(d); @@ -276,6 +292,12 @@ static int verb_probe(UdevEvent *event, sd_device *dev) { return log_oom_debug(); (void) udev_builtin_add_property(event, f, "1"); + + f = mfree(f); + if (asprintf(&f, "ID_DISSECT_PART%i_VERITY_SIG_DEVICE", p->partno) < 0) + return log_oom_debug(); + + (void) udev_builtin_add_propertyf(event, f, "/dev/disk/by-diskseq/%" PRIu64 "-part%i", diskseq, image->partitions[dv].partno); } if (d == verity.designator) { @@ -344,7 +366,12 @@ static int verb_copy(UdevEvent *event, sd_device *dev) { if (r < 0) return log_device_debug_errno(dev, r, "Failed to get partition number of partition block device '%s': %m", devnode); - FOREACH_STRING(f, "_DESIGNATOR", "_ARCHITECTURE", "_HAS_VERITY", "_HAS_VERITY_SIG", "_ROOTHASH", "_ROOTHASH_SIG") { + FOREACH_STRING(f, + "_DESIGNATOR", "_ARCHITECTURE", + "_HAS_VERITY", "_HAS_VERITY_SIG", + "_ROOTHASH", "_ROOTHASH_SIG", + "_VERITY_DEVICE", "_VERITY_SIG_DEVICE") { + /* The property on the parent device contains the partition number */ _cleanup_free_ char *p = strjoin("ID_DISSECT_PART", partn, f); if (!p)