From: Lennart Poettering Date: Thu, 6 Mar 2025 08:33:53 +0000 (+0100) Subject: image-policy: add image_policy_ignore_designators() helper X-Git-Tag: v258-rc1~1168^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e706cadce58fac235306b858684348eb846b697a;p=thirdparty%2Fsystemd.git image-policy: add image_policy_ignore_designators() helper This new helper patches a provide image policy, setting the policy for specified designators to "ignore". This is useful for contexts where we only want to mount some subset of the available partitions, and hence don't care about the parts of the policy that cover the others. Specifically this is useful in systemd-gpt-auto-generator, which runs at a moment the root file system is already established, and hence the policy for the root file system can be ignored, the facts are already established. --- diff --git a/src/shared/image-policy.c b/src/shared/image-policy.c index 1fb24138fb4..e08fbba9664 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 a1a6afa345b..f61f55fd60a 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 12fc10acf0d..7d29e3d12ee 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);