]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
image-policy: add image_policy_ignore_designators() helper
authorLennart Poettering <lennart@poettering.net>
Thu, 6 Mar 2025 08:33:53 +0000 (09:33 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 6 Mar 2025 08:41:46 +0000 (09:41 +0100)
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.

src/shared/image-policy.c
src/shared/image-policy.h
src/test/test-image-policy.c

index 1fb24138fb4abf5bef4d7ab5c6b0cd479906e9fa..e08fbba96648eac774527677b9b0413579e3db0d 100644 (file)
@@ -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,
index a1a6afa345b861cce582af5a13206987c0c5f465..f61f55fd60a4c93911b5586d59c1dd7db5105e23 100644 (file)
@@ -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);
index 12fc10acf0d31d674eeb930b1ef107bae8abf3fe..7d29e3d12ee980a3590d89b02b2cdabf1845afd0 100644 (file)
@@ -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);