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.
This commit is contained in:
Lennart Poettering
2025-03-06 09:33:53 +01:00
parent c0af4859d0
commit e706cadce5
3 changed files with 79 additions and 0 deletions

View 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,

View 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);

View 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);