mirror of
https://github.com/systemd/systemd.git
synced 2026-08-03 22:50:29 +00:00
core: introduce ConditionSecurity=measured-os
So far we always conditioned our TPM magic on the UKI having detected TPM support in the firmware. This is a bit limiting when we want to support a software TPM that is not visible to the firmware. Hence let's split this up, and add a separate control that can be set via the kernel command line. However, as before, let's by default inherit the firmare TPM discovery state into it, to retain the current behaviour unless overriden. With this in place, boot with "systemd.tpm2_measured_os=1 systemd.tpm2_software_fallback=1" on the kernel cmdline to get the swtpm fallback and then a measured OS based on it.
This commit is contained in:
@@ -792,6 +792,18 @@
|
||||
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.tpm2_measured_os=</varname></term>
|
||||
|
||||
<listitem><para>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
|
||||
<citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> is
|
||||
used and it succeeded in doing pre-boot measurements of the booted UKI, and otherwise
|
||||
disabled.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.factory_reset=</varname></term>
|
||||
|
||||
|
||||
@@ -1605,6 +1605,10 @@
|
||||
<entry>measured-uki</entry>
|
||||
<entry>Unified Kernel Image with PCR 11 Measurements, as per <citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry>. <xi:include href="version-info.xml" xpointer="v255"/></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>measured-os</entry>
|
||||
<entry>OS PCR measurements enabled. This is typically equivalent to <varname>measured-uki</varname>, however may also be set explicitly via the <varname>systemd.tpm2_measured_os=</varname> kernel command line switch, see <citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry> for details. The various system services doing boot and runtime measurements are conditioned on this flag. <xi:include href="version-info.xml" xpointer="v261"/></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user