tpm: reject duplicate PCR banks in tpm2_get_pcr_allocation

The TPM2_CAP_PCRS response is external input. tpm2_get_pcr_allocation()
adds every active selection to allocated_banks, while
tpm_sysfs_add_device() has one group slot per distinct hash algorithm.
Eight duplicate selections can therefore write past chip->groups[].

The TPM protocol does not allow a hash algorithm to appear twice in
this capability response. Treat a duplicate as a broken TPM and return
-EIO so the chip is not enabled, instead of silently dropping the
extra selection.

Assisted-by: LLM
Signed-off-by: Yuqi Xu <xuyuqiabc@gmail.com>
Reviewed-by: Ren Wei <weir@nebusec.ai>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/9d27c4513a3c6fc32f9574ba192cd3bfcb2bac98.1790568982.git.xuyuqiabc@gmail.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
This commit is contained in:
Yuqi Xu 2026-09-28 16:27:00 +08:00 committed by Jarkko Sakkinen
parent 03f0525735
commit 071aa806f0

View File

@ -528,6 +528,7 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
u32 rsp_len;
int rc;
int i = 0;
int j;
struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
if (!buf)
@ -570,6 +571,23 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
pcr_select_offset = memchr_inv(pcr_selection.pcr_select, 0,
pcr_selection.size_of_select);
if (pcr_select_offset) {
for (j = 0; j < nr_alloc_banks; j++) {
if (chip->allocated_banks[j].alg_id == hash_alg)
break;
}
/*
* The TPM protocol does not allow the same hash
* algorithm twice. A duplicate means this device
* is not behaving; do not enable it.
*/
if (j != nr_alloc_banks) {
pr_err("tpm: duplicate PCR bank for algorithm 0x%04x\n",
hash_alg);
rc = -EIO;
break;
}
chip->allocated_banks[nr_alloc_banks].alg_id = hash_alg;
rc = tpm2_init_bank_info(chip, nr_alloc_banks);