<para>In systemd, whenever a disk image (DDI) implementing the <ulink
url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">UAPI.2
Discoverable Partitions Specification</ulink> 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
- (<literal>:</literal>). The individual rules consist of a partition identifier, an equal sign
- (<literal>=</literal>), 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 (<literal>+</literal>).</para>
+ 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 (<literal>:</literal>). The individual rules consist of a partition identifier, an
+ equal sign (<literal>=</literal>), 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 (<literal>+</literal>).</para>
<para>The partition identifiers currently defined are: <option>root</option>, <option>usr</option>,
<option>home</option>, <option>srv</option>, <option>esp</option>, <option>xbootldr</option>,
image.</para></listitem>
</itemizedlist>
+ <para>The following filesystem policy flags are defined that dictate which filesystem types are allowed
+ for which partition:</para>
+
+ <table>
+ <title>
+ Filesystems types supported by the policy
+ </title>
+
+ <tgroup cols='1'>
+ <thead>
+ <row>
+ <entry>Filesystem flag</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>btrfs</literal></entry>
+ </row>
+ <row>
+ <entry><literal>erofs</literal></entry>
+ </row>
+ <row>
+ <entry><literal>ext4</literal></entry>
+ </row>
+ <row>
+ <entry><literal>f2fs</literal></entry>
+ </row>
+ <row>
+ <entry><literal>squashfs</literal></entry>
+ </row>
+ <row>
+ <entry><literal>vfat</literal></entry>
+ </row>
+ <row>
+ <entry><literal>xfs</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<para>By setting a combination of the flags above, alternatives can be declared. For example the
combination <literal>unused+absent</literal> means: the partition may exist (in which case it shall not
be used) or may be absent. The combination of
does not have to be, and ignores swap partitions, and uses all other partitions if they are available, possibly with encryption.</para>
<programlisting>root=unprotected+encrypted:swap=absent+unused:=unprotected+encrypted+absent</programlisting>
+
+ <para>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.</para>
+
+ <programlisting>root=erofs+squashfs:swap=absent+unused:=unprotected+encrypted+absent</programlisting>
</refsect1>
<refsect1>
#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;
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() :
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;
}
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();
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;
}
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);
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 {
return -ENOMEM;
*ret = TAKE_PTR(buf);
- return 0;
+ return (int) m;
}
static bool partition_policy_flags_extended_equal(PartitionPolicyFlags a, PartitionPolicyFlags b) {
_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;
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);