Re: [PATCH v7 01/11] tpm: Cap the number of PCR banks

Jarkko Sakkinen
2025-11-27T18:52:11Z

On Thu, Nov 27, 2025 at 06:17:42PM +0100, Roberto Sassu wrote:
> On Thu, 2025-11-27 at 19:14 +0200, Jarkko Sakkinen wrote:
> > On Thu, Nov 27, 2025 at 05:09:38PM +0100, Roberto Sassu wrote:
> > > On Thu, 2025-11-27 at 15:54 +0200, Jarkko Sakkinen wrote:
> > > > From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> > > >
> > > > tpm2_get_pcr_allocation() does not cap any upper limit for the number of
> > > > banks. Cap the limit to eight banks so that out of bounds values coming
> > > > from external I/O cause on only limited harm.
> > > >
> > > > Cc: Roberto Sassu <roberto.sassu@huawei.com>
> > >
> > > Sorry, I realized that you are expecting me to review.
> > >
> > > I have a couple of questions:
> > > - Could you explain better how out of bounds would occur, since one
> > > could check the number of PCR banks?
> > > - Is dynamic allocation that bad? And if yes, why?
> > > - Couldn't you just check that the number of available PCR banks is
> > > below the threshold you like and keep dynamic allocation?
> > > - Is removing tpm1_get_pcr_allocation() improving code readability?
> >
> > nr_possible_banks is read from external source i.e., neither kernel nor
> > CPU fully control its value. This causes *uncontrolled* dynamic
> > allocation. Thus, it must be capped to some value.
>
> Sure, I'm fine with capping. Isn't that enough?

It makes sense to make the whole memory allocation then infallible,
especially since it does not have much effect on diff. And it has
not significant effect on memory usage either.

But I do see one completely spurious and actually unintended change
that I spotted: tpm1_get_pcr_allocation. It there's no intention
doing this it has just carried over the series.

I reverted that part, which make it look like a proper bug fix:

diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 11088bda4e68..6849f216ba0b 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -799,11 +799,6 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
*/
int tpm1_get_pcr_allocation(struct tpm_chip *chip)
{
- chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
- GFP_KERNEL);
- if (!chip->allocated_banks)
- return -ENOMEM;
-
chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 7d77f6fbc152..97501c567c34 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -538,11 +538,9 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)

nr_possible_banks = be32_to_cpup(
(__be32 *)&buf.data[TPM_HEADER_SIZE + 5]);
-
- chip->allocated_banks = kcalloc(nr_possible_banks,
- sizeof(*chip->allocated_banks),
- GFP_KERNEL);
- if (!chip->allocated_banks) {
+ if (nr_possible_banks > TPM2_MAX_PCR_BANKS) {
+ pr_err("tpm: unexpected number of banks: %u > %u",
+ nr_possible_banks, TPM2_MAX_PCR_BANKS);
rc = -ENOMEM;
goto out;
}
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index dc0338a783f3..eb0ff071bcae 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -26,7 +26,9 @@
#include <crypto/aes.h>

#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */
-#define TPM_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
+
+#define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
+#define TPM2_MAX_PCR_BANKS 8

struct tpm_chip;
struct trusted_key_payload;
@@ -68,7 +70,7 @@ enum tpm2_curves {

struct tpm_digest {
u16 alg_id;
- u8 digest[TPM_MAX_DIGEST_SIZE];
+ u8 digest[TPM2_MAX_DIGEST_SIZE];
} __packed;

struct tpm_bank_info {
@@ -189,7 +191,7 @@ struct tpm_chip {
unsigned int groups_cnt;

u32 nr_allocated_banks;
- struct tpm_bank_info *allocated_banks;
+ struct tpm_bank_info allocated_banks[TPM2_MAX_PCR_BANKS];
#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];

>
> Thanks
>
> Roberto
>
> > > Thanks
> > >
> > > Roberto
> >
> > BR, Jarkko
>

BR, Jarkko