gpt-auto: image policy fixes (#36629)
Let's make sure we can define a proper image policy on ParticleOS images.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user