From 0e471978c582a614467d20d041f65c935c407abf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Oct 2022 15:54:09 +0200 Subject: [PATCH] gpt-auto-generator: automatically measure root/var volume keys into PCR 15 let's enable PCR 15 measurements automatically if gpt-auto discovery is used and systemd-stub is also used. (cherry picked from commit ff386f985bb51a48a11f74f6370dedf1bbfb4658) Related: RHEL-16182 --- man/systemd-gpt-auto-generator.xml | 8 +++++ src/gpt-auto-generator/gpt-auto-generator.c | 36 ++++++++++++++++++--- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml index 8ad249ec5d..f26bda511c 100644 --- a/man/systemd-gpt-auto-generator.xml +++ b/man/systemd-gpt-auto-generator.xml @@ -221,6 +221,13 @@ systems, make sure to set the correct default subvolumes on them, using btrfs subvolume set-default. + If the system was booted via + systemd-stub7 and the + stub reported to userspace that the kernel image was measured to a TPM2 PCR, then any discovered root and + /var/ volume identifiers (and volume encryption key in case it is encrypted) will be + automatically measured into PCR 15 on activation, via + systemd-pcrfs@.service8. + systemd-gpt-auto-generator implements systemd.generator7. @@ -272,6 +279,7 @@ systemd.swap5, systemd-fstab-generator8, systemd-cryptsetup@.service8, + systemd-pcrfs@.service8, machine-id5, cryptsetup8, fstab5, diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 0bab43e69a..2134185f04 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -47,10 +47,11 @@ static int add_cryptsetup( const char *what, bool rw, bool require, + bool measure, char **ret_device) { #if HAVE_LIBCRYPTSETUP - _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL; + _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *options = NULL; _cleanup_fclose_ FILE *f = NULL; int r; @@ -84,7 +85,28 @@ static int add_cryptsetup( "After=%s\n", d, d); - r = generator_write_cryptsetup_service_section(f, id, what, NULL, rw ? NULL : "read-only"); + if (!rw) { + options = strdup("read-only"); + if (!options) + return log_oom(); + } + + if (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 + * assignments are also OK with our PCR 15 use here. */ + + r = efi_get_variable(EFI_LOADER_VARIABLE(StubPcrKernelImage), NULL, NULL, NULL); /* we don't actually care which PCR the UKI used for itself */ + if (r == -ENOENT) + log_debug_errno(r, "Will not measure volume key of volume '%s', because not booted via systemd-stub with measurements enabled.", id); + else if (r < 0) + log_debug_errno(r, "Failed to determine whether booted via systemd-stub with measurements enabled, ignoring: %m"); + else if (!strextend_with_separator(&options, ",", "tpm2-measure-pcr=yes")) + return log_oom(); + } + + r = generator_write_cryptsetup_service_section(f, id, what, NULL, options); if (r < 0) return r; @@ -139,6 +161,7 @@ static int add_mount( const char *fstype, bool rw, bool growfs, + bool measure, const char *options, const char *description, const char *post) { @@ -159,7 +182,7 @@ static int add_mount( log_debug("Adding %s: %s fstype=%s", where, what, fstype ?: "(any)"); if (streq_ptr(fstype, "crypto_LUKS")) { - r = add_cryptsetup(id, what, rw, true, &crypto_what); + r = add_cryptsetup(id, what, rw, /* require= */ true, measure, &crypto_what); if (r < 0) return r; @@ -277,6 +300,7 @@ static int add_partition_mount( 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 */ NULL, description, SPECIAL_LOCAL_FS_TARGET); @@ -301,7 +325,7 @@ static int add_partition_swap(DissectedPartition *p) { } if (streq_ptr(p->fstype, "crypto_LUKS")) { - r = add_cryptsetup("swap", p->node, true, true, &crypto_what); + r = add_cryptsetup("swap", p->node, /* rw= */ true, /* require= */ true, /* measure= */ false, &crypto_what); if (r < 0) return r; what = crypto_what; @@ -374,6 +398,7 @@ static int add_automount( fstype, rw, growfs, + /* measure= */ false, opt, description, NULL); @@ -582,7 +607,7 @@ static int add_root_cryptsetup(void) { /* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which * sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */ - return add_cryptsetup("root", "/dev/gpt-auto-root-luks", true, false, NULL); + return add_cryptsetup("root", "/dev/gpt-auto-root-luks", /* rw= */ true, /* require= */ false, /* measure= */ true, NULL); #else return 0; #endif @@ -629,6 +654,7 @@ static int add_root_mount(void) { NULL, /* rw= */ arg_root_rw > 0, /* growfs= */ false, + /* measure= */ true, NULL, "Root Partition", in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);