diff --git a/src/repart/repart.c b/src/repart/repart.c index 6bd0c15715..b74d9bb552 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -2809,7 +2809,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 ((partition_designator_is_verity(p->type.designator) || p->verity == VERITY_DATA) && p->read_only < 0) + if ((partition_designator_is_verity_hash(p->type.designator) || p->verity == VERITY_DATA) && p->read_only < 0) p->read_only = true; /* Default to "growfs" on, unless read-only */ @@ -7500,7 +7500,7 @@ static int resolve_copy_blocks_auto_candidate_harder( * verity/verity-sig partition for it, based on udev metadata. */ const char *property; - if (partition_designator_is_verity(partition_type.designator)) + if (partition_designator_is_verity_hash(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"; diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 63826acd9e..44c4408079 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1060,9 +1060,31 @@ static int dissect_image( if (!image_filter_test(filter, type.designator, label)) continue; - log_debug("Dissecting %s partition with label %s and UUID %s", + log_debug("Dissecting %s partition with label %s and UUID %s.", strna(partition_designator_to_string(type.designator)), strna(label), SD_ID128_TO_UUID_STRING(id)); + /* Note that we don't check the SD_GPT_FLAG_NO_AUTO flag for the ESP, as it is + * not defined there. We instead check the SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as + * recommended by the UEFI spec (See "12.3.3 Number and Location of System + * Partitions"). */ + if (FLAGS_SET(pflags, SD_GPT_FLAG_NO_AUTO) && type.designator != PARTITION_ESP) { + log_debug("Partition has 'no auto' flag set, ignoring."); + continue; + } + + if (!verity && partition_designator_is_verity(type.designator)) { + log_debug("Partition is a verity hash or verity signature partition but no verity was requested, ignoring."); + continue; + } + + PartitionDesignator vd = partition_verity_to_data(type.designator); + if (verity && verity->designator >= 0 && vd >= 0 && vd != verity->designator) { + log_debug("Partition is a %s partition but verity was only requested for the %s partition, ignoring.", + partition_designator_to_string(type.designator), + partition_designator_to_string(verity->designator)); + continue; + } + if (IN_SET(type.designator, PARTITION_HOME, PARTITION_SRV, @@ -1072,21 +1094,15 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); } else if (type.designator == PARTITION_ESP) { - /* Note that we don't check the SD_GPT_FLAG_NO_AUTO flag for the ESP, as it is - * not defined there. We instead check the SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as - * recommended by the UEFI spec (See "12.3.3 Number and Location of System - * Partitions"). */ - - if (pflags & SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL) + if (FLAGS_SET(pflags, SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL)) { + log_debug("ESP Partition has 'no block io' flag set, ignoring."); continue; + } fstype = "vfat"; @@ -1095,12 +1111,13 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - /* If a root ID is specified, ignore everything but the root id */ - if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) + if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) { + log_debug("Partition UUID '%s' does not match expected UUID '%s' derived from root verity hash, ignoring.", + SD_ID128_TO_UUID_STRING(id), + SD_ID128_TO_UUID_STRING(root_uuid)); continue; + } rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); @@ -1110,20 +1127,15 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - m->has_verity = true; - /* If no verity configuration is specified, then don't do verity */ - if (!verity) - continue; - if (verity->designator >= 0 && verity->designator != PARTITION_ROOT) - continue; - /* If root hash is specified, then ignore everything but the root id */ - if (!sd_id128_is_null(root_verity_uuid) && !sd_id128_equal(root_verity_uuid, id)) + if (!sd_id128_is_null(root_verity_uuid) && !sd_id128_equal(root_verity_uuid, id)) { + log_debug("Partition UUID '%s' does not match expected UUID '%s' derived from root verity hash, ignoring.", + SD_ID128_TO_UUID_STRING(id), + SD_ID128_TO_UUID_STRING(root_verity_uuid)); continue; + } fstype = "DM_verity_hash"; rw = false; @@ -1133,16 +1145,7 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - m->has_verity_sig = true; - - if (!verity) - continue; - if (verity->designator >= 0 && verity->designator != PARTITION_ROOT) - continue; - fstype = "verity_hash_signature"; rw = false; @@ -1151,12 +1154,13 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - /* If a usr ID is specified, ignore everything but the usr id */ - if (!sd_id128_is_null(usr_uuid) && !sd_id128_equal(usr_uuid, id)) + if (!sd_id128_is_null(usr_uuid) && !sd_id128_equal(usr_uuid, id)) { + log_debug("Partition UUID '%s' does not match expected UUID '%s' derived from usr verity hash, ignoring.", + SD_ID128_TO_UUID_STRING(id), + SD_ID128_TO_UUID_STRING(usr_uuid)); continue; + } rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); @@ -1166,19 +1170,15 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - m->has_verity = true; - if (!verity) - continue; - if (verity->designator >= 0 && verity->designator != PARTITION_USR) - continue; - /* If usr hash is specified, then ignore everything but the usr id */ - if (!sd_id128_is_null(usr_verity_uuid) && !sd_id128_equal(usr_verity_uuid, id)) + if (!sd_id128_is_null(usr_verity_uuid) && !sd_id128_equal(usr_verity_uuid, id)) { + log_debug("Partition UUID '%s' does not match expected UUID '%s' derived from usr verity hash, ignoring.", + SD_ID128_TO_UUID_STRING(id), + SD_ID128_TO_UUID_STRING(usr_uuid)); continue; + } fstype = "DM_verity_hash"; rw = false; @@ -1188,16 +1188,7 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - m->has_verity_sig = true; - - if (!verity) - continue; - if (verity->designator >= 0 && verity->designator != PARTITION_USR) - continue; - fstype = "verity_hash_signature"; rw = false; @@ -1205,9 +1196,6 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - /* Note: we don't set fstype = "swap" here, because we still need to probe if * it might be encrypted (i.e. fstype "crypt_LUKS") or unencrypted * (i.e. fstype "swap"), and the only way to figure that out is via fstype @@ -1222,9 +1210,6 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - if (generic_node) multiple_generic = true; else { @@ -1240,9 +1225,6 @@ static int dissect_image( check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); - if (pflags & SD_GPT_FLAG_NO_AUTO) - continue; - if (!FLAGS_SET(flags, DISSECT_IMAGE_RELAX_VAR_CHECK)) { sd_id128_t var_uuid; @@ -1446,12 +1428,12 @@ static int dissect_image( m->partitions[PARTITION_ROOT_VERITY_SIG].found)) return log_debug_errno( SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Found root verity hash partition without matching root data partition"); + "Found root verity hash partition without matching root data partition."); /* Hmm, we found a signature partition but no Verity data? Something is off. */ if (m->partitions[PARTITION_ROOT_VERITY_SIG].found && !m->partitions[PARTITION_ROOT_VERITY].found) return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Found root verity signature partition without matching root verity hash partition"); + "Found root verity signature partition without matching root verity hash partition."); /* as above */ if (!m->partitions[PARTITION_USR].found && @@ -1459,12 +1441,12 @@ static int dissect_image( m->partitions[PARTITION_USR_VERITY_SIG].found)) return log_debug_errno( SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Found usr verity hash partition without matching usr data partition"); + "Found usr verity hash partition without matching usr data partition."); /* as above */ if (m->partitions[PARTITION_USR_VERITY_SIG].found && !m->partitions[PARTITION_USR_VERITY].found) return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Found usr verity signature partition without matching usr verity hash partition"); + "Found usr verity signature partition without matching usr verity hash partition."); /* If root and /usr are combined then insist that the architecture matches */ if (m->partitions[PARTITION_ROOT].found && @@ -1473,7 +1455,7 @@ static int dissect_image( m->partitions[PARTITION_USR].architecture >= 0 && m->partitions[PARTITION_ROOT].architecture != m->partitions[PARTITION_USR].architecture)) return log_debug_errno(SYNTHETIC_ERRNO(EREMOTE), - "Found root and usr partitions with different architectures (%s vs %s)", + "Found root and usr partitions with different architectures (%s vs %s).", architecture_to_string(m->partitions[PARTITION_ROOT].architecture), architecture_to_string(m->partitions[PARTITION_USR].architecture)); @@ -1543,17 +1525,17 @@ static int dissect_image( /* Check if we have a root fs if we are told to do check. /usr alone is fine too, but only if appropriate flag for that is set too */ if (FLAGS_SET(flags, DISSECT_IMAGE_REQUIRE_ROOT) && !(m->partitions[PARTITION_ROOT].found || (m->partitions[PARTITION_USR].found && FLAGS_SET(flags, DISSECT_IMAGE_USR_NO_ROOT)))) - return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Root or usr partition requested but found neither"); + return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Root or usr partition requested but found neither."); if (m->partitions[PARTITION_ROOT_VERITY].found) { /* We only support one verity partition per image, i.e. can't do for both /usr and root fs */ if (m->partitions[PARTITION_USR_VERITY].found) - return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ), "Found both root and usr verity enabled partitions which is not supported"); + return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ), "Found both root and usr verity enabled partitions which is not supported."); /* We don't support verity enabled root with a split out /usr. Neither with nor without * verity there. (Note that we do support verity-less root with verity-full /usr, though.) */ if (m->partitions[PARTITION_USR].found) - return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), "Found verity enabled root partition with split usr partition which is not supported"); + return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), "Found verity enabled root partition with split usr partition which is not supported."); } if (verity) { @@ -1561,7 +1543,7 @@ static int dissect_image( if (verity->designator >= 0 && !m->partitions[verity->designator].found) return log_debug_errno( SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Explicit %s verity designator was specified but did not find %s partition", + "Explicit %s verity designator was specified but did not find %s partition.", partition_designator_to_string(verity->designator), partition_designator_to_string(verity->designator)); @@ -1573,12 +1555,12 @@ static int dissect_image( if (!m->partitions[PARTITION_ROOT].found) return log_debug_errno( SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Verity enabled root partition was requested but did not find a root data partition"); + "Verity enabled root partition was requested but did not find a root data partition."); if (!m->partitions[PARTITION_ROOT_VERITY].found) return log_debug_errno( SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Verity enabled root partition was requested but did not find a root verity hash partition"); + "Verity enabled root partition was requested but did not find a root verity hash partition."); /* If we found a verity setup, then the root partition is necessarily read-only. */ m->partitions[PARTITION_ROOT].rw = false; @@ -1588,12 +1570,12 @@ static int dissect_image( if (!m->partitions[PARTITION_USR].found) return log_debug_errno( SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Verity enabled usr partition was requested but did not find a usr data partition"); + "Verity enabled usr partition was requested but did not find a usr data partition."); if (!m->partitions[PARTITION_USR_VERITY].found) return log_debug_errno( SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "Verity enabled usr partition was requested but did not find a usr verity hash partition"); + "Verity enabled usr partition was requested but did not find a usr verity hash partition."); m->partitions[PARTITION_USR].rw = false; @@ -1619,7 +1601,7 @@ static int dissect_image( if (m->partitions[di].found) { found_flags = PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_UNPROTECTED|PARTITION_POLICY_UNUSED; - PartitionDesignator vi = partition_verity_of(di); + PartitionDesignator vi = partition_verity_hash_of(di); if (vi >= 0 && m->partitions[vi].found) { found_flags |= PARTITION_POLICY_VERITY; @@ -1633,7 +1615,7 @@ static int dissect_image( if (DEBUG_LOGGING) { _cleanup_free_ char *s = NULL; (void) partition_policy_flags_to_string(found_flags, /* simplify= */ false, &s); - log_debug("Found for designator %s: %s", partition_designator_to_string(di), strna(s)); + log_debug("Found for designator %s: %s.", partition_designator_to_string(di), strna(s)); } r = image_policy_check_protection(policy, di, found_flags); @@ -3119,7 +3101,7 @@ int dissected_image_decrypt( if (r < 0) return r; - k = partition_verity_of(i); + k = partition_verity_hash_of(i); if (k >= 0) { flags |= getenv_bool("SYSTEMD_VERITY_SHARING") != 0 ? DISSECT_IMAGE_VERITY_SHARE : 0; @@ -3608,7 +3590,7 @@ int dissected_image_load_verity_sig_partition( if (!m->partitions[dd].found) return 0; - PartitionDesignator dv = partition_verity_of(dd); + PartitionDesignator dv = partition_verity_hash_of(dd); assert(dv >= 0); if (!m->partitions[dv].found) return 0; @@ -3734,7 +3716,7 @@ int dissected_image_guess_verity_roothash( if (!d->found) return 0; - PartitionDesignator dv = partition_verity_of(dd); + PartitionDesignator dv = partition_verity_hash_of(dd); assert(dv >= 0); DissectedPartition *p = m->partitions + dv; @@ -4178,7 +4160,7 @@ bool dissected_image_verity_candidate(const DissectedImage *image, PartitionDesi if (image->single_file_system) return partition_designator == PARTITION_ROOT && image->has_verity; - return partition_verity_of(partition_designator) >= 0; + return partition_verity_hash_of(partition_designator) >= 0; } bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignator partition_designator) { @@ -4195,7 +4177,7 @@ bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignat if (image->single_file_system) return partition_designator == PARTITION_ROOT; - k = partition_verity_of(partition_designator); + k = partition_verity_hash_of(partition_designator); return k >= 0 && image->partitions[k].found; } diff --git a/src/shared/gpt.c b/src/shared/gpt.c index 9bb66b7c40..b9b967e806 100644 --- a/src/shared/gpt.c +++ b/src/shared/gpt.c @@ -31,7 +31,7 @@ bool partition_designator_is_versioned(PartitionDesignator d) { PARTITION_USR_VERITY_SIG); } -PartitionDesignator partition_verity_of(PartitionDesignator p) { +PartitionDesignator partition_verity_hash_of(PartitionDesignator p) { switch (p) { case PARTITION_ROOT: @@ -59,7 +59,7 @@ PartitionDesignator partition_verity_sig_of(PartitionDesignator p) { } } -PartitionDesignator partition_verity_to_data(PartitionDesignator d) { +PartitionDesignator partition_verity_hash_to_data(PartitionDesignator d) { switch (d) { case PARTITION_ROOT_VERITY: @@ -87,6 +87,14 @@ PartitionDesignator partition_verity_sig_to_data(PartitionDesignator d) { } } +PartitionDesignator partition_verity_to_data(PartitionDesignator d) { + PartitionDesignator e = partition_verity_hash_to_data(d); + if (e >= 0) + return e; + + return partition_verity_sig_to_data(d); +} + static const char *const partition_designator_table[_PARTITION_DESIGNATOR_MAX] = { [PARTITION_ROOT] = "root", [PARTITION_USR] = "usr", diff --git a/src/shared/gpt.h b/src/shared/gpt.h index 3261d0001b..0103ac2f4a 100644 --- a/src/shared/gpt.h +++ b/src/shared/gpt.h @@ -31,19 +31,24 @@ typedef enum PartitionDesignator { bool partition_designator_is_versioned(PartitionDesignator d) _const_; -PartitionDesignator partition_verity_of(PartitionDesignator p) _const_; +PartitionDesignator partition_verity_hash_of(PartitionDesignator p) _const_; PartitionDesignator partition_verity_sig_of(PartitionDesignator p) _const_; -PartitionDesignator partition_verity_to_data(PartitionDesignator d) _const_; +PartitionDesignator partition_verity_hash_to_data(PartitionDesignator d) _const_; PartitionDesignator partition_verity_sig_to_data(PartitionDesignator d) _const_; +PartitionDesignator partition_verity_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_hash(PartitionDesignator d) { + return partition_verity_hash_to_data(d) >= 0; } static inline bool partition_designator_is_verity_sig(PartitionDesignator d) { return partition_verity_sig_to_data(d) >= 0; } +static inline bool partition_designator_is_verity(PartitionDesignator d) { + return partition_verity_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/shared/image-policy.c b/src/shared/image-policy.c index 16fc91e1fe..7a248318eb 100644 --- a/src/shared/image-policy.c +++ b/src/shared/image-policy.c @@ -76,12 +76,12 @@ static PartitionPolicyFlags partition_policy_normalized_flags(const PartitionPol /* If this is a verity or verity signature designator, then mask off all protection bits, this after * all needs no protection, because it *is* the protection */ - if (partition_verity_to_data(policy->designator) >= 0 || + if (partition_verity_hash_to_data(policy->designator) >= 0 || partition_verity_sig_to_data(policy->designator) >= 0) flags &= ~(PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_ENCRYPTED); /* if this designator has no verity concept, then mask off verity protection flags */ - if (partition_verity_of(policy->designator) < 0) + if (partition_verity_hash_of(policy->designator) < 0) flags &= ~(PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED); /* If the partition must be absent, then the gpt flags don't matter */ @@ -110,7 +110,7 @@ PartitionPolicyFlags image_policy_get(const ImagePolicy *policy, PartitionDesign /* Hmm, so this didn't work, then let's see if we can derive some policy from the underlying data * partition in case of verity/signature partitions */ - data_designator = partition_verity_to_data(designator); + data_designator = partition_verity_hash_to_data(designator); if (data_designator >= 0) { PartitionPolicyFlags data_flags; diff --git a/src/test/test-gpt.c b/src/test/test-gpt.c index 2c793181d9..6772d46ef6 100644 --- a/src/test/test-gpt.c +++ b/src/test/test-gpt.c @@ -48,17 +48,20 @@ TEST(verity_mappings) { for (PartitionDesignator p = 0; p < _PARTITION_DESIGNATOR_MAX; p++) { PartitionDesignator q; - q = partition_verity_of(p); - assert_se(q < 0 || partition_verity_to_data(q) == p); + q = partition_verity_hash_of(p); + assert_se(q < 0 || partition_verity_hash_to_data(q) == p); q = partition_verity_sig_of(p); assert_se(q < 0 || partition_verity_sig_to_data(q) == p); - q = partition_verity_to_data(p); - assert_se(q < 0 || partition_verity_of(q) == p); + q = partition_verity_hash_to_data(p); + assert_se(q < 0 || partition_verity_hash_of(q) == p); q = partition_verity_sig_to_data(p); assert_se(q < 0 || partition_verity_sig_of(q) == p); + + q = partition_verity_to_data(p); + assert_se(q < 0 || partition_verity_hash_of(q) == p || partition_verity_sig_of(q) == p); } } diff --git a/src/udev/udev-builtin-dissect_image.c b/src/udev/udev-builtin-dissect_image.c index 444b0fce37..32aea19a6f 100644 --- a/src/udev/udev-builtin-dissect_image.c +++ b/src/udev/udev-builtin-dissect_image.c @@ -265,7 +265,7 @@ static int verb_probe(UdevEvent *event, sd_device *dev) { } /* Indicate whether this partition has verity protection */ - PartitionDesignator dv = partition_verity_of(d); + PartitionDesignator dv = partition_verity_hash_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;