From: Luca Boccassi Date: Wed, 3 Dec 2025 16:48:01 +0000 (+0000) Subject: image-policy: add support for restricting to specific filesystems X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d0cb79b8a9732d5b6468f48460472c726dd70324;p=thirdparty%2Fsystemd.git image-policy: add support for restricting to specific filesystems --- diff --git a/man/systemd.image-policy.xml b/man/systemd.image-policy.xml index 6d91669ef1b..3732d6e1ad6 100644 --- a/man/systemd.image-policy.xml +++ b/man/systemd.image-policy.xml @@ -26,11 +26,11 @@ In systemd, whenever a disk image (DDI) implementing the UAPI.2 Discoverable Partitions Specification is activated, a policy may be specified controlling which - partitions to mount and what kind of cryptographic protection to require. Such a disk image dissection - policy is a string that contains per-partition-type rules, separated by colons - (:). The individual rules consist of a partition identifier, an equal sign - (=), and one or more flags which may be set per partition. If multiple flags are - specified per partition they are separated by a plus sign (+). + partitions to mount and what kind of cryptographic protection to require, and which type of filesystem + is allowed. Such a disk image dissection policy is a string that contains per-partition-type rules, + separated by colons (:). The individual rules consist of a partition identifier, an + equal sign (=), and one or more flags which may be set per partition. If multiple + flags are specified per partition they are separated by a plus sign (+). The partition identifiers currently defined are: , , , , , , @@ -71,6 +71,46 @@ image. + The following filesystem policy flags are defined that dictate which filesystem types are allowed + for which partition: + + + + Filesystems types supported by the policy + + + + + + Filesystem flag + + + + + btrfs + + + erofs + + + ext4 + + + f2fs + + + squashfs + + + vfat + + + xfs + + + +
+ By setting a combination of the flags above, alternatives can be declared. For example the combination unused+absent means: the partition may exist (in which case it shall not be used) or may be absent. The combination of @@ -175,6 +215,11 @@ does not have to be, and ignores swap partitions, and uses all other partitions if they are available, possibly with encryption. root=unprotected+encrypted:swap=absent+unused:=unprotected+encrypted+absent + + The following image policy string dictates a single root partition that can only be erofs or squashfs, + and ignores swap partitions, and uses all other partitions if they are available, possibly with encryption. + + root=erofs+squashfs:swap=absent+unused:=unprotected+encrypted+absent diff --git a/src/analyze/analyze-image-policy.c b/src/analyze/analyze-image-policy.c index aa7f7445557..65f54505979 100644 --- a/src/analyze/analyze-image-policy.c +++ b/src/analyze/analyze-image-policy.c @@ -9,7 +9,7 @@ #include "string-util.h" static int table_add_designator_line(Table *table, PartitionDesignator d, PartitionPolicyFlags f) { - _cleanup_free_ char *q = NULL; + _cleanup_free_ char *q = NULL, *t = NULL; const char *color; int r; @@ -19,6 +19,9 @@ static int table_add_designator_line(Table *table, PartitionDesignator d, Partit if (partition_policy_flags_to_string(f & _PARTITION_POLICY_USE_MASK, /* simplify= */ true, &q) < 0) return log_oom(); + if (partition_policy_flags_to_string(f & _PARTITION_POLICY_FSTYPE_MASK, /* simplify= */ true, &t) < 0) + return log_oom(); + color = (f & _PARTITION_POLICY_USE_MASK) == PARTITION_POLICY_IGNORE ? ansi_grey() : ((f & (PARTITION_POLICY_UNPROTECTED|PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_ENCRYPTEDWITHINTEGRITY|PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_ABSENT)) == (PARTITION_POLICY_UNPROTECTED|PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_ENCRYPTEDWITHINTEGRITY|PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_ABSENT)) ? ansi_highlight_yellow() : @@ -72,6 +75,11 @@ static int table_add_designator_line(Table *table, PartitionDesignator d, Partit if (r < 0) return table_log_add_error(r); + r = table_add_many(table, + TABLE_STRING, isempty(t) ? "-" : t); + if (r < 0) + return table_log_add_error(r); + return 0; } @@ -128,7 +136,7 @@ int verb_image_policy(int argc, char *argv[], void *userdata) { ansi_highlight(), as_string_simplified, ansi_normal(), ansi_grey(), as_string, ansi_normal()); - table = table_new("partition", "mode", "read-only", "growfs"); + table = table_new("partition", "mode", "read-only", "growfs", "fstype"); if (!table) return log_oom(); diff --git a/src/shared/image-policy.c b/src/shared/image-policy.c index e917b03b066..44c807f6cbb 100644 --- a/src/shared/image-policy.c +++ b/src/shared/image-policy.c @@ -207,6 +207,20 @@ static PartitionPolicyFlags policy_flag_from_string_one(const char *s) { return PARTITION_POLICY_GROWFS_ON; if (streq(s, "growfs-off")) return PARTITION_POLICY_GROWFS_OFF; + if (streq(s, "btrfs")) + return PARTITION_POLICY_BTRFS; + if (streq(s, "erofs")) + return PARTITION_POLICY_EROFS; + if (streq(s, "ext4")) + return PARTITION_POLICY_EXT4; + if (streq(s, "f2fs")) + return PARTITION_POLICY_F2FS; + if (streq(s, "squashfs")) + return PARTITION_POLICY_SQUASHFS; + if (streq(s, "vfat")) + return PARTITION_POLICY_VFAT; + if (streq(s, "xfs")) + return PARTITION_POLICY_XFS; return _PARTITION_POLICY_FLAGS_INVALID; } @@ -389,7 +403,7 @@ int image_policy_from_string(const char *s, bool graceful, ImagePolicy **ret) { int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify, char **ret) { _cleanup_free_ char *buf = NULL; - const char *l[CONST_LOG2U(_PARTITION_POLICY_MASK + 1) + 1]; /* one string per known flag at most */ + const char *l[CONST_LOG2U(_PARTITION_POLICY_MASK + _PARTITION_POLICY_FSTYPE_MASK + 1) + 1]; /* one string per known flag at most */ size_t m = 0; assert(ret); @@ -449,6 +463,23 @@ int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify, l[m++] = "growfs-on"; } + /* These flags must translate to the literal fstype name of each filesystem, as accepted by + * `mount -t`. */ + if (flags & PARTITION_POLICY_BTRFS) + l[m++] = "btrfs"; + if (flags & PARTITION_POLICY_EROFS) + l[m++] = "erofs"; + if (flags & PARTITION_POLICY_EXT4) + l[m++] = "ext4"; + if (flags & PARTITION_POLICY_F2FS) + l[m++] = "f2fs"; + if (flags & PARTITION_POLICY_SQUASHFS) + l[m++] = "squashfs"; + if (flags & PARTITION_POLICY_VFAT) + l[m++] = "vfat"; + if (flags & PARTITION_POLICY_XFS) + l[m++] = "xfs"; + if (m == 0) buf = strdup("-"); else { @@ -461,7 +492,7 @@ int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify, return -ENOMEM; *ret = TAKE_PTR(buf); - return 0; + return (int) m; } static bool partition_policy_flags_extended_equal(PartitionPolicyFlags a, PartitionPolicyFlags b) { diff --git a/src/shared/image-policy.h b/src/shared/image-policy.h index 30d319ed698..8023eb31aeb 100644 --- a/src/shared/image-policy.h +++ b/src/shared/image-policy.h @@ -36,6 +36,19 @@ typedef enum PartitionPolicyFlags { _PARTITION_POLICY_MASK = _PARTITION_POLICY_USE_MASK|_PARTITION_POLICY_READ_ONLY_MASK|_PARTITION_POLICY_GROWFS_MASK, + /* Policies can impose filesystem type requirements on images. These flags translate to the literal + * fstype name of each filesystem. */ + PARTITION_POLICY_BTRFS = 1 << 11, + PARTITION_POLICY_EROFS = 1 << 12, + PARTITION_POLICY_EXT4 = 1 << 13, + PARTITION_POLICY_F2FS = 1 << 14, + PARTITION_POLICY_SQUASHFS = 1 << 15, + PARTITION_POLICY_VFAT = 1 << 16, + PARTITION_POLICY_XFS = 1 << 17, + _PARTITION_POLICY_FSTYPE_MASK = PARTITION_POLICY_BTRFS|PARTITION_POLICY_EROFS|PARTITION_POLICY_EXT4| + PARTITION_POLICY_F2FS|PARTITION_POLICY_SQUASHFS| + PARTITION_POLICY_VFAT|PARTITION_POLICY_XFS, + _PARTITION_POLICY_FLAGS_INVALID = -EINVAL, _PARTITION_POLICY_FLAGS_ERRNO_MAX = -ERRNO_MAX, /* Ensure the whole errno range fits into this enum */ } PartitionPolicyFlags; diff --git a/src/test/test-image-policy.c b/src/test/test-image-policy.c index 512df19078a..01c0417900f 100644 --- a/src/test/test-image-policy.c +++ b/src/test/test-image-policy.c @@ -92,6 +92,10 @@ TEST_RET(test_image_policy_to_string) { test_policy_string("swap=open:root=signed+read-only-on+growfs-off:=absent"); test_policy_string("=-"); test_policy_string("="); + test_policy_string("root=ext4+squashfs+verity"); + test_policy_string("usr=encrypted+erofs+read-only-off"); + test_policy_string("home=unprotected+btrfs"); + test_policy_string("=vfat+erofs"); test_policy_equiv("", image_policy_equiv_ignore); test_policy_equiv("-", image_policy_equiv_ignore);