mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
tpm2: add common helper for checking if we are running on UKI with TPM measurements
Let's introduce a common implementation of a function that checks whether we are booted on a kernel with systemd-stub that has TPM PCR measurements enabled. Do our own userspace measurements only if we detect that. PCRs are scarce and most likely there are projects which already make use of them in other ways. Hence, instead of blindly stepping into their territory let's conditionalize things so that people have to explicitly buy into our PCR assignments before we start measuring things into them. Specifically bind everything to an UKI that reported measurements. This was previously already implemented in systemd-pcrphase, but with this change we expand this to all tools that process PCR measurement settings. The env var to override the check is renamed to SYSTEMD_FORCE_MEASURE, to make it more generic (since we'll use it at multiple places now). This is not a compat break, since the original env var for that was not included in any stable release yet.
This commit is contained in:
parent
04959faa63
commit
6c51b49ce0
@ -506,7 +506,10 @@ SYSTEMD_HOME_DEBUG_SUFFIX=foo \
|
||||
journal. Note that journal files in compact mode are limited to 4G to allow use of
|
||||
32-bit offsets. Enabled by default.
|
||||
|
||||
`systemd-pcrphase`:
|
||||
`systemd-pcrphase`, `systemd-cryptsetup`:
|
||||
|
||||
* `$SYSTEMD_PCRPHASE_STUB_VERIFY` – Takes a boolean. If false the requested
|
||||
measurement is done even if no EFI stub usage was reported via EFI variables.
|
||||
* `$SYSTEMD_FORCE_MEASURE=1` — If set, force measuring of resources (which are
|
||||
marked for measurement) even if not booted on a kernel equipped with
|
||||
systemd-stub. Normally, requested measurement of resources is conditionalized
|
||||
on kernels that have booted with `systemd-stub`. With this environment
|
||||
variable the test for that my be bypassed, for testing purposes.
|
||||
|
@ -9,15 +9,14 @@
|
||||
#include "blockdev-util.h"
|
||||
#include "build.h"
|
||||
#include "chase-symlinks.h"
|
||||
#include "efi-loader.h"
|
||||
#include "efivars.h"
|
||||
#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
#include "main-func.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "openssl-util.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "tpm-pcr.h"
|
||||
#include "tpm2-util.h"
|
||||
@ -241,9 +240,9 @@ static int get_file_system_word(
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_free_ char *joined = NULL, *pcr_string = NULL, *word = NULL;
|
||||
_cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
|
||||
unsigned target_pcr_nr, efi_pcr_nr;
|
||||
_cleanup_free_ char *joined = NULL, *word = NULL;
|
||||
unsigned target_pcr_nr;
|
||||
size_t length;
|
||||
int r;
|
||||
|
||||
@ -334,32 +333,13 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
length = strlen(word);
|
||||
|
||||
int b = getenv_bool("SYSTEMD_PCRPHASE_STUB_VERIFY");
|
||||
if (b < 0 && b != -ENXIO)
|
||||
log_warning_errno(b, "Unable to parse $SYSTEMD_PCRPHASE_STUB_VERIFY value, ignoring.");
|
||||
|
||||
/* Skip logic if sd-stub is not used, after all PCR 11 might have a very different purpose then. */
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(StubPcrKernelImage), &pcr_string);
|
||||
if (r == -ENOENT) {
|
||||
if (b != 0) {
|
||||
log_info("Kernel stub did not measure kernel image into PCR %u, skipping measurement.", TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
return EXIT_SUCCESS;
|
||||
} else
|
||||
log_notice("Kernel stub did not measure kernel image into PCR %u, but told to measure anyway, hence proceeding.", TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
} else if (r < 0)
|
||||
return log_error_errno(r, "Failed to read StubPcrKernelImage EFI variable: %m");
|
||||
else {
|
||||
/* Let's validate that the stub announced PCR 11 as we expected. */
|
||||
r = safe_atou(pcr_string, &efi_pcr_nr);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse StubPcrKernelImage EFI variable: %s", pcr_string);
|
||||
if (efi_pcr_nr != TPM_PCR_INDEX_KERNEL_IMAGE) {
|
||||
if (b != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "Kernel stub measured kernel image into PCR %u, which is different than expected %u.", efi_pcr_nr, TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
else
|
||||
log_notice("Kernel stub measured kernel image into PCR %u, which is different than expected %u, but told to measure anyway, hence proceeding.", efi_pcr_nr, TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
} else
|
||||
log_debug("Kernel stub reported same PCR %u as we want to use, proceeding.", TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
r = efi_stub_measured();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to detect if we are running on a kernel image with TPM measurement enabled: %m");
|
||||
if (r == 0) {
|
||||
log_info("Kernel stub did not measure kernel image into PCR %u, skipping userspace measurement, too.", TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
r = dlopen_tpm2();
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "cryptsetup-util.h"
|
||||
#include "device-util.h"
|
||||
#include "efi-api.h"
|
||||
#include "efi-loader.h"
|
||||
#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "fileio.h"
|
||||
@ -827,6 +828,14 @@ static int measure_volume_key(
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_stub_measured();
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to detect if we are running on a kernel image with TPM measurement enabled: %m");
|
||||
if (r == 0) {
|
||||
log_debug("Kernel stub did not measure kernel image into the expected PCR, skipping userspace measurement, too.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_TPM2
|
||||
r = dlopen_tpm2();
|
||||
if (r < 0)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "bus-error.h"
|
||||
#include "bus-locator.h"
|
||||
#include "chase-symlinks.h"
|
||||
#include "efi-loader.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fstab-util.h"
|
||||
@ -529,9 +530,16 @@ static int add_mount(
|
||||
}
|
||||
|
||||
if (flags & MOUNT_PCRFS) {
|
||||
r = generator_hook_up_pcrfs(dest, where, target_unit);
|
||||
r = efi_stub_measured();
|
||||
if (r < 0)
|
||||
return r;
|
||||
log_warning_errno(r, "Failed to detect if we are running on a kernel image with TPM measurement enabled, assuming not: %m");
|
||||
else if (r == 0)
|
||||
log_debug("Kernel stub did not measure kernel image into PCR, skipping userspace measurement, too.");
|
||||
else {
|
||||
r = generator_hook_up_pcrfs(dest, where, target_unit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(flags, MOUNT_AUTOMOUNT)) {
|
||||
|
@ -102,11 +102,11 @@ static int add_cryptsetup(
|
||||
* 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");
|
||||
r = efi_stub_measured();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine whether booted via systemd-stub with measurements enabled, ignoring: %m");
|
||||
else if (r == 0)
|
||||
log_debug("Will not measure volume key of volume '%s', because not booted via systemd-stub with measurements enabled.", id);
|
||||
else if (!strextend_with_separator(&options, ",", "tpm2-measure-pcr=yes"))
|
||||
return log_oom();
|
||||
}
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "efi-loader.h"
|
||||
#include "env-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "tpm-pcr.h"
|
||||
#include "utf8.h"
|
||||
|
||||
#if ENABLE_EFI
|
||||
@ -236,6 +238,43 @@ int efi_stub_get_features(uint64_t *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int efi_stub_measured(void) {
|
||||
_cleanup_free_ char *pcr_string = NULL;
|
||||
unsigned pcr_nr;
|
||||
int r;
|
||||
|
||||
/* Checks if we are booted on a kernel with sd-stub which measured the kernel into PCR 11. Or in
|
||||
* other words, if we are running on a TPM enabled UKI.
|
||||
*
|
||||
* Returns == 0 and > 0 depending on the result of the test. Returns -EREMOTE if we detected a stub
|
||||
* being used, but it measured things into a different PCR than we are configured for in
|
||||
* userspace. (i.e. we expect PCR 11 being used for this by both sd-stub and us) */
|
||||
|
||||
r = getenv_bool_secure("SYSTEMD_FORCE_MEASURE"); /* Give user a chance to override the variable test,
|
||||
* for debugging purposes */
|
||||
if (r >= 0)
|
||||
return r;
|
||||
if (r != -ENXIO)
|
||||
log_debug_errno(r, "Failed to parse $SYSTEMD_FORCE_MEASURE, ignoring: %m");
|
||||
|
||||
if (!is_efi_boot())
|
||||
return 0;
|
||||
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(StubPcrKernelImage), &pcr_string);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou(pcr_string, &pcr_nr);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse StubPcrKernelImage EFI variable: %s", pcr_string);
|
||||
if (pcr_nr != TPM_PCR_INDEX_KERNEL_IMAGE)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EREMOTE), "Kernel stub measured kernel image into PCR %u, which is different than expected %u.", pcr_nr, TPM_PCR_INDEX_KERNEL_IMAGE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
|
||||
_cleanup_free_ char *v = NULL;
|
||||
static struct stat cache_stat = {};
|
||||
|
@ -18,6 +18,8 @@ int efi_loader_get_entries(char ***ret);
|
||||
int efi_loader_get_features(uint64_t *ret);
|
||||
int efi_stub_get_features(uint64_t *ret);
|
||||
|
||||
int efi_stub_measured(void);
|
||||
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user