From 34906680afe60d724ea435b79b9b830a4bf2e7e9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Nov 2022 17:26:49 +0100 Subject: [PATCH 1/2] tpm2-util: force default TCTI to be "device" with parameter "/dev/tpmrm0" Apparently some distros default to tss-abmrd. Let's bypass that and always go to the kernel resource manager. abmrd cannot really work for us, since we want to access the TPM already in earliest boot i.e. in environments the abmrd service is not available in. Fixes: #25352 --- src/shared/tpm2-util.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index ba8a23e18c..b4808691da 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -152,8 +152,19 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) { if (r < 0) return log_error_errno(r, "TPM2 support not installed: %m"); - if (!device) + if (!device) { device = secure_getenv("SYSTEMD_TPM2_DEVICE"); + if (device) + /* Setting the env var to an empty string forces tpm2-tss' own device picking + * logic to be used. */ + device = empty_to_null(device); + else + /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti + * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd + * might be used and we really don't want that, since it is a system service and that creates + * various ordering issues/deadlocks during early boot. */ + device = "device:/dev/tpmrm0"; + } if (device) { const char *param, *driver, *fn; From 50a085143fa8f5dd6b6b3cef8a6ea2ec7c53ed0d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Nov 2022 23:01:04 +0100 Subject: [PATCH 2/2] tpm2: add some extra validation of device string before using it Let's add some extra validation before constructing and using the .so name to load. This isn't really security sensitive, given that we used secure_getenv() to get the device string (and it thus should have been come from a trusted source) but let's better be safe than sorry. --- src/shared/tpm2-util.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index b4808691da..68a3af1716 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -174,15 +174,27 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) { param = strchr(device, ':'); if (param) { + /* Syntax #1: Pair of driver string and arbitrary parameter */ driver = strndupa_safe(device, param - device); + if (isempty(driver)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing."); + param++; - } else { + } else if (path_is_absolute(device) && path_is_valid(device)) { + /* Syntax #2: TPM device node */ driver = "device"; param = device; - } + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing."); + + log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param); fn = strjoina("libtss2-tcti-", driver, ".so.0"); + /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */ + if (!filename_is_valid(fn)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver); + dl = dlopen(fn, RTLD_NOW); if (!dl) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());