mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
generators: hook in validatefs on gpt-auto and fstab generator mounts
Let's turn on validatefs automatically for all auto-discovered partitions. Let's add an x-systemd.validatefs option to optionally turn this on for fstab listed file systems.
This commit is contained in:
@@ -281,6 +281,10 @@
|
||||
automatically measured into PCR 15 on activation, via
|
||||
<citerefentry><refentrytitle>systemd-pcrfs@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>Mount constraint metadata contained in the file systems is validated by pulling in
|
||||
<citerefentry><refentrytitle>systemd-validatefs@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
for generated mounts.</para>
|
||||
|
||||
<para><filename>systemd-gpt-auto-generator</filename> implements
|
||||
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
||||
</refsect1>
|
||||
@@ -375,6 +379,7 @@
|
||||
<member><citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-pcrfs@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-validatefs@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
|
||||
<member><citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
|
||||
|
||||
@@ -58,6 +58,14 @@
|
||||
GPT partition type UUID formatted as string. It is compared with the partition type UUID of the
|
||||
partition this file system is located on, and if different the validation will fail.</para></listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>The <filename>systemd-validatefs@.service</filename> unit is automatically pulled into the initial
|
||||
transaction by
|
||||
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
for all file systems it discovers and generates mounts
|
||||
for. <citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
will do this for all mounts with the <option>x-systemd.validatefs</option> mount option in
|
||||
<filename>/etc/fstab</filename>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@@ -432,6 +432,22 @@
|
||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>x-systemd.validatefs</option></term>
|
||||
|
||||
<listitem><para>Validates mount constraint metadata of the mounted file system after mounting
|
||||
it. This ensures the
|
||||
<citerefentry><refentrytitle>systemd-validatefs@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
service is pulled in by the mount unit.</para>
|
||||
|
||||
<para>Note that this option can only be used in <filename>/etc/fstab</filename>, and will be ignored
|
||||
when part of the <varname>Options=</varname> setting in a unit file. It is also implied for all
|
||||
partitions discovered by
|
||||
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>x-systemd.rw-only</option></term>
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
#define SPECIAL_GROWFS_ROOT_SERVICE "systemd-growfs-root.service"
|
||||
#define SPECIAL_PCRFS_SERVICE "systemd-pcrfs@.service"
|
||||
#define SPECIAL_PCRFS_ROOT_SERVICE "systemd-pcrfs-root.service"
|
||||
#define SPECIAL_VALIDATEFS_SERVICE "systemd-validatefs@.service"
|
||||
#define SPECIAL_HIBERNATE_RESUME_SERVICE "systemd-hibernate-resume.service"
|
||||
|
||||
/* Services systemd relies on */
|
||||
|
||||
@@ -39,14 +39,15 @@
|
||||
#include "volatile-util.h"
|
||||
|
||||
typedef enum MountPointFlags {
|
||||
MOUNT_NOAUTO = 1 << 0,
|
||||
MOUNT_NOFAIL = 1 << 1,
|
||||
MOUNT_AUTOMOUNT = 1 << 2,
|
||||
MOUNT_MAKEFS = 1 << 3,
|
||||
MOUNT_GROWFS = 1 << 4,
|
||||
MOUNT_RW_ONLY = 1 << 5,
|
||||
MOUNT_PCRFS = 1 << 6,
|
||||
MOUNT_QUOTA = 1 << 7,
|
||||
MOUNT_NOAUTO = 1 << 0,
|
||||
MOUNT_NOFAIL = 1 << 1,
|
||||
MOUNT_AUTOMOUNT = 1 << 2,
|
||||
MOUNT_MAKEFS = 1 << 3,
|
||||
MOUNT_GROWFS = 1 << 4,
|
||||
MOUNT_RW_ONLY = 1 << 5,
|
||||
MOUNT_PCRFS = 1 << 6,
|
||||
MOUNT_QUOTA = 1 << 7,
|
||||
MOUNT_VALIDATEFS = 1 << 8,
|
||||
} MountPointFlags;
|
||||
|
||||
typedef struct Mount {
|
||||
@@ -249,9 +250,10 @@ static int add_swap(
|
||||
return true;
|
||||
}
|
||||
|
||||
log_debug("Found swap entry what=%s makefs=%s growfs=%s pcrfs=%s noauto=%s nofail=%s",
|
||||
log_debug("Found swap entry what=%s makefs=%s growfs=%s pcrfs=%s validatefs=%s noauto=%s nofail=%s",
|
||||
what,
|
||||
yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS), yes_no(flags & MOUNT_PCRFS),
|
||||
yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS),
|
||||
yes_no(flags & MOUNT_PCRFS), yes_no(flags & MOUNT_VALIDATEFS),
|
||||
yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL));
|
||||
|
||||
r = unit_name_from_path(what, ".swap", &name);
|
||||
@@ -304,6 +306,8 @@ static int add_swap(
|
||||
log_warning("%s: growing swap devices is currently unsupported.", what);
|
||||
if (flags & MOUNT_PCRFS)
|
||||
log_warning("%s: measuring swap devices is currently unsupported.", what);
|
||||
if (flags & MOUNT_VALIDATEFS)
|
||||
log_warning("%s: validating swap devices is currently unsupported.", what);
|
||||
|
||||
if (!(flags & MOUNT_NOAUTO)) {
|
||||
r = generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET,
|
||||
@@ -688,6 +692,12 @@ static int add_mount(
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & MOUNT_VALIDATEFS) {
|
||||
r = generator_hook_up_validatefs(dest, where, target_unit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (flags & MOUNT_QUOTA) {
|
||||
r = generator_hook_up_quotacheck(dest, what, where, target_unit, fstype);
|
||||
if (r < 0) {
|
||||
@@ -842,6 +852,8 @@ static MountPointFlags fstab_options_to_flags(const char *options, bool is_swap)
|
||||
flags |= MOUNT_GROWFS;
|
||||
if (fstab_test_option(options, "x-systemd.pcrfs\0"))
|
||||
flags |= MOUNT_PCRFS;
|
||||
if (fstab_test_option(options, "x-systemd.validatefs\0"))
|
||||
flags |= MOUNT_VALIDATEFS;
|
||||
if (fstab_test_option(options, "usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0" "prjquota\0"))
|
||||
flags |= MOUNT_QUOTA;
|
||||
if (fstab_test_yes_no_option(options, "noauto\0" "auto\0"))
|
||||
@@ -970,9 +982,10 @@ static int parse_fstab_one(
|
||||
free_and_replace(what, p);
|
||||
}
|
||||
|
||||
log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s pcrfs=%s noauto=%s nofail=%s",
|
||||
log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s pcrfs=%s validatefs=%s noauto=%s nofail=%s",
|
||||
what, where, strna(fstype),
|
||||
yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS), yes_no(flags & MOUNT_PCRFS),
|
||||
yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS),
|
||||
yes_no(flags & MOUNT_PCRFS), yes_no(flags & MOUNT_VALIDATEFS),
|
||||
yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL));
|
||||
|
||||
bool is_sysroot = in_initrd() && path_equal(where, "/sysroot");
|
||||
|
||||
@@ -38,6 +38,13 @@
|
||||
#include "unit-name.h"
|
||||
#include "virt.h"
|
||||
|
||||
typedef enum MountPointFlags {
|
||||
MOUNT_RW = 1 << 0,
|
||||
MOUNT_GROWFS = 1 << 1,
|
||||
MOUNT_MEASURE = 1 << 2,
|
||||
MOUNT_VALIDATEFS = 1 << 3,
|
||||
} MountPointFlags;
|
||||
|
||||
static const char *arg_dest = NULL;
|
||||
static bool arg_enabled = true;
|
||||
static GptAutoRoot arg_auto_root = _GPT_AUTO_ROOT_INVALID;
|
||||
@@ -57,9 +64,8 @@ static int add_cryptsetup(
|
||||
const char *id,
|
||||
const char *what,
|
||||
const char *mount_opts,
|
||||
bool rw,
|
||||
MountPointFlags flags,
|
||||
bool require,
|
||||
bool measure,
|
||||
char **ret_device) {
|
||||
|
||||
#if HAVE_LIBCRYPTSETUP
|
||||
@@ -97,7 +103,7 @@ static int add_cryptsetup(
|
||||
"After=%s\n",
|
||||
d, d);
|
||||
|
||||
if (!rw) {
|
||||
if (!FLAGS_SET(flags, MOUNT_RW)) {
|
||||
options = strdup("read-only");
|
||||
if (!options)
|
||||
return log_oom();
|
||||
@@ -109,7 +115,7 @@ static int add_cryptsetup(
|
||||
if (!strextend_with_separator(&options, ",", "tpm2-device=auto"))
|
||||
return log_oom();
|
||||
|
||||
if (measure) {
|
||||
if (FLAGS_SET(flags, MOUNT_MEASURE)) {
|
||||
/* We only measure the root volume key into PCR 15 if we are booted with sd-stub (i.e. in a
|
||||
* UKI), and sd-stub measured the UKI. We do this in order not to step into people's own PCR
|
||||
* assignment, under the assumption that people who are fine to use sd-stub with its PCR
|
||||
@@ -178,9 +184,7 @@ static int add_mount(
|
||||
const char *what,
|
||||
const char *where,
|
||||
const char *fstype,
|
||||
bool rw,
|
||||
bool growfs,
|
||||
bool measure,
|
||||
MountPointFlags flags,
|
||||
const char *options,
|
||||
const char *description,
|
||||
const char *post) {
|
||||
@@ -203,7 +207,7 @@ static int add_mount(
|
||||
if (streq_ptr(fstype, "crypto_LUKS")) {
|
||||
/* Mount options passed are determined by partition_pick_mount_options(), whose result
|
||||
* is known to not contain timeout options. */
|
||||
r = add_cryptsetup(id, what, /* mount_opts = */ NULL, rw, /* require= */ true, measure, &crypto_what);
|
||||
r = add_cryptsetup(id, what, /* mount_opts = */ NULL, flags, /* require= */ true, &crypto_what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -270,13 +274,19 @@ static int add_mount(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write unit %s: %m", unit);
|
||||
|
||||
if (growfs) {
|
||||
if (FLAGS_SET(flags, MOUNT_VALIDATEFS)) {
|
||||
r = generator_hook_up_validatefs(arg_dest, where, post);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, MOUNT_GROWFS)) {
|
||||
r = generator_hook_up_growfs(arg_dest, where, post);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (measure) {
|
||||
if (FLAGS_SET(flags, MOUNT_MEASURE)) {
|
||||
r = generator_hook_up_pcrfs(arg_dest, where, post);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -353,9 +363,10 @@ static int add_partition_mount(
|
||||
p->node,
|
||||
where,
|
||||
p->fstype,
|
||||
p->rw,
|
||||
p->growfs,
|
||||
/* measure= */ STR_IN_SET(id, "root", "var"), /* by default measure rootfs and /var, since they contain the "identity" of the system */
|
||||
(p->rw ? MOUNT_RW : 0) |
|
||||
MOUNT_VALIDATEFS |
|
||||
(p->growfs ? MOUNT_GROWFS : 0) |
|
||||
(STR_IN_SET(id, "root", "var") ? MOUNT_MEASURE : 0), /* by default measure rootfs and /var, since they contain the "identity" of the system */
|
||||
options,
|
||||
description,
|
||||
SPECIAL_LOCAL_FS_TARGET);
|
||||
@@ -383,7 +394,7 @@ static int add_partition_swap(DissectedPartition *p) {
|
||||
}
|
||||
|
||||
if (streq_ptr(p->fstype, "crypto_LUKS")) {
|
||||
r = add_cryptsetup("swap", p->node, /* mount_opts = */ NULL, /* rw= */ true, /* require= */ true, /* measure= */ false, &crypto_what);
|
||||
r = add_cryptsetup("swap", p->node, /* mount_opts = */ NULL, MOUNT_RW, /* require= */ true, &crypto_what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
what = crypto_what;
|
||||
@@ -427,8 +438,7 @@ static int add_automount(
|
||||
const char *what,
|
||||
const char *where,
|
||||
const char *fstype,
|
||||
bool rw,
|
||||
bool growfs,
|
||||
MountPointFlags flags,
|
||||
const char *options,
|
||||
const char *description,
|
||||
usec_t timeout) {
|
||||
@@ -445,12 +455,10 @@ static int add_automount(
|
||||
what,
|
||||
where,
|
||||
fstype,
|
||||
rw,
|
||||
growfs,
|
||||
/* measure= */ false,
|
||||
flags,
|
||||
options,
|
||||
description,
|
||||
NULL);
|
||||
/* post= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -508,8 +516,7 @@ static int add_partition_xbootldr(DissectedPartition *p) {
|
||||
p->node,
|
||||
"/boot",
|
||||
p->fstype,
|
||||
/* rw= */ true,
|
||||
/* growfs= */ false,
|
||||
MOUNT_RW,
|
||||
options,
|
||||
"Boot Loader Partition",
|
||||
LOADER_PARTITION_IDLE_USEC);
|
||||
@@ -571,8 +578,7 @@ static int add_partition_esp(DissectedPartition *p, bool has_xbootldr) {
|
||||
p->node,
|
||||
esp_path,
|
||||
p->fstype,
|
||||
/* rw= */ true,
|
||||
/* growfs= */ false,
|
||||
MOUNT_RW,
|
||||
options,
|
||||
"EFI System Partition Automount",
|
||||
LOADER_PARTITION_IDLE_USEC);
|
||||
@@ -665,7 +671,7 @@ static int add_root_cryptsetup(void) {
|
||||
bdev = "/dev/gpt-auto-root-luks-ignore-factory-reset";
|
||||
}
|
||||
|
||||
return add_cryptsetup("root", bdev, arg_root_options, /* rw= */ true, /* require= */ false, /* measure= */ true, NULL);
|
||||
return add_cryptsetup("root", bdev, arg_root_options, MOUNT_RW|MOUNT_MEASURE, /* require= */ false, NULL);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@@ -752,9 +758,9 @@ static int add_root_mount(void) {
|
||||
bdev,
|
||||
in_initrd() ? "/sysroot" : "/",
|
||||
arg_root_fstype,
|
||||
/* rw= */ arg_root_rw > 0,
|
||||
/* growfs= */ false,
|
||||
/* measure= */ true,
|
||||
(arg_root_rw > 0 ? MOUNT_RW : 0) |
|
||||
(in_initrd() ? MOUNT_VALIDATEFS : 0) |
|
||||
MOUNT_MEASURE,
|
||||
options,
|
||||
"Root Partition",
|
||||
in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
|
||||
|
||||
@@ -764,6 +764,43 @@ int generator_hook_up_pcrfs(
|
||||
return generator_add_symlink_full(dir, where_unit, "wants", pcrfs_unit_path, instance);
|
||||
}
|
||||
|
||||
int generator_hook_up_validatefs(
|
||||
const char *dir,
|
||||
const char *where,
|
||||
const char *target) {
|
||||
|
||||
_cleanup_free_ char *where_unit = NULL, *instance = NULL;
|
||||
const char *validatefs_unit, *validatefs_unit_path;
|
||||
int r;
|
||||
|
||||
assert(dir);
|
||||
assert(where);
|
||||
|
||||
/* never hook this in for the actual root fs, because it's too late then, we already are running from
|
||||
* the root fs, it makes no sense to validate it anymore */
|
||||
if (empty_or_root(where))
|
||||
return 0;
|
||||
|
||||
r = unit_name_from_path(where, ".mount", &where_unit);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to make unit name from path '%s': %m", where);
|
||||
|
||||
validatefs_unit = SPECIAL_VALIDATEFS_SERVICE;
|
||||
validatefs_unit_path = SYSTEM_DATA_UNIT_DIR "/" SPECIAL_VALIDATEFS_SERVICE;
|
||||
|
||||
r = unit_name_path_escape(where, &instance);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to escape path '%s': %m", where);
|
||||
|
||||
if (target) {
|
||||
r = generator_add_ordering(dir, target, "After", validatefs_unit, instance);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return generator_add_symlink_full(dir, where_unit, "wants", validatefs_unit_path, instance);
|
||||
}
|
||||
|
||||
int generator_hook_up_quotacheck(
|
||||
const char *dir,
|
||||
const char *what,
|
||||
|
||||
@@ -67,6 +67,10 @@ int generator_hook_up_pcrfs(
|
||||
const char *dir,
|
||||
const char *where,
|
||||
const char *target);
|
||||
int generator_hook_up_validatefs(
|
||||
const char *dir,
|
||||
const char *where,
|
||||
const char *target);
|
||||
int generator_hook_up_quotacheck(
|
||||
const char *dir,
|
||||
const char *what,
|
||||
|
||||
Reference in New Issue
Block a user