]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
generators: optionally, measure file systems at boot
authorLennart Poettering <lennart@poettering.net>
Sun, 16 Oct 2022 21:25:04 +0000 (23:25 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 17 Jan 2023 08:42:16 +0000 (09:42 +0100)
If we use gpt-auto-generator, automatically measure root fs and /var.

Otherwise, add x-systemd.measure option to request this.

src/basic/special.h
src/fstab-generator/fstab-generator.c
src/gpt-auto-generator/gpt-auto-generator.c
src/shared/generator.c
src/shared/generator.h
units/meson.build
units/systemd-pcrfs-root.service.in [new file with mode: 0644]
units/systemd-pcrfs@.service.in [new file with mode: 0644]

index 9bb36c573298e116b58f3d11e88676f6a738a1f9..0e4342eb40daa55074041b921cff564379a24e52 100644 (file)
@@ -89,6 +89,8 @@
 #define SPECIAL_UDEVD_SERVICE "systemd-udevd.service"
 #define SPECIAL_GROWFS_SERVICE "systemd-growfs@.service"
 #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"
 
 /* Services systemd relies on */
 #define SPECIAL_DBUS_SERVICE "dbus.service"
index b0ea536eb29778ca7f1f4a770210cb7572e1e612..4b763bc247250e4dc0772949516e34903c6fb65f 100644 (file)
@@ -40,6 +40,7 @@ typedef enum MountPointFlags {
         MOUNT_MAKEFS    = 1 << 3,
         MOUNT_GROWFS    = 1 << 4,
         MOUNT_RW_ONLY   = 1 << 5,
+        MOUNT_PCRFS     = 1 << 6,
 } MountPointFlags;
 
 static bool arg_sysroot_check = false;
@@ -176,6 +177,8 @@ static int add_swap(
         if (flags & MOUNT_GROWFS)
                 /* TODO: swap devices must be wiped and recreated */
                 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_NOAUTO)) {
                 r = generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET,
@@ -525,6 +528,12 @@ static int add_mount(
                         return r;
         }
 
+        if (flags & MOUNT_PCRFS) {
+                r = generator_hook_up_pcrfs(dest, where, target_unit);
+                if (r < 0)
+                        return r;
+        }
+
         if (!FLAGS_SET(flags, MOUNT_AUTOMOUNT)) {
                 if (!FLAGS_SET(flags, MOUNT_NOAUTO) && strv_isempty(wanted_by) && strv_isempty(required_by)) {
                         r = generator_add_symlink(dest, target_unit,
@@ -658,7 +667,7 @@ static int parse_fstab(bool initrd) {
 
         while ((me = getmntent(f))) {
                 _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
-                bool makefs, growfs, noauto, nofail;
+                bool makefs, growfs, pcrfs, noauto, nofail;
                 MountPointFlags flags;
                 int k;
 
@@ -718,16 +727,18 @@ static int parse_fstab(bool initrd) {
 
                 makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0");
                 growfs = fstab_test_option(me->mnt_opts, "x-systemd.growfs\0");
+                pcrfs = fstab_test_option(me->mnt_opts, "x-systemd.pcrfs\0");
                 noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
                 nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
 
-                log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s noauto=%s nofail=%s",
+                log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s pcrfs=%s noauto=%s nofail=%s",
                           what, where, me->mnt_type,
-                          yes_no(makefs), yes_no(growfs),
+                          yes_no(makefs), yes_no(growfs), yes_no(pcrfs),
                           yes_no(noauto), yes_no(nofail));
 
                 flags = makefs * MOUNT_MAKEFS |
                         growfs * MOUNT_GROWFS |
+                        pcrfs * MOUNT_PCRFS |
                         noauto * MOUNT_NOAUTO |
                         nofail * MOUNT_NOFAIL;
 
@@ -911,7 +922,7 @@ static int add_sysroot_mount(void) {
                          fstype,
                          opts,
                          is_device_path(what) ? 1 : 0, /* passno */
-                         flags,                        /* makefs, growfs off, noauto off, nofail off, automount off */
+                         flags,                        /* makefs off, pcrfs off, noauto off, nofail off, automount off */
                          SPECIAL_INITRD_ROOT_FS_TARGET);
 }
 
index 1fc75865240d8ae166e73c1cc2eaff222ed98b68..63bb2a3cbb903ccba3dae8e83953161ad92ed006 100644 (file)
@@ -259,6 +259,12 @@ static int add_mount(
                         return r;
         }
 
+        if (measure) {
+                r = generator_hook_up_pcrfs(arg_dest, where, post);
+                if (r < 0)
+                        return r;
+        }
+
         if (post) {
                 r = generator_add_symlink(arg_dest, post, "requires", unit);
                 if (r < 0)
index 6c82d0f0efe3a9d1917ab650b529000129a55037..64f4a2741c324ad56cd03fde89a7425a2cd9f0fd 100644 (file)
@@ -650,6 +650,43 @@ int generator_hook_up_growfs(
         return generator_add_symlink_full(dir, where_unit, "wants", growfs_unit_path, instance);
 }
 
+int generator_hook_up_pcrfs(
+                const char *dir,
+                const char *where,
+                const char *target) {
+
+        const char *pcrfs_unit, *pcrfs_unit_path;
+        _cleanup_free_ char *where_unit = NULL, *instance = NULL;
+        int r;
+
+        assert(dir);
+        assert(where);
+
+        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);
+
+        if (empty_or_root(where)) {
+                pcrfs_unit = SPECIAL_PCRFS_ROOT_SERVICE;
+                pcrfs_unit_path = SYSTEM_DATA_UNIT_DIR "/" SPECIAL_PCRFS_ROOT_SERVICE;
+        } else {
+                pcrfs_unit = SPECIAL_PCRFS_SERVICE;
+                pcrfs_unit_path = SYSTEM_DATA_UNIT_DIR "/" SPECIAL_PCRFS_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", pcrfs_unit, instance);
+                if (r < 0)
+                        return r;
+        }
+
+        return generator_add_symlink_full(dir, where_unit, "wants", pcrfs_unit_path, instance);
+}
+
 int generator_enable_remount_fs_service(const char *dir) {
         /* Pull in systemd-remount-fs.service */
         return generator_add_symlink(dir, SPECIAL_LOCAL_FS_TARGET, "wants",
index a4049dbd8fb1c6a51de55928f54413a4355e813b..111900fd45143d6c24694fd2bccbb32633974b09 100644 (file)
@@ -81,6 +81,10 @@ int generator_hook_up_growfs(
         const char *dir,
         const char *where,
         const char *target);
+int generator_hook_up_pcrfs(
+        const char *dir,
+        const char *where,
+        const char *target);
 
 int generator_enable_remount_fs_service(const char *dir);
 
index 62ce438a3f0e77daa4f30afa4e18200649bf42e3..d59796b62b6d46d864f1c89922049956815d7418 100644 (file)
@@ -267,6 +267,8 @@ in_units = [
          'sysinit.target.wants/'],
         ['systemd-pcrmachine.service',           'HAVE_GNU_EFI HAVE_OPENSSL HAVE_TPM2',
          'sysinit.target.wants/'],
+        ['systemd-pcrfs-root.service',           ''],
+        ['systemd-pcrfs@.service',               ''],
         ['systemd-growfs-root.service',          ''],
         ['systemd-growfs@.service',              ''],
 ]
diff --git a/units/systemd-pcrfs-root.service.in b/units/systemd-pcrfs-root.service.in
new file mode 100644 (file)
index 0000000..b0da413
--- /dev/null
@@ -0,0 +1,24 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=TPM2 PCR Root File System Measurement
+Documentation=man:systemd-pcrfs-root.service(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+After=systemd-pcrmachine.service
+Before=shutdown.target
+AssertPathExists=!/etc/initrd-release
+ConditionSecurity=tpm2
+ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --file-system=/
diff --git a/units/systemd-pcrfs@.service.in b/units/systemd-pcrfs@.service.in
new file mode 100644 (file)
index 0000000..ec1ff11
--- /dev/null
@@ -0,0 +1,25 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=TPM2 PCR File System Measurement of %f
+Documentation=man:systemd-pcrfs@.service(8)
+DefaultDependencies=no
+BindsTo=%i.mount
+Conflicts=shutdown.target
+After=%i.mount systemd-pcrfs-root.service
+Before=shutdown.target
+AssertPathExists=!/etc/initrd-release
+ConditionSecurity=tpm2
+ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart={{ROOTLIBEXECDIR}}/systemd-pcrphase --file-system=%f