diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index 1292bbfbee1..088ce241540 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -792,6 +792,18 @@
+
+ systemd.tpm2_measured_os=
+
+ Controls whether to execute various boot and runtime TPM PCR measurements. Takes a
+ boolean argument. If not specified explicitly this behaviour is enabled automatically in case
+ systemd-stub7 is
+ used and it succeeded in doing pre-boot measurements of the booted UKI, and otherwise
+ disabled.
+
+
+
+
systemd.factory_reset=
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 37022ecc1c3..8bbff2f210a 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -1605,6 +1605,10 @@
measured-uki
Unified Kernel Image with PCR 11 Measurements, as per systemd-stub7.
+
+ measured-os
+ OS PCR measurements enabled. This is typically equivalent to measured-uki, however may also be set explicitly via the systemd.tpm2_measured_os= kernel command line switch, see kernel-command-line7 for details. The various system services doing boot and runtime measurements are conditioned on this flag.
+
diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c
index 4184e3d4249..178bffb3652 100644
--- a/src/bootctl/bootctl-status.c
+++ b/src/bootctl/bootctl-status.c
@@ -477,6 +477,16 @@ int verb_status(int argc, char *argv[], uintptr_t _data, void *userdata) {
printf(" Measured UKI: %sfailed%s (%m)\n", ansi_highlight_red(), ansi_normal());
}
+ k = efi_measured_os(LOG_DEBUG);
+ if (k > 0)
+ printf(" Measured OS: %syes%s\n", ansi_highlight_green(), ansi_normal());
+ else if (k == 0)
+ printf(" Measured OS: no\n");
+ else {
+ errno = -k;
+ printf(" Measured OS: %sfailed%s (%m)\n", ansi_highlight_red(), ansi_normal());
+ }
+
k = efi_get_reboot_to_firmware();
if (k > 0)
printf(" Boot into FW: %sactive%s\n", ansi_highlight_yellow(), ansi_normal());
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index bda9a8cc84a..64cd3813b87 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -1030,11 +1030,11 @@ static int measure_volume_key(
return 0;
}
- r = efi_measured_uki(LOG_WARNING);
+ r = efi_measured_os(LOG_WARNING);
if (r < 0)
return r;
if (r == 0) {
- log_debug("Kernel stub did not measure kernel image into the expected PCR, skipping userspace volume key measurement, too.");
+ log_debug("OS measurements not explicitly requested and kernel stub did not measure kernel image into the expected PCR, skipping userspace volume key measurement, too.");
return 0;
}
@@ -1109,11 +1109,11 @@ static int measure_keyslot(
}
#if HAVE_TPM2
- r = efi_measured_uki(LOG_WARNING);
+ r = efi_measured_os(LOG_WARNING);
if (r < 0)
return r;
if (r == 0) {
- log_debug("Kernel stub did not measure kernel image into the expected PCR, skipping userspace key slot measurement, too.");
+ log_debug("OS measurements not explicitly requested and kernel stub did not measure kernel image into the expected PCR, skipping userspace key slot measurement, too.");
return 0;
}
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index d60db7e9c1d..1bfebf3c408 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -672,9 +672,9 @@ static int add_mount(
}
if (flags & MOUNT_PCRFS) {
- r = efi_measured_uki(LOG_WARNING);
+ r = efi_measured_os(LOG_WARNING);
if (r == 0)
- log_debug("Kernel stub did not measure kernel image into PCR, skipping userspace measurement, too.");
+ log_debug("OS measurements not explicitly requested and kernel stub did not measure kernel image into PCR, skipping userspace measurement, too.");
else if (r > 0) {
r = generator_hook_up_pcrfs(dest, where, target_unit);
if (r < 0)
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index a87b5140805..6716a8d1aaf 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -115,11 +115,13 @@ static int add_cryptsetup(
return log_oom();
}
- r = efi_measured_uki(LOG_WARNING);
- if (r > 0)
+ r = efi_measured_os(LOG_WARNING);
+ if (r > 0) {
/* Enable TPM2 based unlocking automatically, if we have a TPM. See #30176. */
if (!strextend_with_separator(&options, ",", "tpm2-device=auto"))
return log_oom();
+ } else if (r == 0)
+ log_debug("Will not enable TPM based unlocking of volume '%s', OS measurements are not explicitly requested and not booted via systemd-stub with measurements enabled.", id);
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
@@ -130,7 +132,7 @@ static int add_cryptsetup(
if (!strextend_with_separator(&options, ",", "tpm2-measure-pcr=yes,tpm2-measure-keyslot-nvpcr=yes"))
return log_oom();
if (r == 0)
- log_debug("Will not measure volume key of volume '%s', not booted via systemd-stub with measurements enabled.", id);
+ log_debug("Will not measure volume key of volume '%s', as OS measurements are not explicitly requested and not booted via systemd-stub with measurements enabled.", id);
}
r = generator_write_cryptsetup_service_section(f, id, what, NULL, options);
@@ -240,11 +242,11 @@ static int add_veritysetup(
return log_oom();
if (FLAGS_SET(flags, MOUNT_MEASURE)) {
- r = efi_measured_uki(LOG_WARNING);
+ r = efi_measured_os(LOG_WARNING);
if (r > 0 && !strextend_with_separator(&options, ",", "tpm2-measure-nvpcr=yes"))
return log_oom();
- if (r == 0)
- log_debug("Will not measure root hash/signature of volume '%s', not booted via systemd-stub with measurements enabled.", id);
+ else if (r == 0)
+ log_debug("Will not measure root hash/signature of volume '%s', OS measurements not explicitly requested and not booted via systemd-stub with measurements enabled.", id);
}
r = generator_write_veritysetup_service_section(
diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c
index 79c7d41bb45..998c8e84d95 100644
--- a/src/hibernate-resume/hibernate-resume-generator.c
+++ b/src/hibernate-resume/hibernate-resume-generator.c
@@ -86,7 +86,7 @@ static int add_dissected_swap_cryptsetup(void) {
r = generator_write_cryptsetup_service_section(
f, "swap", DISSECTED_SWAP_LUKS_DEVICE,
/* key_file= */ NULL,
- efi_measured_uki(LOG_DEBUG) > 0 ? "tpm2-device=auto" : NULL);
+ efi_measured_os(LOG_DEBUG) > 0 ? "tpm2-device=auto" : NULL);
if (r < 0)
return r;
diff --git a/src/pcrextend/pcrextend.c b/src/pcrextend/pcrextend.c
index c0b111a0964..8ec0a733c68 100644
--- a/src/pcrextend/pcrextend.c
+++ b/src/pcrextend/pcrextend.c
@@ -536,12 +536,12 @@ static int run(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
- /* Skip logic if sd-stub is not used, after all PCR 11 might have a very different purpose then. */
- r = efi_measured_uki(LOG_ERR);
+ /* Skip logic if measured OS functionality is not enabled. */
+ r = efi_measured_os(LOG_ERR);
if (r < 0)
return r;
if (r == 0) {
- log_info("Kernel stub did not measure kernel image into PCR %i, skipping userspace measurement, too.", TPM2_PCR_KERNEL_BOOT);
+ log_info("OS measurements not explicitly requested and kernel stub did not measure kernel image into PCR %i, skipping userspace measurement, too.", TPM2_PCR_KERNEL_BOOT);
return EXIT_SUCCESS;
}
diff --git a/src/shared/condition.c b/src/shared/condition.c
index 903662edf1a..dd720c55bd9 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -741,6 +741,8 @@ static int condition_test_security(Condition *c, char **env) {
return detect_confidential_virtualization() > 0;
if (streq(c->parameter, "measured-uki"))
return efi_measured_uki(LOG_DEBUG);
+ if (streq(c->parameter, "measured-os"))
+ return efi_measured_os(LOG_DEBUG);
return false;
}
diff --git a/src/shared/efi-loader.c b/src/shared/efi-loader.c
index 1f4fc665c03..ce10a44d34c 100644
--- a/src/shared/efi-loader.c
+++ b/src/shared/efi-loader.c
@@ -8,6 +8,7 @@
#include "log.h"
#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
@@ -312,6 +313,30 @@ int efi_measured_uki(int log_level) {
#endif
}
+int efi_measured_os(int log_level) {
+#if ENABLE_EFI
+ static int cached = -1;
+ int r;
+
+ /* Returns if we shall enable our measurement machinery */
+
+ if (cached >= 0)
+ return cached;
+
+ bool b;
+ r = proc_cmdline_get_bool("systemd.tpm2_measured_os", /* flags= */ 0, &b);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse systemd.tpm2_measured_os= kernel command line argument, ignoring: %m");
+ else if (r > 0)
+ return (cached = b);
+
+ /* If nothing is explicitly configured, just assume that if we booted with a measured UKI we also want a measured OS */
+ return (cached = efi_measured_uki(log_level));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP), "Compiled without support for EFI");
+#endif
+}
+
int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
#if ENABLE_EFI
_cleanup_free_ char *v = NULL;
diff --git a/src/shared/efi-loader.h b/src/shared/efi-loader.h
index 5b614cd0a7e..abf8bdc49ef 100644
--- a/src/shared/efi-loader.h
+++ b/src/shared/efi-loader.h
@@ -15,6 +15,7 @@ int efi_loader_get_features(uint64_t *ret);
int efi_stub_get_features(uint64_t *ret);
int efi_measured_uki(int log_level);
+int efi_measured_os(int log_level);
int efi_loader_get_config_timeout_one_shot(usec_t *ret);
int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat);
diff --git a/units/systemd-pcrextend.socket b/units/systemd-pcrextend.socket
index d429150eda0..0f4ab11e2fd 100644
--- a/units/systemd-pcrextend.socket
+++ b/units/systemd-pcrextend.socket
@@ -13,7 +13,7 @@ Documentation=man:systemd-pcrextend(8)
DefaultDependencies=no
After=tpm2.target
Before=sockets.target
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
[Socket]
ListenStream=/run/systemd/io.systemd.PCRExtend
diff --git a/units/systemd-pcrfs-root.service.in b/units/systemd-pcrfs-root.service.in
index f774c4c8bf6..88551d7ed08 100644
--- a/units/systemd-pcrfs-root.service.in
+++ b/units/systemd-pcrfs-root.service.in
@@ -15,7 +15,7 @@ Conflicts=shutdown.target
After=tpm2.target systemd-pcrmachine.service
Before=shutdown.target
ConditionPathExists=!/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrfs@.service.in b/units/systemd-pcrfs@.service.in
index 3d18fe4d30e..38cc41976f6 100644
--- a/units/systemd-pcrfs@.service.in
+++ b/units/systemd-pcrfs@.service.in
@@ -16,7 +16,7 @@ Conflicts=shutdown.target
After=%i.mount tpm2.target systemd-pcrfs-root.service
Before=shutdown.target
ConditionPathExists=!/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrmachine.service.in b/units/systemd-pcrmachine.service.in
index ea2561ef79e..d97afa69655 100644
--- a/units/systemd-pcrmachine.service.in
+++ b/units/systemd-pcrmachine.service.in
@@ -15,7 +15,7 @@ Conflicts=shutdown.target
After=tpm2.target
Before=sysinit.target shutdown.target
ConditionPathExists=!/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrnvdone.service.in b/units/systemd-pcrnvdone.service.in
index e0dd9a88209..7593dedfed1 100644
--- a/units/systemd-pcrnvdone.service.in
+++ b/units/systemd-pcrnvdone.service.in
@@ -14,7 +14,7 @@ DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-tpm2-setup-early.service systemd-tpm2-setup.service
Before=sysinit.target shutdown.target
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
ConditionPathExists=!/etc/initrd-release
FailureAction=reboot-force
diff --git a/units/systemd-pcrphase-factory-reset.service.in b/units/systemd-pcrphase-factory-reset.service.in
index 5dbcb0f53f1..2efd8830d32 100644
--- a/units/systemd-pcrphase-factory-reset.service.in
+++ b/units/systemd-pcrphase-factory-reset.service.in
@@ -14,7 +14,7 @@ DefaultDependencies=no
Conflicts=shutdown.target
After=tpm2.target
Before=shutdown.target factory-reset.target
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrphase-initrd.service.in b/units/systemd-pcrphase-initrd.service.in
index 5aba32128c0..cbb83314701 100644
--- a/units/systemd-pcrphase-initrd.service.in
+++ b/units/systemd-pcrphase-initrd.service.in
@@ -15,7 +15,7 @@ Conflicts=shutdown.target initrd-switch-root.target
After=tpm2.target
Before=sysinit.target cryptsetup-pre.target cryptsetup.target shutdown.target initrd-switch-root.target systemd-sysext.service
ConditionPathExists=/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrphase-storage-target-mode.service.in b/units/systemd-pcrphase-storage-target-mode.service.in
index 52b53e5b819..b4330c560f5 100644
--- a/units/systemd-pcrphase-storage-target-mode.service.in
+++ b/units/systemd-pcrphase-storage-target-mode.service.in
@@ -15,7 +15,7 @@ Conflicts=shutdown.target
After=tpm2.target
Before=shutdown.target
ConditionPathExists=/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrphase-sysinit.service.in b/units/systemd-pcrphase-sysinit.service.in
index 4a01279159d..aa4d3640981 100644
--- a/units/systemd-pcrphase-sysinit.service.in
+++ b/units/systemd-pcrphase-sysinit.service.in
@@ -15,7 +15,7 @@ Conflicts=shutdown.target
After=sysinit.target tpm2.target
Before=basic.target shutdown.target
ConditionPathExists=!/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrphase.service.in b/units/systemd-pcrphase.service.in
index 43459a2fccb..b2f925d40f4 100644
--- a/units/systemd-pcrphase.service.in
+++ b/units/systemd-pcrphase.service.in
@@ -13,7 +13,7 @@ Documentation=man:systemd-pcrphase.service(8)
After=remote-fs.target remote-cryptsetup.target tpm2.target
Before=systemd-user-sessions.service
ConditionPathExists=!/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
FailureAction=reboot-force
[Service]
diff --git a/units/systemd-pcrproduct.service.in b/units/systemd-pcrproduct.service.in
index 09e446c2a01..2562dea18fe 100644
--- a/units/systemd-pcrproduct.service.in
+++ b/units/systemd-pcrproduct.service.in
@@ -16,7 +16,7 @@ After=tpm2.target
Before=sysinit.target shutdown.target
RequiresMountsFor=/var/lib/systemd/nvpcr
ConditionPathExists=!/etc/initrd-release
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
[Service]
Type=oneshot
diff --git a/units/systemd-tpm2-clear.service.in b/units/systemd-tpm2-clear.service.in
index a47d99ac8e7..501846180c9 100644
--- a/units/systemd-tpm2-clear.service.in
+++ b/units/systemd-tpm2-clear.service.in
@@ -22,7 +22,7 @@ ConditionPathExists=/sys/class/tpm/tpm0/ppi/request
# derive here from the fact that UKIs are used. Because if they do they are OK
# with our SRK initialization and our PCR measurements, and hence should also
# be OK with our TPM resets.
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
[Service]
Type=oneshot
diff --git a/units/systemd-tpm2-setup-early.service.in b/units/systemd-tpm2-setup-early.service.in
index ce1ee94cc49..6b7ef34b8c0 100644
--- a/units/systemd-tpm2-setup-early.service.in
+++ b/units/systemd-tpm2-setup-early.service.in
@@ -14,7 +14,7 @@ DefaultDependencies=no
Conflicts=shutdown.target
After=tpm2.target systemd-pcrphase-initrd.service
Before=sysinit.target shutdown.target
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
ConditionPathExists=!/run/systemd/tpm2-srk-public-key.pem
[Service]
diff --git a/units/systemd-tpm2-setup.service.in b/units/systemd-tpm2-setup.service.in
index dff516832d3..4593211c1ef 100644
--- a/units/systemd-tpm2-setup.service.in
+++ b/units/systemd-tpm2-setup.service.in
@@ -15,7 +15,7 @@ Conflicts=shutdown.target
After=tpm2.target systemd-tpm2-setup-early.service systemd-remount-fs.service
Before=sysinit.target shutdown.target
RequiresMountsFor=/var/lib/systemd
-ConditionSecurity=measured-uki
+ConditionSecurity=measured-os
ConditionPathExists=!/etc/initrd-release
[Service]