diff --git a/man/systemd.image-policy.xml b/man/systemd.image-policy.xml
index 6d91669ef1..3732d6e1ad 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: root , usr ,
home , srv , esp , xbootldr ,
@@ -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 aa7f744555..65f5450597 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 e917b03b06..44c807f6cb 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 30d319ed69..8023eb31ae 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 512df19078..01c0417900 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);