diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index c6727523f0..8a49948780 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -485,11 +485,7 @@ static int add_partition_xbootldr(DissectedPartition *p) { int r; assert(p); - - if (in_initrd()) { - log_debug("In initrd, ignoring the XBOOTLDR partition."); - return 0; - } + assert(!in_initrd()); r = path_is_busy("/boot"); if (r < 0) @@ -526,11 +522,7 @@ static int add_partition_esp(DissectedPartition *p, bool has_xbootldr) { int r; assert(p); - - if (in_initrd()) { - log_debug("In initrd, ignoring the ESP."); - return 0; - } + assert(!in_initrd()); /* Check if there's an existing fstab entry for ESP. If so, we just skip the gpt-auto logic. */ r = fstab_has_node(p->node); @@ -834,6 +826,15 @@ static int enumerate_partitions(dev_t devnum) { _cleanup_free_ char *devname = NULL; int r; + static const PartitionDesignator ignore_designators[] = { + PARTITION_ROOT, + PARTITION_ROOT_VERITY, + PARTITION_ROOT_VERITY_SIG, + PARTITION_USR, + PARTITION_USR_VERITY, + PARTITION_USR_VERITY_SIG, + }; + assert(!in_initrd()); /* Run on the final root fs (not in the initrd), to mount auxiliary partitions, and hook in rw @@ -849,6 +850,14 @@ static int enumerate_partitions(dev_t devnum) { return log_debug_errno(r, "Failed to get device node of " DEVNUM_FORMAT_STR ": %m", DEVNUM_FORMAT_VAL(devnum)); + _cleanup_(image_policy_freep) ImagePolicy *image_policy = NULL; + r = image_policy_ignore_designators( + arg_image_policy ?: &image_policy_host, + ignore_designators, ELEMENTSOF(ignore_designators), + &image_policy); + if (r < 0) + return log_debug_errno(r, "Failed to mark root/usr designators as ignore in image policy: %m"); + /* Let's take a LOCK_SH lock on the block device, in case udevd is already running. If we don't take * the lock, udevd might end up issuing BLKRRPART in the middle, and we don't want that, since that * might remove all partitions while we are operating on them. */ @@ -860,7 +869,7 @@ static int enumerate_partitions(dev_t devnum) { loop, /* verity= */ NULL, /* mount_options= */ NULL, - arg_image_policy ?: &image_policy_host, + image_policy, DISSECT_IMAGE_GPT_ONLY| DISSECT_IMAGE_USR_NO_ROOT| DISSECT_IMAGE_DISKSEQ_DEVNODE| @@ -908,6 +917,9 @@ static int add_mounts(void) { dev_t devno; int r; + if (in_initrd()) + return 0; + r = blockdev_get_root(LOG_ERR, &devno); if (r < 0) return r; @@ -1011,10 +1023,9 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) return 0; } - r = add_root_mount(); - - if (!in_initrd()) - RET_GATHER(r, add_mounts()); + r = 0; + RET_GATHER(r, add_root_mount()); + RET_GATHER(r, add_mounts()); return r; } diff --git a/src/shared/image-policy.c b/src/shared/image-policy.c index 1fb24138fb..e08fbba966 100644 --- a/src/shared/image-policy.c +++ b/src/shared/image-policy.c @@ -774,6 +774,56 @@ int image_policy_intersect(const ImagePolicy *a, const ImagePolicy *b, ImagePoli return 0; } +int image_policy_ignore_designators(const ImagePolicy *p, const PartitionDesignator table[], size_t n_table, ImagePolicy **ret) { + assert(p); + assert(table || n_table == 0); + assert(ret); + + /* Patches the specified image policy, replacing the policy for the specified designators by an + * "ignore" policy. Returns a patched copy. This is useful in context where only some of the + * available partitions shall be mounted, and hence the policy for the others really doesn't + * matter. */ + + _cleanup_(image_policy_freep) ImagePolicy *np = image_policy_new(_PARTITION_DESIGNATOR_MAX); + if (!np) + return -ENOMEM; + + FOREACH_ARRAY(t, table, n_table) { + assert(*t >= 0); + assert(*t < _PARTITION_DESIGNATOR_MAX); + + if (image_policy_bsearch(np, *t)) + continue; + + /* Insert an ignore policy for this entry, and sort it to the right place, so that image_policy_bsearch() can work */ + np->policies[np->n_policies++] = (PartitionPolicy) { + .designator = *t, + .flags = PARTITION_POLICY_IGNORE, + }; + typesafe_qsort(np->policies, np->n_policies, partition_policy_compare); + } + + FOREACH_ARRAY(i, p->policies, p->n_policies) { + + if (image_policy_bsearch(np, i->designator)) + continue; + + /* Copy the policy entry from the old image policy, and sort it to the right place, so that image_policy_bsearch() can work */ + np->policies[np->n_policies++] = *i; + typesafe_qsort(np->policies, np->n_policies, partition_policy_compare); + } + + np->default_flags = p->default_flags; + + /* Return unused space to libc */ + ImagePolicy *t = realloc(np, offsetof(ImagePolicy, policies) + sizeof(PartitionPolicy) * np->n_policies); + if (t) + np = t; + + *ret = TAKE_PTR(np); + return 0; +} + const ImagePolicy image_policy_allow = { /* Allow policy */ .n_policies = 0, diff --git a/src/shared/image-policy.h b/src/shared/image-policy.h index a1a6afa345..f61f55fd60 100644 --- a/src/shared/image-policy.h +++ b/src/shared/image-policy.h @@ -106,3 +106,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(ImagePolicy*, image_policy_free); CONFIG_PARSER_PROTOTYPE(config_parse_image_policy); int parse_image_policy_argument(const char *s, ImagePolicy **policy); + +int image_policy_ignore_designators(const ImagePolicy *p, const PartitionDesignator table[], size_t n_table, ImagePolicy **ret); diff --git a/src/test/test-image-policy.c b/src/test/test-image-policy.c index 12fc10acf0..7d29e3d12e 100644 --- a/src/test/test-image-policy.c +++ b/src/test/test-image-policy.c @@ -162,4 +162,31 @@ TEST(image_policy_intersect) { test_policy_intersect_one("root=open", "=verity+ignore", "root=verity+ignore:=ignore"); } +static void test_policy_ignore_designators_one(const char *a, const PartitionDesignator array[], size_t n, const char *b) { + _cleanup_(image_policy_freep) ImagePolicy *x = NULL, *y = NULL, *t = NULL; + + ASSERT_OK(image_policy_from_string(a, &x)); + ASSERT_OK(image_policy_from_string(b, &y)); + + _cleanup_free_ char *s1 = NULL, *s2 = NULL, *s3 = NULL; + ASSERT_OK(image_policy_to_string(x, true, &s1)); + ASSERT_OK(image_policy_to_string(y, true, &s2)); + + ASSERT_OK(image_policy_ignore_designators(x, array, n, &t)); + + ASSERT_OK(image_policy_to_string(t, true, &s3)); + + log_info("%s → %s vs. %s", s1, s2, s3); + + ASSERT_TRUE(image_policy_equivalent(t, y)); +} + +TEST(image_policy_ignore_designators) { + test_policy_ignore_designators_one("-", NULL, 0, "-"); + test_policy_ignore_designators_one("-", ((const PartitionDesignator[]) { PARTITION_ROOT }), 1, "-"); + test_policy_ignore_designators_one("*", ((const PartitionDesignator[]) { PARTITION_ROOT }), 1, "root=ignore:=open"); + test_policy_ignore_designators_one("*", ((const PartitionDesignator[]) { PARTITION_ROOT, PARTITION_USR }), 2, "root=ignore:usr=ignore:=open"); + test_policy_ignore_designators_one("~", ((const PartitionDesignator[]) { PARTITION_VAR, PARTITION_ESP, PARTITION_VAR }), 2, "var=ignore:esp=ignore:=absent"); +} + DEFINE_TEST_MAIN(LOG_INFO);