image-policy: add support for restricting to specific filesystems
This commit is contained in:
@@ -26,11 +26,11 @@
|
|||||||
<para>In systemd, whenever a disk image (DDI) implementing the <ulink
|
<para>In systemd, whenever a disk image (DDI) implementing the <ulink
|
||||||
url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">UAPI.2
|
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
|
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
|
partitions to mount and what kind of cryptographic protection to require, and which type of filesystem
|
||||||
policy is a string that contains per-partition-type rules, separated by colons
|
is allowed. Such a disk image dissection policy is a string that contains per-partition-type rules,
|
||||||
(<literal>:</literal>). The individual rules consist of a partition identifier, an equal sign
|
separated by colons (<literal>:</literal>). The individual rules consist of a partition identifier, an
|
||||||
(<literal>=</literal>), and one or more flags which may be set per partition. If multiple flags are
|
equal sign (<literal>=</literal>), and one or more flags which may be set per partition. If multiple
|
||||||
specified per partition they are separated by a plus sign (<literal>+</literal>).</para>
|
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>,
|
<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>,
|
<option>home</option>, <option>srv</option>, <option>esp</option>, <option>xbootldr</option>,
|
||||||
@@ -71,6 +71,46 @@
|
|||||||
image.</para></listitem>
|
image.</para></listitem>
|
||||||
</itemizedlist>
|
</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
|
<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
|
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
|
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.</para>
|
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>
|
<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>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
|
||||||
static int table_add_designator_line(Table *table, PartitionDesignator d, PartitionPolicyFlags f) {
|
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;
|
const char *color;
|
||||||
int r;
|
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)
|
if (partition_policy_flags_to_string(f & _PARTITION_POLICY_USE_MASK, /* simplify= */ true, &q) < 0)
|
||||||
return log_oom();
|
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() :
|
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)) ==
|
((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() :
|
(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)
|
if (r < 0)
|
||||||
return table_log_add_error(r);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +136,7 @@ int verb_image_policy(int argc, char *argv[], void *userdata) {
|
|||||||
ansi_highlight(), as_string_simplified, ansi_normal(),
|
ansi_highlight(), as_string_simplified, ansi_normal(),
|
||||||
ansi_grey(), as_string, 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)
|
if (!table)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,20 @@ static PartitionPolicyFlags policy_flag_from_string_one(const char *s) {
|
|||||||
return PARTITION_POLICY_GROWFS_ON;
|
return PARTITION_POLICY_GROWFS_ON;
|
||||||
if (streq(s, "growfs-off"))
|
if (streq(s, "growfs-off"))
|
||||||
return PARTITION_POLICY_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;
|
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) {
|
int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify, char **ret) {
|
||||||
_cleanup_free_ char *buf = NULL;
|
_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;
|
size_t m = 0;
|
||||||
|
|
||||||
assert(ret);
|
assert(ret);
|
||||||
@@ -449,6 +463,23 @@ int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify,
|
|||||||
l[m++] = "growfs-on";
|
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)
|
if (m == 0)
|
||||||
buf = strdup("-");
|
buf = strdup("-");
|
||||||
else {
|
else {
|
||||||
@@ -461,7 +492,7 @@ int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
*ret = TAKE_PTR(buf);
|
*ret = TAKE_PTR(buf);
|
||||||
return 0;
|
return (int) m;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool partition_policy_flags_extended_equal(PartitionPolicyFlags a, PartitionPolicyFlags b) {
|
static bool partition_policy_flags_extended_equal(PartitionPolicyFlags a, PartitionPolicyFlags b) {
|
||||||
|
|||||||
@@ -36,6 +36,19 @@ typedef enum PartitionPolicyFlags {
|
|||||||
|
|
||||||
_PARTITION_POLICY_MASK = _PARTITION_POLICY_USE_MASK|_PARTITION_POLICY_READ_ONLY_MASK|_PARTITION_POLICY_GROWFS_MASK,
|
_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_INVALID = -EINVAL,
|
||||||
_PARTITION_POLICY_FLAGS_ERRNO_MAX = -ERRNO_MAX, /* Ensure the whole errno range fits into this enum */
|
_PARTITION_POLICY_FLAGS_ERRNO_MAX = -ERRNO_MAX, /* Ensure the whole errno range fits into this enum */
|
||||||
} PartitionPolicyFlags;
|
} PartitionPolicyFlags;
|
||||||
|
|||||||
@@ -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("swap=open:root=signed+read-only-on+growfs-off:=absent");
|
||||||
test_policy_string("=-");
|
test_policy_string("=-");
|
||||||
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);
|
||||||
test_policy_equiv("-", image_policy_equiv_ignore);
|
test_policy_equiv("-", image_policy_equiv_ignore);
|
||||||
|
|||||||
Reference in New Issue
Block a user