From: Lennart Poettering Date: Tue, 23 Sep 2025 11:42:02 +0000 (+0200) Subject: boot: check protocol version before assuming GetActiveBanks() exists X-Git-Tag: v259-rc1~458^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b388fa20c735add38080a746fd831273820c93ac;p=thirdparty%2Fsystemd.git boot: check protocol version before assuming GetActiveBanks() exists Alternative to: #39034 Fixes: #38932 Follow-up to: 6eab4cd44c3c43698dcfc2c3bc8cd31ed610a812 --- diff --git a/src/boot/measure.c b/src/boot/measure.c index e097e6676e6..b1433ff1b50 100644 --- a/src/boot/measure.c +++ b/src/boot/measure.c @@ -150,7 +150,7 @@ static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) { return cc; } -static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) { +static EFI_TCG2_PROTOCOL* tcg2_interface_check(EFI_TCG2_VERSION *ret_version) { EFI_STATUS err; EFI_TCG2_PROTOCOL *tcg; @@ -167,28 +167,42 @@ static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) { assert(capability.Size >= endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, Size)); - if (capability.Size < endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, TPMPresentFlag)) + /* This is a paranoia check, given these fields existed from day one of the spec. But the spec also + * suggests checking the structure size before accessing any fields, hence let's do so, for extra + * paranoia. */ + if (capability.Size < CONST_MAX(endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, TPMPresentFlag), + endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, ProtocolVersion))) return NULL; if (!capability.TPMPresentFlag) return NULL; + if (ret_version) + *ret_version = capability.ProtocolVersion; + return tcg; } bool tpm_present(void) { - return tcg2_interface_check(); + return tcg2_interface_check(/* ret_version= */ NULL); } uint32_t tpm_get_active_pcr_banks(void) { - uint32_t active_pcr_banks = 0; - EFI_TCG2_PROTOCOL *tpm2; EFI_STATUS err; - tpm2 = tcg2_interface_check(); + EFI_TCG2_PROTOCOL *tpm2; + EFI_TCG2_VERSION version; + tpm2 = tcg2_interface_check(&version); if (!tpm2) return 0; + /* GetActivePcrBanks() was added only in version 1.1 of the spec */ + if (version.Major < 1 || (version.Major == 1 && version.Minor < 1)) { + log_debug("TCG protocol too old for GetActivePcrBanks(), claiming no active banks."); + return 0; + } + + uint32_t active_pcr_banks = 0; err = tpm2->GetActivePcrBanks(tpm2, &active_pcr_banks); if (err != EFI_SUCCESS) { log_warning_status(err, "Failed to get TPM2 active PCR banks, assuming none: %m"); @@ -204,7 +218,7 @@ static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buf assert(ret_measured); - tpm2 = tcg2_interface_check(); + tpm2 = tcg2_interface_check(/* ret_version= */ NULL); if (!tpm2) { *ret_measured = false; return EFI_SUCCESS; @@ -286,7 +300,7 @@ EFI_STATUS tpm_log_tagged_event( /* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured * something, or false if measurement was turned off. */ - tpm2 = tcg2_interface_check(); + tpm2 = tcg2_interface_check(/* ret_version= */ NULL); if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */ if (ret_measured) *ret_measured = false;