From: Jarkko Sakkinen <jarkko@kernel.org>
To: Ross Philipson <ross.philipson@gmail.com>
Cc: linux-kernel@vger.kernel.org, x86@kernel.org,
linux-integrity@vger.kernel.org, linux-crypto@vger.kernel.org,
linux-efi@vger.kernel.org, dpsmith@apertussolutions.com,
tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
hpa@zytor.com, dave.hansen@linux.intel.com, ardb@kernel.org,
mjg59@srcf.ucam.org, James.Bottomley@hansenpartnership.com,
peterhuewe@gmx.de, luto@amacapital.net,
herbert@gondor.apana.org.au, davem@davemloft.net, corbet@lwn.net,
kanth.ghatraju@oracle.com, daniel.kiper@oracle.com,
andrew.cooper3@citrix.com, trenchboot-devel@googlegroups.com
Subject: Re: [PATCH v2 09/10] tpm-buf: Memory-safe allocations
Date: Sat, 11 Jul 2026 21:15:51 +0300 [thread overview]
Message-ID: <alKIV4oyQPu_BWaC@kernel.org> (raw)
In-Reply-To: <20260711160110.267780-10-ross.philipson@gmail.com>
On Sat, Jul 11, 2026 at 09:01:09AM -0700, Ross Philipson wrote:
> From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
>
> Decouple kzalloc from buffer creation, so that a managed allocation can be
> used:
>
> struct tpm_buf *buf __free(kfree) buf = kzalloc(TPM_BUFSIZE,
> GFP_KERNEL);
> if (!buf)
> return -ENOMEM;
>
> tpm_buf_init(buf, TPM_BUFSIZE);
>
> Alternatively, other allocations are also possible (static data, stack,
> etc) for example:
>
> u8 buf_data[512];
> struct tpm_buf *buf = (struct tpm_buf *)buf_data;
> tpm_buf_init(buf, sizeof(buf_data));
>
> This is achieved by embedding buffer's header inside the allocated blob,
> instead of having an outer wrapper.
>
> Cc: Arun Menon <armenon@redhat.com>
> Cc: Daniel P. Smith <dpsmith@apertussolutions.com>
> Cc: Alec Brown <alec.r.brown@oracle.com>
> Cc: Ross Philipson <ross.philipson@gmail.com>
> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> Tested-by: Srish Srinivasan <ssrish@linux.ibm.com>
> Message-ID: <20260522013555.1063716-1-jarkko@kernel.org>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
> drivers/char/tpm/tpm-buf.c | 122 +++++----
> drivers/char/tpm/tpm-sysfs.c | 26 +-
> drivers/char/tpm/tpm1-cmd.c | 163 ++++++------
> drivers/char/tpm/tpm2-cmd.c | 291 +++++++++++-----------
> drivers/char/tpm/tpm2-sessions.c | 162 ++++++------
> drivers/char/tpm/tpm2-space.c | 44 ++--
> drivers/char/tpm/tpm_vtpm_proxy.c | 30 +--
> include/linux/tpm.h | 17 +-
> security/keys/trusted-keys/trusted_tpm1.c | 44 ++--
> security/keys/trusted-keys/trusted_tpm2.c | 165 ++++++------
> 10 files changed, 530 insertions(+), 534 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c
> index 99811809a72a..1e5c11c312a8 100644
> --- a/drivers/char/tpm/tpm-buf.c
> +++ b/drivers/char/tpm/tpm-buf.c
> @@ -6,82 +6,110 @@
> #include <linux/module.h>
> #include <linux/tpm.h>
>
> -/**
> - * tpm_buf_init() - Allocate and initialize a TPM command
> - * @buf: A &tpm_buf
> - * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS
> - * @ordinal: A command ordinal
> - *
> - * Return: 0 or -ENOMEM
> - */
> -int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
> +static void __tpm_buf_size_invariant(struct tpm_buf *buf, u16 buf_size)
> {
> - buf->data = (u8 *)__get_free_page(GFP_KERNEL);
> - if (!buf->data)
> - return -ENOMEM;
> -
> - tpm_buf_reset(buf, tag, ordinal);
> - return 0;
> + u32 buf_size_2 = (u32)buf->capacity + (u32)sizeof(*buf);
> +
> + if (!buf->capacity) {
> + if (buf_size > TPM_BUFSIZE) {
> + WARN(1, "%s: size overflow: %u\n", __func__, buf_size);
> + buf->flags |= TPM_BUF_INVALID;
> + }
> + } else {
> + if (buf_size != buf_size_2) {
> + WARN(1, "%s: size mismatch: %u != %u\n", __func__,
> + buf_size, buf_size_2);
> + buf->flags |= TPM_BUF_INVALID;
> + }
> + }
> }
> -EXPORT_SYMBOL_GPL(tpm_buf_init);
>
> -/**
> - * tpm_buf_reset() - Initialize a TPM command
> - * @buf: A &tpm_buf
> - * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS
> - * @ordinal: A command ordinal
> - */
> -void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal)
> +static void __tpm_buf_reset(struct tpm_buf *buf, u16 buf_size, u16 tag,
> + u32 ordinal)
> {
> struct tpm_header *head = (struct tpm_header *)buf->data;
>
> + __tpm_buf_size_invariant(buf, buf_size);
> +
> + if (buf->flags & TPM_BUF_INVALID)
> + return;
> +
> WARN_ON(tag != TPM_TAG_RQU_COMMAND && tag != TPM2_ST_NO_SESSIONS &&
> tag != TPM2_ST_SESSIONS && tag != 0);
>
> buf->flags = 0;
> buf->length = sizeof(*head);
> + buf->capacity = buf_size - sizeof(*buf);
> + buf->handles = 0;
> head->tag = cpu_to_be16(tag);
> head->length = cpu_to_be32(sizeof(*head));
> head->ordinal = cpu_to_be32(ordinal);
> +}
> +
> +static void __tpm_buf_reset_sized(struct tpm_buf *buf, u16 buf_size)
> +{
> + __tpm_buf_size_invariant(buf, buf_size);
> +
> + if (buf->flags & TPM_BUF_INVALID)
> + return;
> +
> + buf->flags = TPM_BUF_TPM2B;
> + buf->length = 2;
> + buf->capacity = buf_size - sizeof(*buf);
> buf->handles = 0;
> + buf->data[0] = 0;
> + buf->data[1] = 0;
> }
> -EXPORT_SYMBOL_GPL(tpm_buf_reset);
>
> /**
> - * tpm_buf_init_sized() - Allocate and initialize a sized (TPM2B) buffer
> - * @buf: A @tpm_buf
> - *
> - * Return: 0 or -ENOMEM
> + * tpm_buf_init() - Initialize a TPM command
> + * @buf: A &tpm_buf
> + * @buf_size: Size of the buffer.
> */
> -int tpm_buf_init_sized(struct tpm_buf *buf)
> +void tpm_buf_init(struct tpm_buf *buf, u16 buf_size)
> {
> - buf->data = (u8 *)__get_free_page(GFP_KERNEL);
> - if (!buf->data)
> - return -ENOMEM;
> + memset(buf, 0, buf_size);
> + __tpm_buf_reset(buf, buf_size, TPM_TAG_RQU_COMMAND, 0);
> +}
> +EXPORT_SYMBOL_GPL(tpm_buf_init);
>
> - tpm_buf_reset_sized(buf);
> - return 0;
> +/**
> + * tpm_buf_init_sized() - Initialize a sized buffer
> + * @buf: A &tpm_buf
> + * @buf_size: Size of the buffer.
> + */
> +void tpm_buf_init_sized(struct tpm_buf *buf, u16 buf_size)
> +{
> + memset(buf, 0, buf_size);
> + __tpm_buf_reset_sized(buf, buf_size);
> }
> EXPORT_SYMBOL_GPL(tpm_buf_init_sized);
>
> /**
> - * tpm_buf_reset_sized() - Initialize a sized buffer
> + * tpm_buf_reset() - Re-initialize a TPM command
> * @buf: A &tpm_buf
> + * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS
> + * @ordinal: A command ordinal
> */
> -void tpm_buf_reset_sized(struct tpm_buf *buf)
> +void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal)
> {
> - buf->flags = TPM_BUF_TPM2B;
> - buf->length = 2;
> - buf->data[0] = 0;
> - buf->data[1] = 0;
> + u16 buf_size = buf->capacity + sizeof(*buf);
> +
> + __tpm_buf_reset(buf, buf_size, tag, ordinal);
> }
> -EXPORT_SYMBOL_GPL(tpm_buf_reset_sized);
> +EXPORT_SYMBOL_GPL(tpm_buf_reset);
>
> -void tpm_buf_destroy(struct tpm_buf *buf)
> +/**
> + * tpm_buf_reset_sized() - Re-initialize a sized buffer
> + * @buf: A &tpm_buf
> + */
> +void tpm_buf_reset_sized(struct tpm_buf *buf)
> {
> - free_page((unsigned long)buf->data);
> + u16 buf_size = buf->capacity + sizeof(*buf);
> +
> + __tpm_buf_reset_sized(buf, buf_size);
> }
> -EXPORT_SYMBOL_GPL(tpm_buf_destroy);
> +EXPORT_SYMBOL_GPL(tpm_buf_reset_sized);
>
> /**
> * tpm_buf_length() - Return the number of bytes consumed by the data
> @@ -89,7 +117,7 @@ EXPORT_SYMBOL_GPL(tpm_buf_destroy);
> *
> * Return: The number of bytes consumed by the buffer
> */
> -u32 tpm_buf_length(struct tpm_buf *buf)
> +u16 tpm_buf_length(struct tpm_buf *buf)
> {
> return buf->length;
> }
> @@ -103,10 +131,12 @@ EXPORT_SYMBOL_GPL(tpm_buf_length);
> */
> void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length)
> {
> + u32 total_length = (u32)buf->length + (u32)new_length;
> +
> if (buf->flags & TPM_BUF_INVALID)
> return;
>
> - if ((buf->length + new_length) > PAGE_SIZE) {
> + if (total_length > (u32)buf->capacity) {
> WARN(1, "tpm_buf: write overflow\n");
> buf->flags |= TPM_BUF_INVALID;
> return;
> diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
> index 94231f052ea7..d915307ae833 100644
> --- a/drivers/char/tpm/tpm-sysfs.c
> +++ b/drivers/char/tpm/tpm-sysfs.c
> @@ -32,28 +32,35 @@ struct tpm_readpubek_out {
> static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> - struct tpm_buf tpm_buf;
> struct tpm_readpubek_out *out;
> int i;
> char *str = buf;
> struct tpm_chip *chip = to_tpm_chip(dev);
> char anti_replay[20];
> + struct tpm_buf *tpm_buf __free(kfree) = NULL;
>
> memset(&anti_replay, 0, sizeof(anti_replay));
>
> if (tpm_try_get_ops(chip))
> return 0;
>
> - if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK))
> - goto out_ops;
> + tpm_buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!tpm_buf) {
> + tpm_put_ops(chip);
> + return 0;
> + }
>
> - tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay));
> + tpm_buf_init(tpm_buf, TPM_BUFSIZE);
> + tpm_buf_reset(tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK);
> + tpm_buf_append(tpm_buf, anti_replay, sizeof(anti_replay));
>
> - if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE,
> - "attempting to read the PUBEK"))
> - goto out_buf;
> + if (tpm_transmit_cmd(chip, tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE,
> + "attempting to read the PUBEK")) {
> + tpm_put_ops(chip);
> + return 0;
> + }
>
> - out = (struct tpm_readpubek_out *)&tpm_buf.data[10];
> + out = (struct tpm_readpubek_out *)&tpm_buf->data[10];
> str +=
> sprintf(str,
> "Algorithm: %4ph\n"
> @@ -71,9 +78,6 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
> for (i = 0; i < 256; i += 16)
> str += sprintf(str, "%16ph\n", &out->modulus[i]);
>
> -out_buf:
> - tpm_buf_destroy(&tpm_buf);
> -out_ops:
> tpm_put_ops(chip);
> return str - buf;
> }
> diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
> index 96f189b5fd6f..7a8606e8c711 100644
> --- a/drivers/char/tpm/tpm1-cmd.c
> +++ b/drivers/char/tpm/tpm1-cmd.c
> @@ -318,20 +318,18 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
> */
> static int tpm1_startup(struct tpm_chip *chip)
> {
> - struct tpm_buf buf;
> - int rc;
> + struct tpm_buf *buf __free(kfree) = NULL;
>
> dev_info(&chip->dev, "starting up the TPM manually\n");
>
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
> - if (rc < 0)
> - return rc;
> -
> - tpm_buf_append_u16(&buf, TPM_ST_CLEAR);
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM");
> - tpm_buf_destroy(&buf);
> - return rc;
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
> + tpm_buf_append_u16(buf, TPM_ST_CLEAR);
> + return tpm_transmit_cmd(chip, buf, 0, "attempting to start the TPM");
> }
>
> int tpm1_get_timeouts(struct tpm_chip *chip)
> @@ -457,49 +455,49 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
> int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash,
> const char *log_msg)
> {
> - struct tpm_buf buf;
> - int rc;
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
> - if (rc)
> - return rc;
> -
> - tpm_buf_append_u32(&buf, pcr_idx);
> - tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
> + tpm_buf_append_u32(buf, pcr_idx);
> + tpm_buf_append(buf, hash, TPM_DIGEST_SIZE);
>
> - rc = tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, log_msg);
> - tpm_buf_destroy(&buf);
> - return rc;
> + return tpm_transmit_cmd(chip, buf, TPM_DIGEST_SIZE, log_msg);
> }
>
> ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
> const char *desc, size_t min_cap_length)
> {
> - struct tpm_buf buf;
> int rc;
>
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP);
> - if (rc)
> - return rc;
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP);
>
> if (subcap_id == TPM_CAP_VERSION_1_1 ||
> subcap_id == TPM_CAP_VERSION_1_2) {
> - tpm_buf_append_u32(&buf, subcap_id);
> - tpm_buf_append_u32(&buf, 0);
> + tpm_buf_append_u32(buf, subcap_id);
> + tpm_buf_append_u32(buf, 0);
> } else {
> if (subcap_id == TPM_CAP_FLAG_PERM ||
> subcap_id == TPM_CAP_FLAG_VOL)
> - tpm_buf_append_u32(&buf, TPM_CAP_FLAG);
> + tpm_buf_append_u32(buf, TPM_CAP_FLAG);
> else
> - tpm_buf_append_u32(&buf, TPM_CAP_PROP);
> + tpm_buf_append_u32(buf, TPM_CAP_PROP);
>
> - tpm_buf_append_u32(&buf, 4);
> - tpm_buf_append_u32(&buf, subcap_id);
> + tpm_buf_append_u32(buf, 4);
> + tpm_buf_append_u32(buf, subcap_id);
> }
> - rc = tpm_transmit_cmd(chip, &buf, min_cap_length, desc);
> +
> + rc = tpm_transmit_cmd(chip, buf, min_cap_length, desc);
> if (!rc)
> - *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4];
> - tpm_buf_destroy(&buf);
> + *cap = *(cap_t *)&buf->data[TPM_HEADER_SIZE + 4];
> +
> return rc;
> }
> EXPORT_SYMBOL_GPL(tpm1_getcap);
> @@ -517,81 +515,77 @@ EXPORT_SYMBOL_GPL(tpm1_getcap);
> int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
> {
> struct tpm1_get_random_out *out;
> + struct tpm_buf *buf __free(kfree) = NULL;
> u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
> - struct tpm_buf buf;
> u32 total = 0;
> int retries = 5;
> u32 recd;
> int rc;
>
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM);
> - if (rc)
> - return rc;
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM);
>
> do {
> - tpm_buf_append_u32(&buf, num_bytes);
> + tpm_buf_append_u32(buf, num_bytes);
>
> - rc = tpm_transmit_cmd(chip, &buf, sizeof(out->rng_data_len),
> + rc = tpm_transmit_cmd(chip, buf, sizeof(out->rng_data_len),
> "attempting get random");
> if (rc) {
> if (rc > 0)
> rc = -EIO;
> - goto out;
> + return rc;
> }
>
> - out = (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE];
> + out = (struct tpm1_get_random_out *)&buf->data[TPM_HEADER_SIZE];
>
> recd = be32_to_cpu(out->rng_data_len);
> - if (recd > num_bytes) {
> - rc = -EFAULT;
> - goto out;
> - }
> + if (recd > num_bytes)
> + return -EFAULT;
> +
> + if (tpm_buf_length(buf) < TPM_HEADER_SIZE +
> + sizeof(out->rng_data_len) + recd)
> + return -EFAULT;
>
> - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE +
> - sizeof(out->rng_data_len) + recd) {
> - rc = -EFAULT;
> - goto out;
> - }
> memcpy(dest, out->rng_data, recd);
>
> dest += recd;
> total += recd;
> num_bytes -= recd;
>
> - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM);
> } while (retries-- && total < max);
>
> rc = total ? (int)total : -EIO;
> -out:
> - tpm_buf_destroy(&buf);
> +
> return rc;
> }
>
> int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)
> {
> - struct tpm_buf buf;
> int rc;
>
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_READ);
> - if (rc)
> - return rc;
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - tpm_buf_append_u32(&buf, pcr_idx);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_READ);
> + tpm_buf_append_u32(buf, pcr_idx);
>
> - rc = tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE,
> + rc = tpm_transmit_cmd(chip, buf, TPM_DIGEST_SIZE,
> "attempting to read a pcr value");
> if (rc)
> - goto out;
> + return rc;
>
> - if (tpm_buf_length(&buf) < TPM_DIGEST_SIZE) {
> - rc = -EFAULT;
> - goto out;
> - }
> + if (tpm_buf_length(buf) < TPM_DIGEST_SIZE)
> + return -EFAULT;
>
> - memcpy(res_buf, &buf.data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE);
> + memcpy(res_buf, &buf->data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE);
>
> -out:
> - tpm_buf_destroy(&buf);
> return rc;
> }
>
> @@ -604,16 +598,13 @@ int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)
> */
> static int tpm1_continue_selftest(struct tpm_chip *chip)
> {
> - struct tpm_buf buf;
> - int rc;
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
> - if (rc)
> - return rc;
> -
> - rc = tpm_transmit_cmd(chip, &buf, 0, "continue selftest");
> - tpm_buf_destroy(&buf);
> - return rc;
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
> + return tpm_transmit_cmd(chip, buf, 0, "continue selftest");
> }
>
> /**
> @@ -725,22 +716,24 @@ int tpm1_auto_startup(struct tpm_chip *chip)
> int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
> {
> u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
> - struct tpm_buf buf;
> unsigned int try;
> + struct tpm_buf *buf __free(kfree) = NULL;
> int rc;
>
> -
> /* for buggy tpm, flush pcrs with extend to selected dummy */
> if (tpm_suspend_pcr)
> rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash,
> "extending dummy pcr before suspend");
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
>
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
> - if (rc)
> - return rc;
> /* now do the actual savestate */
> for (try = 0; try < TPM_RETRY; try++) {
> - rc = tpm_transmit_cmd(chip, &buf, 0, NULL);
> + rc = tpm_transmit_cmd(chip, buf, 0, NULL);
> /*
> * If the TPM indicates that it is too busy to respond to
> * this command then retry before giving up. It can take
> @@ -755,7 +748,7 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
> break;
> tpm_msleep(TPM_TIMEOUT_RETRY);
>
> - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
> }
>
> if (rc)
> @@ -765,8 +758,6 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
> dev_warn(&chip->dev, "TPM savestate took %dms\n",
> try * TPM_TIMEOUT_RETRY);
>
> - tpm_buf_destroy(&buf);
> -
> return rc;
> }
>
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index c7952319384e..48cec39995fe 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -108,12 +108,13 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
> {
> int i;
> int rc;
> - struct tpm_buf buf;
> struct tpm2_pcr_read_out *out;
> u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
> u16 digest_size;
> u16 expected_digest_size = 0;
>
> + struct tpm_buf *buf __free(kfree) = NULL;
> +
> if (pcr_idx >= TPM2_PLATFORM_PCR)
> return -EINVAL;
>
> @@ -128,36 +129,35 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
> expected_digest_size = chip->allocated_banks[i].digest_size;
> }
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
> - if (rc)
> - return rc;
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
>
> pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
>
> - tpm_buf_append_u32(&buf, 1);
> - tpm_buf_append_u16(&buf, digest->alg_id);
> - tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN);
> - tpm_buf_append(&buf, (const unsigned char *)pcr_select,
> + tpm_buf_append_u32(buf, 1);
> + tpm_buf_append_u16(buf, digest->alg_id);
> + tpm_buf_append_u8(buf, TPM2_PCR_SELECT_MIN);
> + tpm_buf_append(buf, (const unsigned char *)pcr_select,
> sizeof(pcr_select));
>
> - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value");
> + rc = tpm_transmit_cmd(chip, buf, 0, "attempting to read a pcr value");
> if (rc)
> - goto out;
> + return rc;
>
> - out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
> + out = (struct tpm2_pcr_read_out *)&buf->data[TPM_HEADER_SIZE];
> digest_size = be16_to_cpu(out->digest_size);
> if (digest_size > sizeof(digest->digest) ||
> - (!digest_size_ptr && digest_size != expected_digest_size)) {
> - rc = -EINVAL;
> - goto out;
> - }
> + (!digest_size_ptr && digest_size != expected_digest_size))
> + return -EINVAL;
>
> if (digest_size_ptr)
> *digest_size_ptr = digest_size;
>
> memcpy(digest->digest, out->digest, digest_size);
> -out:
> - tpm_buf_destroy(&buf);
> return rc;
> }
>
> @@ -173,7 +173,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
> int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
> struct tpm_digest *digests)
> {
> - struct tpm_buf buf;
> + struct tpm_buf *buf __free(kfree) = NULL;
> int rc;
> int i;
>
> @@ -183,46 +183,45 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
> return rc;
> }
>
> - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
> - if (rc) {
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> if (!disable_pcr_integrity)
> tpm2_end_auth_session(chip);
> - return rc;
> + return -ENOMEM;
> }
>
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
> +
> if (!disable_pcr_integrity) {
> - rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
> + rc = tpm_buf_append_name(chip, buf, pcr_idx, NULL);
> if (rc) {
> - tpm_buf_destroy(&buf);
> + tpm2_end_auth_session(chip);
> return rc;
> }
> - tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
> + tpm_buf_append_hmac_session(chip, buf, 0, NULL, 0);
> } else {
> - tpm_buf_append_handle(&buf, pcr_idx);
> - tpm_buf_append_auth(chip, &buf, NULL, 0);
> + tpm_buf_append_handle(buf, pcr_idx);
> + tpm_buf_append_auth(chip, buf, NULL, 0);
> }
>
> - tpm_buf_append_u32(&buf, chip->nr_allocated_banks);
> + tpm_buf_append_u32(buf, chip->nr_allocated_banks);
>
> for (i = 0; i < chip->nr_allocated_banks; i++) {
> - tpm_buf_append_u16(&buf, digests[i].alg_id);
> - tpm_buf_append(&buf, (const unsigned char *)&digests[i].digest,
> + tpm_buf_append_u16(buf, digests[i].alg_id);
> + tpm_buf_append(buf, (const unsigned char *)&digests[i].digest,
> chip->allocated_banks[i].digest_size);
> }
>
> if (!disable_pcr_integrity) {
> - rc = tpm_buf_fill_hmac_session(chip, &buf);
> - if (rc) {
> - tpm_buf_destroy(&buf);
> + rc = tpm_buf_fill_hmac_session(chip, buf);
> + if (rc)
> return rc;
> - }
> }
>
> - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
> + rc = tpm_transmit_cmd(chip, buf, 0, "attempting extend a PCR value");
> if (!disable_pcr_integrity)
> - rc = tpm_buf_check_hmac_response(chip, &buf, rc);
> -
> - tpm_buf_destroy(&buf);
> + rc = tpm_buf_check_hmac_response(chip, buf, rc);
>
> return rc;
> }
> @@ -242,7 +241,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
> {
> struct tpm2_get_random_out *out;
> struct tpm_header *head;
> - struct tpm_buf buf;
> u32 recd;
> u32 num_bytes = max;
> int err;
> @@ -251,6 +249,8 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
> u8 *dest_ptr = dest;
> off_t offset;
>
> + struct tpm_buf *buf __free(kfree) = NULL;
> +
> if (!num_bytes || max > TPM_MAX_RNG_DATA)
> return -EINVAL;
>
> @@ -258,55 +258,58 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
> if (err)
> return err;
>
> - err = tpm_buf_init(&buf, 0, 0);
> - if (err) {
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> tpm2_end_auth_session(chip);
> - return err;
> + return -ENOMEM;
> }
>
> + tpm_buf_init(buf, TPM_BUFSIZE);
> +
> do {
> - tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
> + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
> if (tpm2_chip_auth(chip)) {
> - tpm_buf_append_hmac_session(chip, &buf,
> + tpm_buf_append_hmac_session(chip, buf,
> TPM2_SA_ENCRYPT |
> TPM2_SA_CONTINUE_SESSION,
> NULL, 0);
> } else {
> - offset = buf.handles * 4 + TPM_HEADER_SIZE;
> - head = (struct tpm_header *)buf.data;
> - if (tpm_buf_length(&buf) == offset)
> + offset = buf->handles * 4 + TPM_HEADER_SIZE;
> + head = (struct tpm_header *)buf->data;
> + if (tpm_buf_length(buf) == offset)
> head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
> }
> - tpm_buf_append_u16(&buf, num_bytes);
> - err = tpm_buf_fill_hmac_session(chip, &buf);
> + tpm_buf_append_u16(buf, num_bytes);
> + err = tpm_buf_fill_hmac_session(chip, buf);
> if (err)
> - goto out;
> + return err;
>
> - err = tpm_transmit_cmd(chip, &buf,
> + err = tpm_transmit_cmd(chip, buf,
> offsetof(struct tpm2_get_random_out,
> buffer),
> "attempting get random");
> - err = tpm_buf_check_hmac_response(chip, &buf, err);
> + err = tpm_buf_check_hmac_response(chip, buf, err);
> if (err) {
> if (err > 0)
> err = -EIO;
> - goto out;
> + tpm2_end_auth_session(chip);
> + return err;
> }
>
> - head = (struct tpm_header *)buf.data;
> + head = (struct tpm_header *)buf->data;
> offset = TPM_HEADER_SIZE;
> /* Skip the parameter size field: */
> if (be16_to_cpu(head->tag) == TPM2_ST_SESSIONS)
> offset += 4;
>
> - out = (struct tpm2_get_random_out *)&buf.data[offset];
> + out = (struct tpm2_get_random_out *)&buf->data[offset];
> recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
> - if (tpm_buf_length(&buf) <
> + if (tpm_buf_length(buf) <
> TPM_HEADER_SIZE +
> offsetof(struct tpm2_get_random_out, buffer) +
> recd) {
> - err = -EFAULT;
> - goto out;
> + tpm2_end_auth_session(chip);
> + return -EFAULT;
> }
> memcpy(dest_ptr, out->buffer, recd);
>
> @@ -315,13 +318,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
> num_bytes -= recd;
> } while (retries-- && total < max);
>
> - tpm_buf_destroy(&buf);
> -
> return total ? total : -EIO;
> -out:
> - tpm_buf_destroy(&buf);
> - tpm2_end_auth_session(chip);
> - return err;
> }
>
> /**
> @@ -331,20 +328,18 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
> */
> void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
> {
> - struct tpm_buf buf;
> - int rc;
> -
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
> - if (rc) {
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
> handle);
> return;
> }
>
> - tpm_buf_append_u32(&buf, handle);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
> + tpm_buf_append_u32(buf, handle);
>
> - tpm_transmit_cmd(chip, &buf, 0, "flushing context");
> - tpm_buf_destroy(&buf);
> + tpm_transmit_cmd(chip, buf, 0, "flushing context");
> }
> EXPORT_SYMBOL_GPL(tpm2_flush_context);
>
> @@ -363,19 +358,21 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
> const char *desc)
> {
> struct tpm2_get_cap_out *out;
> - struct tpm_buf buf;
> int rc;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> - if (rc)
> - return rc;
> - tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES);
> - tpm_buf_append_u32(&buf, property_id);
> - tpm_buf_append_u32(&buf, 1);
> - rc = tpm_transmit_cmd(chip, &buf, 0, NULL);
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> + tpm_buf_append_u32(buf, TPM2_CAP_TPM_PROPERTIES);
> + tpm_buf_append_u32(buf, property_id);
> + tpm_buf_append_u32(buf, 1);
> + rc = tpm_transmit_cmd(chip, buf, 0, NULL);
> if (!rc) {
> out = (struct tpm2_get_cap_out *)
> - &buf.data[TPM_HEADER_SIZE];
> + &buf->data[TPM_HEADER_SIZE];
> /*
> * To prevent failing boot up of some systems, Infineon TPM2.0
> * returns SUCCESS on TPM2_Startup in field upgrade mode. Also
> @@ -387,7 +384,6 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
> else
> rc = -ENODATA;
> }
> - tpm_buf_destroy(&buf);
> return rc;
> }
> EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);
> @@ -404,15 +400,14 @@ EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);
> */
> void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
> {
> - struct tpm_buf buf;
> - int rc;
> -
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
> - if (rc)
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> return;
> - tpm_buf_append_u16(&buf, shutdown_type);
> - tpm_transmit_cmd(chip, &buf, 0, "stopping the TPM");
> - tpm_buf_destroy(&buf);
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
> + tpm_buf_append_u16(buf, shutdown_type);
> + tpm_transmit_cmd(chip, buf, 0, "stopping the TPM");
> }
>
> /**
> @@ -430,20 +425,21 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
> */
> static int tpm2_do_selftest(struct tpm_chip *chip)
> {
> - struct tpm_buf buf;
> int full;
> int rc;
>
> for (full = 0; full < 2; full++) {
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST);
> - if (rc)
> - return rc;
> + struct tpm_buf *buf __free(kfree) = NULL;
>
> - tpm_buf_append_u8(&buf, full);
> - rc = tpm_transmit_cmd(chip, &buf, 0,
> - "attempting the self test");
> - tpm_buf_destroy(&buf);
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST);
> + tpm_buf_append_u8(buf, full);
> + rc = tpm_transmit_cmd(chip, buf, 0,
> + "attempting the self test");
> if (rc == TPM2_RC_TESTING)
> rc = TPM2_RC_SUCCESS;
> if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS)
> @@ -468,23 +464,24 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
> int tpm2_probe(struct tpm_chip *chip)
> {
> struct tpm_header *out;
> - struct tpm_buf buf;
> int rc;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> - if (rc)
> - return rc;
> - tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES);
> - tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS);
> - tpm_buf_append_u32(&buf, 1);
> - rc = tpm_transmit_cmd(chip, &buf, 0, NULL);
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> + tpm_buf_append_u32(buf, TPM2_CAP_TPM_PROPERTIES);
> + tpm_buf_append_u32(buf, TPM_PT_TOTAL_COMMANDS);
> + tpm_buf_append_u32(buf, 1);
> + rc = tpm_transmit_cmd(chip, buf, 0, NULL);
> /* We ignore TPM return codes on purpose. */
> if (rc >= 0) {
> - out = (struct tpm_header *)buf.data;
> + out = (struct tpm_header *)buf->data;
> if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS)
> chip->flags |= TPM_CHIP_FLAG_TPM2;
> }
> - tpm_buf_destroy(&buf);
> return 0;
> }
> EXPORT_SYMBOL_GPL(tpm2_probe);
> @@ -518,7 +515,6 @@ static int tpm2_init_bank_info(struct tpm_chip *chip, u32 bank_index)
> ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
> {
> struct tpm2_pcr_selection pcr_selection;
> - struct tpm_buf buf;
> void *marker;
> void *end;
> void *pcr_select_offset;
> @@ -530,31 +526,32 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
> int rc;
> int i = 0;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> - if (rc)
> - return rc;
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - tpm_buf_append_u32(&buf, TPM2_CAP_PCRS);
> - tpm_buf_append_u32(&buf, 0);
> - tpm_buf_append_u32(&buf, 1);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> + tpm_buf_append_u32(buf, TPM2_CAP_PCRS);
> + tpm_buf_append_u32(buf, 0);
> + tpm_buf_append_u32(buf, 1);
>
> - rc = tpm_transmit_cmd(chip, &buf, 9, "get tpm pcr allocation");
> + rc = tpm_transmit_cmd(chip, buf, 9, "get tpm pcr allocation");
> if (rc)
> - goto out;
> + return rc;
>
> nr_possible_banks = be32_to_cpup(
> - (__be32 *)&buf.data[TPM_HEADER_SIZE + 5]);
> + (__be32 *)&buf->data[TPM_HEADER_SIZE + 5]);
> if (nr_possible_banks > TPM2_MAX_PCR_BANKS) {
> pr_err("tpm: out of bank capacity: %u > %u\n",
> nr_possible_banks, TPM2_MAX_PCR_BANKS);
> - rc = -ENOMEM;
> - goto out;
> + return -ENOMEM;
> }
>
> - marker = &buf.data[TPM_HEADER_SIZE + 9];
> + marker = &buf->data[TPM_HEADER_SIZE + 9];
>
> - rsp_len = be32_to_cpup((__be32 *)&buf.data[2]);
> - end = &buf.data[rsp_len];
> + rsp_len = be32_to_cpup((__be32 *)&buf->data[2]);
> + end = &buf->data[rsp_len];
>
> for (i = 0; i < nr_possible_banks; i++) {
> pcr_select_offset = marker +
> @@ -586,21 +583,20 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
> }
>
> chip->nr_allocated_banks = nr_alloc_banks;
> -out:
> - tpm_buf_destroy(&buf);
>
> return rc;
> }
>
> int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
> {
> - struct tpm_buf buf;
> u32 nr_commands;
> __be32 *attrs;
> u32 cc;
> int i;
> int rc;
>
> + struct tpm_buf *buf __free(kfree) = NULL;
> +
> rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL);
> if (rc)
> goto out;
> @@ -617,30 +613,31 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
> goto out;
> }
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> - if (rc)
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> + rc = -ENOMEM;
> goto out;
> + }
>
> - tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS);
> - tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
> - tpm_buf_append_u32(&buf, nr_commands);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
> + tpm_buf_append_u32(buf, TPM2_CAP_COMMANDS);
> + tpm_buf_append_u32(buf, TPM2_CC_FIRST);
> + tpm_buf_append_u32(buf, nr_commands);
>
> - rc = tpm_transmit_cmd(chip, &buf, 9 + 4 * nr_commands, NULL);
> - if (rc) {
> - tpm_buf_destroy(&buf);
> + rc = tpm_transmit_cmd(chip, buf, 9 + 4 * nr_commands, NULL);
> + if (rc)
> goto out;
> - }
>
> if (nr_commands !=
> - be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) {
> + be32_to_cpup((__be32 *)&buf->data[TPM_HEADER_SIZE + 5])) {
> rc = -EFAULT;
> - tpm_buf_destroy(&buf);
> goto out;
> }
>
> chip->nr_commands = nr_commands;
>
> - attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9];
> + attrs = (__be32 *)&buf->data[TPM_HEADER_SIZE + 9];
> for (i = 0; i < nr_commands; i++, attrs++) {
> chip->cc_attrs_tbl[i] = be32_to_cpup(attrs);
> cc = chip->cc_attrs_tbl[i] & 0xFFFF;
> @@ -652,8 +649,6 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
> }
> }
>
> - tpm_buf_destroy(&buf);
> -
> out:
> if (rc > 0)
> rc = -ENODEV;
> @@ -674,20 +669,18 @@ EXPORT_SYMBOL_GPL(tpm2_get_cc_attrs_tbl);
>
> static int tpm2_startup(struct tpm_chip *chip)
> {
> - struct tpm_buf buf;
> - int rc;
> + struct tpm_buf *buf __free(kfree) = NULL;
>
> dev_info(&chip->dev, "starting up the TPM manually\n");
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
> - if (rc < 0)
> - return rc;
> -
> - tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
> - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM");
> - tpm_buf_destroy(&buf);
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - return rc;
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
> + tpm_buf_append_u16(buf, TPM2_SU_CLEAR);
> + return tpm_transmit_cmd(chip, buf, 0, "attempting to start the TPM");
> }
>
> /**
> diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
> index 0d89643e6880..cf8f1fd6790b 100644
> --- a/drivers/char/tpm/tpm2-sessions.c
> +++ b/drivers/char/tpm/tpm2-sessions.c
> @@ -167,8 +167,8 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
> {
> u32 mso = tpm2_handle_mso(handle);
> off_t offset = TPM_HEADER_SIZE;
> + struct tpm_buf *buf __free(kfree) = NULL;
> int rc, name_size_alg;
> - struct tpm_buf buf;
>
> if (mso != TPM2_MSO_PERSISTENT && mso != TPM2_MSO_VOLATILE &&
> mso != TPM2_MSO_NVRAM) {
> @@ -176,50 +176,40 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
> return sizeof(u32);
> }
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
> - if (rc)
> - return rc;
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - tpm_buf_append_u32(&buf, handle);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
> + tpm_buf_append_u32(buf, handle);
>
> - rc = tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic");
> - if (rc) {
> - tpm_buf_destroy(&buf);
> + rc = tpm_transmit_cmd(chip, buf, 0, "TPM2_ReadPublic");
> + if (rc)
> return tpm_ret_to_err(rc);
> - }
>
> /* Skip TPMT_PUBLIC: */
> - offset += tpm_buf_read_u16(&buf, &offset);
> + offset += tpm_buf_read_u16(buf, &offset);
>
> /*
> * Ensure space for the length field of TPM2B_NAME and hashAlg field of
> * TPMT_HA (the extra four bytes).
> */
> - if (offset + 4 > tpm_buf_length(&buf)) {
> - tpm_buf_destroy(&buf);
> + if (offset + 4 > tpm_buf_length(buf))
> return -EIO;
> - }
>
> - rc = tpm_buf_read_u16(&buf, &offset);
> - name_size_alg = name_size(&buf.data[offset]);
> -
> - if (name_size_alg < 0) {
> - tpm_buf_destroy(&buf);
> + rc = tpm_buf_read_u16(buf, &offset);
> + name_size_alg = name_size(&buf->data[offset]);
> + if (name_size_alg < 0)
> return name_size_alg;
> - }
>
> - if (rc != name_size_alg) {
> - tpm_buf_destroy(&buf);
> + if (rc != name_size_alg)
> return -EIO;
> - }
>
> - if (offset + rc > tpm_buf_length(&buf)) {
> - tpm_buf_destroy(&buf);
> + if (offset + rc > tpm_buf_length(buf))
> return -EIO;
> - }
>
> - memcpy(name, &buf.data[offset], rc);
> - tpm_buf_destroy(&buf);
> + memcpy(name, &buf->data[offset], rc);
> return name_size_alg;
> }
> #endif /* CONFIG_TCG_TPM2_HMAC */
> @@ -1005,8 +995,8 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
> */
> int tpm2_start_auth_session(struct tpm_chip *chip)
> {
> + struct tpm_buf *buf __free(kfree) = NULL;
> struct tpm2_auth *auth;
> - struct tpm_buf buf;
> u32 null_key;
> int rc;
>
> @@ -1020,58 +1010,61 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
> return -ENOMEM;
>
> rc = tpm2_load_null(chip, &null_key);
> - if (rc)
> - goto out;
> + if (rc) {
> + kfree_sensitive(auth);
> + return rc;
> + }
>
> auth->session = TPM_HEADER_SIZE;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS);
> - if (rc)
> - goto out;
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> + kfree_sensitive(auth);
> + return -ENOMEM;
> + }
>
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS);
> /* salt key handle */
> - tpm_buf_append_u32(&buf, null_key);
> + tpm_buf_append_u32(buf, null_key);
> /* bind key handle */
> - tpm_buf_append_u32(&buf, TPM2_RH_NULL);
> + tpm_buf_append_u32(buf, TPM2_RH_NULL);
> /* nonce caller */
> get_random_bytes(auth->our_nonce, sizeof(auth->our_nonce));
> - tpm_buf_append_u16(&buf, sizeof(auth->our_nonce));
> - tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce));
> + tpm_buf_append_u16(buf, sizeof(auth->our_nonce));
> + tpm_buf_append(buf, auth->our_nonce, sizeof(auth->our_nonce));
>
> /* append encrypted salt and squirrel away unencrypted in auth */
> - rc = tpm_buf_append_salt(&buf, chip, auth);
> + rc = tpm_buf_append_salt(buf, chip, auth);
> if (rc) {
> tpm2_flush_context(chip, null_key);
> - tpm_buf_destroy(&buf);
> - goto out;
> + kfree_sensitive(auth);
> + return rc;
> }
> /* session type (HMAC, audit or policy) */
> - tpm_buf_append_u8(&buf, TPM2_SE_HMAC);
> + tpm_buf_append_u8(buf, TPM2_SE_HMAC);
>
> /* symmetric encryption parameters */
> /* symmetric algorithm */
> - tpm_buf_append_u16(&buf, TPM_ALG_AES);
> + tpm_buf_append_u16(buf, TPM_ALG_AES);
> /* bits for symmetric algorithm */
> - tpm_buf_append_u16(&buf, AES_KEY_BITS);
> + tpm_buf_append_u16(buf, AES_KEY_BITS);
> /* symmetric algorithm mode (must be CFB) */
> - tpm_buf_append_u16(&buf, TPM_ALG_CFB);
> + tpm_buf_append_u16(buf, TPM_ALG_CFB);
> /* hash algorithm for session */
> - tpm_buf_append_u16(&buf, TPM_ALG_SHA256);
> + tpm_buf_append_u16(buf, TPM_ALG_SHA256);
>
> - rc = tpm_ret_to_err(tpm_transmit_cmd(chip, &buf, 0, "StartAuthSession"));
> + rc = tpm_ret_to_err(tpm_transmit_cmd(chip, buf, 0, "StartAuthSession"));
> tpm2_flush_context(chip, null_key);
>
> if (rc == TPM2_RC_SUCCESS)
> - rc = tpm2_parse_start_auth_session(auth, &buf);
> -
> - tpm_buf_destroy(&buf);
> + rc = tpm2_parse_start_auth_session(auth, buf);
>
> if (rc == TPM2_RC_SUCCESS) {
> chip->auth = auth;
> return 0;
> }
>
> -out:
> kfree_sensitive(auth);
> return rc;
> }
> @@ -1285,19 +1278,21 @@ static int tpm2_parse_create_primary(struct tpm_chip *chip, struct tpm_buf *buf,
> static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
> u32 *handle, u8 *name)
> {
> + struct tpm_buf *template __free(kfree) = NULL;
> + struct tpm_buf *buf __free(kfree) = NULL;
> int rc;
> - struct tpm_buf buf;
> - struct tpm_buf template;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY);
> - if (rc)
> - return rc;
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
>
> - rc = tpm_buf_init_sized(&template);
> - if (rc) {
> - tpm_buf_destroy(&buf);
> - return rc;
> - }
> + template = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!template)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY);
> + tpm_buf_init_sized(template, TPM_BUFSIZE);
>
> /*
> * create the template. Note: in order for userspace to
> @@ -1309,75 +1304,72 @@ static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
> */
>
> /* key type */
> - tpm_buf_append_u16(&template, TPM_ALG_ECC);
> + tpm_buf_append_u16(template, TPM_ALG_ECC);
>
> /* name algorithm */
> - tpm_buf_append_u16(&template, TPM_ALG_SHA256);
> + tpm_buf_append_u16(template, TPM_ALG_SHA256);
>
> /* object properties */
> - tpm_buf_append_u32(&template, TPM2_OA_NULL_KEY);
> + tpm_buf_append_u32(template, TPM2_OA_NULL_KEY);
>
> /* sauth policy (empty) */
> - tpm_buf_append_u16(&template, 0);
> + tpm_buf_append_u16(template, 0);
>
> /* BEGIN parameters: key specific; for ECC*/
>
> /* symmetric algorithm */
> - tpm_buf_append_u16(&template, TPM_ALG_AES);
> + tpm_buf_append_u16(template, TPM_ALG_AES);
>
> /* bits for symmetric algorithm */
> - tpm_buf_append_u16(&template, AES_KEY_BITS);
> + tpm_buf_append_u16(template, AES_KEY_BITS);
>
> /* algorithm mode (must be CFB) */
> - tpm_buf_append_u16(&template, TPM_ALG_CFB);
> + tpm_buf_append_u16(template, TPM_ALG_CFB);
>
> /* scheme (NULL means any scheme) */
> - tpm_buf_append_u16(&template, TPM_ALG_NULL);
> + tpm_buf_append_u16(template, TPM_ALG_NULL);
>
> /* ECC Curve ID */
> - tpm_buf_append_u16(&template, TPM2_ECC_NIST_P256);
> + tpm_buf_append_u16(template, TPM2_ECC_NIST_P256);
>
> /* KDF Scheme */
> - tpm_buf_append_u16(&template, TPM_ALG_NULL);
> + tpm_buf_append_u16(template, TPM_ALG_NULL);
>
> /* unique: key specific; for ECC it is two zero size points */
> - tpm_buf_append_u16(&template, 0);
> - tpm_buf_append_u16(&template, 0);
> + tpm_buf_append_u16(template, 0);
> + tpm_buf_append_u16(template, 0);
>
> /* END parameters */
>
> /* primary handle */
> - tpm_buf_append_u32(&buf, hierarchy);
> - tpm_buf_append_empty_auth(&buf, TPM2_RS_PW);
> + tpm_buf_append_u32(buf, hierarchy);
> + tpm_buf_append_empty_auth(buf, TPM2_RS_PW);
>
> /* sensitive create size is 4 for two empty buffers */
> - tpm_buf_append_u16(&buf, 4);
> + tpm_buf_append_u16(buf, 4);
>
> /* sensitive create auth data (empty) */
> - tpm_buf_append_u16(&buf, 0);
> + tpm_buf_append_u16(buf, 0);
>
> /* sensitive create sensitive data (empty) */
> - tpm_buf_append_u16(&buf, 0);
> + tpm_buf_append_u16(buf, 0);
>
> /* the public template */
> - tpm_buf_append(&buf, template.data, template.length);
> - tpm_buf_destroy(&template);
> + tpm_buf_append(buf, template->data, template->length);
>
> /* outside info (empty) */
> - tpm_buf_append_u16(&buf, 0);
> + tpm_buf_append_u16(buf, 0);
>
> /* creation PCR (none) */
> - tpm_buf_append_u32(&buf, 0);
> + tpm_buf_append_u32(buf, 0);
>
> - rc = tpm_transmit_cmd(chip, &buf, 0,
> + rc = tpm_transmit_cmd(chip, buf, 0,
> "attempting to create NULL primary");
>
> if (rc == TPM2_RC_SUCCESS)
> - rc = tpm2_parse_create_primary(chip, &buf, handle, hierarchy,
> + rc = tpm2_parse_create_primary(chip, buf, handle, hierarchy,
> name);
>
> - tpm_buf_destroy(&buf);
> -
> return rc;
> }
>
> diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> index 7c1c0a174a2b..5b0f233db898 100644
> --- a/drivers/char/tpm/tpm2-space.c
> +++ b/drivers/char/tpm/tpm2-space.c
> @@ -58,24 +58,25 @@ void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space)
> int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
> unsigned int *offset, u32 *handle)
> {
> - struct tpm_buf tbuf;
> struct tpm2_context *ctx;
> unsigned int body_size;
> int rc;
>
> - rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
> - if (rc)
> - return rc;
> + struct tpm_buf *tbuf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!tbuf)
> + return -ENOMEM;
> +
> + tpm_buf_init(tbuf, TPM_BUFSIZE);
> + tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
>
> ctx = (struct tpm2_context *)&buf[*offset];
> body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
> - tpm_buf_append(&tbuf, &buf[*offset], body_size);
> + tpm_buf_append(tbuf, &buf[*offset], body_size);
>
> - rc = tpm_transmit_cmd(chip, &tbuf, 4, NULL);
> + rc = tpm_transmit_cmd(chip, tbuf, 4, NULL);
> if (rc < 0) {
> dev_warn(&chip->dev, "%s: failed with a system error %d\n",
> __func__, rc);
> - tpm_buf_destroy(&tbuf);
> return -EFAULT;
> } else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE ||
> rc == TPM2_RC_REFERENCE_H0) {
> @@ -90,64 +91,55 @@ int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
> * flushed outside the space
> */
> *handle = 0;
> - tpm_buf_destroy(&tbuf);
> return -ENOENT;
> } else if (tpm2_rc_value(rc) == TPM2_RC_INTEGRITY) {
> - tpm_buf_destroy(&tbuf);
> return -EINVAL;
> } else if (rc > 0) {
> dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
> __func__, rc);
> - tpm_buf_destroy(&tbuf);
> return -EFAULT;
> }
>
> - *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]);
> + *handle = be32_to_cpup((__be32 *)&tbuf->data[TPM_HEADER_SIZE]);
> *offset += body_size;
> -
> - tpm_buf_destroy(&tbuf);
> return 0;
> }
>
> int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
> unsigned int buf_size, unsigned int *offset)
> {
> - struct tpm_buf tbuf;
> unsigned int body_size;
> int rc;
>
> - rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);
> - if (rc)
> - return rc;
> + struct tpm_buf *tbuf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!tbuf)
> + return -ENOMEM;
>
> - tpm_buf_append_u32(&tbuf, handle);
> + tpm_buf_init(tbuf, TPM_BUFSIZE);
> + tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);
> + tpm_buf_append_u32(tbuf, handle);
>
> - rc = tpm_transmit_cmd(chip, &tbuf, 0, NULL);
> + rc = tpm_transmit_cmd(chip, tbuf, 0, NULL);
> if (rc < 0) {
> dev_warn(&chip->dev, "%s: failed with a system error %d\n",
> __func__, rc);
> - tpm_buf_destroy(&tbuf);
> return -EFAULT;
> } else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) {
> - tpm_buf_destroy(&tbuf);
> return -ENOENT;
> } else if (rc) {
> dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
> __func__, rc);
> - tpm_buf_destroy(&tbuf);
> return -EFAULT;
> }
>
> - body_size = tpm_buf_length(&tbuf) - TPM_HEADER_SIZE;
> + body_size = tpm_buf_length(tbuf) - TPM_HEADER_SIZE;
> if ((*offset + body_size) > buf_size) {
> dev_warn(&chip->dev, "%s: out of backing storage\n", __func__);
> - tpm_buf_destroy(&tbuf);
> return -ENOMEM;
> }
>
> - memcpy(&buf[*offset], &tbuf.data[TPM_HEADER_SIZE], body_size);
> + memcpy(&buf[*offset], &tbuf->data[TPM_HEADER_SIZE], body_size);
> *offset += body_size;
> - tpm_buf_destroy(&tbuf);
> return 0;
> }
>
> diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c
> index 7bb0f4d4a2ed..b81fd2a537df 100644
> --- a/drivers/char/tpm/tpm_vtpm_proxy.c
> +++ b/drivers/char/tpm/tpm_vtpm_proxy.c
> @@ -395,40 +395,36 @@ static bool vtpm_proxy_tpm_req_canceled(struct tpm_chip *chip, u8 status)
>
> static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality)
> {
> - struct tpm_buf buf;
> int rc;
> const struct tpm_header *header;
> struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev);
>
> + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + tpm_buf_init(buf, TPM_BUFSIZE);
> if (chip->flags & TPM_CHIP_FLAG_TPM2)
> - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS,
> - TPM2_CC_SET_LOCALITY);
> + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_SET_LOCALITY);
> else
> - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND,
> - TPM_ORD_SET_LOCALITY);
> - if (rc)
> - return rc;
> - tpm_buf_append_u8(&buf, locality);
> + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SET_LOCALITY);
> +
> + tpm_buf_append_u8(buf, locality);
>
> proxy_dev->state |= STATE_DRIVER_COMMAND;
>
> - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to set locality");
> + rc = tpm_transmit_cmd(chip, buf, 0, "attempting to set locality");
>
> proxy_dev->state &= ~STATE_DRIVER_COMMAND;
>
> - if (rc < 0) {
> - locality = rc;
> - goto out;
> - }
> + if (rc < 0)
> + return rc;
>
> - header = (const struct tpm_header *)buf.data;
> + header = (const struct tpm_header *)buf->data;
> rc = be32_to_cpu(header->return_code);
> if (rc)
> locality = -1;
>
> -out:
> - tpm_buf_destroy(&buf);
> -
> return locality;
> }
>
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index b357f8971d03..598dd53a10d8 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -208,13 +208,15 @@ enum tpm_buf_flags {
> };
>
> /*
> - * A string buffer type for constructing TPM commands.
> + * A buffer for constructing and parsing TPM commands, responses and sized
> + * (TPM2B) buffers.
> */
> struct tpm_buf {
> - u32 flags;
> - u32 length;
> - u8 *data;
> + u8 flags;
> + u16 length;
> + u16 capacity;
> u8 handles;
> + u8 data[];
> };
>
> struct tpm2_hash {
> @@ -222,12 +224,11 @@ struct tpm2_hash {
> unsigned int tpm_id;
> };
>
> -int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal);
> +void tpm_buf_init(struct tpm_buf *buf, u16 buf_size);
> +void tpm_buf_init_sized(struct tpm_buf *buf, u16 buf_size);
> void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal);
> -int tpm_buf_init_sized(struct tpm_buf *buf);
> void tpm_buf_reset_sized(struct tpm_buf *buf);
> -void tpm_buf_destroy(struct tpm_buf *buf);
> -u32 tpm_buf_length(struct tpm_buf *buf);
> +u16 tpm_buf_length(struct tpm_buf *buf);
> void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length);
> void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value);
> void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value);
> diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
> index 331b1bad6581..d27c846bb90a 100644
> --- a/security/keys/trusted-keys/trusted_tpm1.c
> +++ b/security/keys/trusted-keys/trusted_tpm1.c
> @@ -316,9 +316,8 @@ static int TSS_checkhmac2(unsigned char *buffer,
> * For key specific tpm requests, we will generate and send our
> * own TPM command packets using the drivers send function.
> */
> -static int trusted_tpm_send(unsigned char *cmd, size_t buflen)
> +static int trusted_tpm_send(struct tpm_buf *buf)
> {
> - struct tpm_buf buf;
> int rc;
>
> if (!chip)
> @@ -328,12 +327,9 @@ static int trusted_tpm_send(unsigned char *cmd, size_t buflen)
> if (rc)
> return rc;
>
> - buf.flags = 0;
> - buf.length = buflen;
> - buf.data = cmd;
> - dump_tpm_buf(cmd);
> - rc = tpm_transmit_cmd(chip, &buf, 4, "sending data");
> - dump_tpm_buf(cmd);
> + dump_tpm_buf(buf->data);
> + rc = tpm_transmit_cmd(chip, buf, 4, "sending data");
> + dump_tpm_buf(buf->data);
>
> if (rc > 0)
> /* TPM error */
> @@ -379,7 +375,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
> tpm_buf_append_u32(tb, handle);
> tpm_buf_append(tb, ononce, TPM_NONCE_SIZE);
>
> - ret = trusted_tpm_send(tb->data, tb->length);
> + ret = trusted_tpm_send(tb);
> if (ret < 0)
> return ret;
>
> @@ -403,7 +399,7 @@ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
> return -ENODEV;
>
> tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP);
> - ret = trusted_tpm_send(tb->data, tb->length);
> + ret = trusted_tpm_send(tb);
> if (ret < 0)
> return ret;
>
> @@ -512,7 +508,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
> tpm_buf_append_u8(tb, cont);
> tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE);
>
> - ret = trusted_tpm_send(tb->data, tb->length);
> + ret = trusted_tpm_send(tb);
> if (ret < 0)
> goto out;
>
> @@ -603,7 +599,7 @@ static int tpm_unseal(struct tpm_buf *tb,
> tpm_buf_append_u8(tb, cont);
> tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE);
>
> - ret = trusted_tpm_send(tb->data, tb->length);
> + ret = trusted_tpm_send(tb);
> if (ret < 0) {
> pr_info("authhmac failed (%d)\n", ret);
> return ret;
> @@ -630,23 +626,23 @@ static int tpm_unseal(struct tpm_buf *tb,
> static int key_seal(struct trusted_key_payload *p,
> struct trusted_key_options *o)
> {
> - struct tpm_buf tb;
> int ret;
>
> - ret = tpm_buf_init(&tb, 0, 0);
> - if (ret)
> - return ret;
> + struct tpm_buf *tb __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!tb)
> + return -ENOMEM;
> +
> + tpm_buf_init(tb, TPM_BUFSIZE);
>
> /* include migratable flag at end of sealed key */
> p->key[p->key_len] = p->migratable;
>
> - ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,
> + ret = tpm_seal(tb, o->keytype, o->keyhandle, o->keyauth,
> p->key, p->key_len + 1, p->blob, &p->blob_len,
> o->blobauth, o->pcrinfo, o->pcrinfo_len);
> if (ret < 0)
> pr_info("srkseal failed (%d)\n", ret);
>
> - tpm_buf_destroy(&tb);
> return ret;
> }
>
> @@ -656,14 +652,15 @@ static int key_seal(struct trusted_key_payload *p,
> static int key_unseal(struct trusted_key_payload *p,
> struct trusted_key_options *o)
> {
> - struct tpm_buf tb;
> int ret;
>
> - ret = tpm_buf_init(&tb, 0, 0);
> - if (ret)
> - return ret;
> + struct tpm_buf *tb __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!tb)
> + return -ENOMEM;
> +
> + tpm_buf_init(tb, TPM_BUFSIZE);
>
> - ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
> + ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
> o->blobauth, p->key, &p->key_len);
> if (ret < 0)
> pr_info("srkunseal failed (%d)\n", ret);
> @@ -671,7 +668,6 @@ static int key_unseal(struct trusted_key_payload *p,
> /* pull migratable flag out of sealed key */
> p->migratable = p->key[--p->key_len];
>
> - tpm_buf_destroy(&tb);
> return ret;
> }
>
> diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
> index 779a2e66ac20..67225dd562a9 100644
> --- a/security/keys/trusted-keys/trusted_tpm2.c
> +++ b/security/keys/trusted-keys/trusted_tpm2.c
> @@ -233,7 +233,8 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
> struct trusted_key_options *options)
> {
> off_t offset = TPM_HEADER_SIZE;
> - struct tpm_buf buf, sized;
> + struct tpm_buf *buf __free(kfree) = NULL;
> + struct tpm_buf *sized __free(kfree) = NULL;
> int blob_len = 0;
> int hash;
> u32 flags;
> @@ -254,97 +255,100 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
> if (rc)
> goto out_put;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
> - if (rc) {
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> + rc = -ENOMEM;
> tpm2_end_auth_session(chip);
> goto out_put;
> }
>
> - rc = tpm_buf_init_sized(&sized);
> - if (rc) {
> - tpm_buf_destroy(&buf);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
> +
> + sized = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!sized) {
> + rc = -ENOMEM;
> tpm2_end_auth_session(chip);
> goto out_put;
> }
>
> - rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
> + tpm_buf_init_sized(sized, TPM_BUFSIZE);
> +
> + rc = tpm_buf_append_name(chip, buf, options->keyhandle, NULL);
> if (rc)
> goto out;
>
> - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
> + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_DECRYPT,
> options->keyauth, TPM_DIGEST_SIZE);
>
> /* sensitive */
> - tpm_buf_append_u16(&sized, options->blobauth_len);
> + tpm_buf_append_u16(sized, options->blobauth_len);
>
> if (options->blobauth_len)
> - tpm_buf_append(&sized, options->blobauth, options->blobauth_len);
> + tpm_buf_append(sized, options->blobauth, options->blobauth_len);
>
> - tpm_buf_append_u16(&sized, payload->key_len);
> - tpm_buf_append(&sized, payload->key, payload->key_len);
> - tpm_buf_append(&buf, sized.data, sized.length);
> + tpm_buf_append_u16(sized, payload->key_len);
> + tpm_buf_append(sized, payload->key, payload->key_len);
> + tpm_buf_append(buf, sized->data, sized->length);
>
> /* public */
> - tpm_buf_reset_sized(&sized);
> - tpm_buf_append_u16(&sized, TPM_ALG_KEYEDHASH);
> - tpm_buf_append_u16(&sized, hash);
> + tpm_buf_reset_sized(sized);
> + tpm_buf_append_u16(sized, TPM_ALG_KEYEDHASH);
> + tpm_buf_append_u16(sized, hash);
>
> /* key properties */
> flags = 0;
> flags |= options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH;
> flags |= payload->migratable ? 0 : (TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_PARENT);
> - tpm_buf_append_u32(&sized, flags);
> + tpm_buf_append_u32(sized, flags);
>
> /* policy */
> - tpm_buf_append_u16(&sized, options->policydigest_len);
> + tpm_buf_append_u16(sized, options->policydigest_len);
> if (options->policydigest_len)
> - tpm_buf_append(&sized, options->policydigest, options->policydigest_len);
> + tpm_buf_append(sized, options->policydigest, options->policydigest_len);
>
> /* public parameters */
> - tpm_buf_append_u16(&sized, TPM_ALG_NULL);
> - tpm_buf_append_u16(&sized, 0);
> + tpm_buf_append_u16(sized, TPM_ALG_NULL);
> + tpm_buf_append_u16(sized, 0);
>
> - tpm_buf_append(&buf, sized.data, sized.length);
> + tpm_buf_append(buf, sized->data, sized->length);
>
> /* outside info */
> - tpm_buf_append_u16(&buf, 0);
> + tpm_buf_append_u16(buf, 0);
>
> /* creation PCR */
> - tpm_buf_append_u32(&buf, 0);
> + tpm_buf_append_u32(buf, 0);
>
> - if (buf.flags & TPM_BUF_INVALID) {
> + if (buf->flags & TPM_BUF_INVALID) {
> rc = -E2BIG;
> tpm2_end_auth_session(chip);
> goto out;
> }
>
> - rc = tpm_buf_fill_hmac_session(chip, &buf);
> + rc = tpm_buf_fill_hmac_session(chip, buf);
> if (rc)
> goto out;
>
> - rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
> - rc = tpm_buf_check_hmac_response(chip, &buf, rc);
> + rc = tpm_transmit_cmd(chip, buf, 4, "sealing data");
> + rc = tpm_buf_check_hmac_response(chip, buf, rc);
> if (rc)
> goto out;
>
> - blob_len = tpm_buf_read_u32(&buf, &offset);
> - if (blob_len > MAX_BLOB_SIZE || buf.flags & TPM_BUF_INVALID) {
> + blob_len = tpm_buf_read_u32(buf, &offset);
> + if (blob_len > MAX_BLOB_SIZE || buf->flags & TPM_BUF_INVALID) {
> rc = -E2BIG;
> goto out;
> }
> - if (buf.length - offset < blob_len) {
> + if (buf->length - offset < blob_len) {
> rc = -EFAULT;
> goto out;
> }
>
> - blob_len = tpm2_key_encode(payload, options, &buf.data[offset], blob_len);
> + blob_len = tpm2_key_encode(payload, options, &buf->data[offset], blob_len);
> if (blob_len < 0)
> rc = blob_len;
>
> out:
> - tpm_buf_destroy(&sized);
> - tpm_buf_destroy(&buf);
> -
> if (!rc)
> payload->blob_len = blob_len;
>
> @@ -372,7 +376,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
> u32 *blob_handle)
> {
> u8 *blob_ref __free(kfree) = NULL;
> - struct tpm_buf buf;
> + struct tpm_buf *buf __free(kfree) = NULL;
> unsigned int private_len;
> unsigned int public_len;
> unsigned int blob_len;
> @@ -426,39 +430,38 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
> if (rc)
> return rc;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
> - if (rc) {
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> tpm2_end_auth_session(chip);
> - return rc;
> + return -ENOMEM;
> }
>
> - rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
> +
> + rc = tpm_buf_append_name(chip, buf, options->keyhandle, NULL);
> if (rc)
> - goto out;
> + return rc;
>
> - tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
> + tpm_buf_append_hmac_session(chip, buf, 0, options->keyauth,
> TPM_DIGEST_SIZE);
>
> - tpm_buf_append(&buf, blob, blob_len);
> + tpm_buf_append(buf, blob, blob_len);
>
> - if (buf.flags & TPM_BUF_INVALID) {
> - rc = -E2BIG;
> + if (buf->flags & TPM_BUF_INVALID) {
> tpm2_end_auth_session(chip);
> - goto out;
> + return -E2BIG;
> }
>
> - rc = tpm_buf_fill_hmac_session(chip, &buf);
> + rc = tpm_buf_fill_hmac_session(chip, buf);
> if (rc)
> - goto out;
> + return rc;
>
> - rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
> - rc = tpm_buf_check_hmac_response(chip, &buf, rc);
> + rc = tpm_transmit_cmd(chip, buf, 4, "loading blob");
> + rc = tpm_buf_check_hmac_response(chip, buf, rc);
> if (!rc)
> *blob_handle = be32_to_cpup(
> - (__be32 *) &buf.data[TPM_HEADER_SIZE]);
> -
> -out:
> - tpm_buf_destroy(&buf);
> + (__be32 *)&buf->data[TPM_HEADER_SIZE]);
>
> return tpm_ret_to_err(rc);
> }
> @@ -481,7 +484,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
> u32 blob_handle)
> {
> struct tpm_header *head;
> - struct tpm_buf buf;
> + struct tpm_buf *buf __free(kfree) = NULL;
> u16 data_len;
> int offset;
> u8 *data;
> @@ -491,18 +494,21 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
> if (rc)
> return rc;
>
> - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
> - if (rc) {
> + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
> + if (!buf) {
> tpm2_end_auth_session(chip);
> - return rc;
> + return -ENOMEM;
> }
>
> - rc = tpm_buf_append_name(chip, &buf, blob_handle, NULL);
> + tpm_buf_init(buf, TPM_BUFSIZE);
> + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
> +
> + rc = tpm_buf_append_name(chip, buf, blob_handle, NULL);
> if (rc)
> - goto out;
> + return rc;
>
> if (!options->policyhandle) {
> - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
> + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_ENCRYPT,
> options->blobauth,
> options->blobauth_len);
> } else {
> @@ -517,39 +523,36 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
> * could repeat our actions with the exfiltrated
> * password.
> */
> - tpm2_buf_append_auth(&buf, options->policyhandle,
> + tpm2_buf_append_auth(buf, options->policyhandle,
> NULL /* nonce */, 0, 0,
> options->blobauth, options->blobauth_len);
> if (tpm2_chip_auth(chip)) {
> - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0);
> + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_ENCRYPT,
> + NULL, 0);
> } else {
> - offset = buf.handles * 4 + TPM_HEADER_SIZE;
> - head = (struct tpm_header *)buf.data;
> - if (tpm_buf_length(&buf) == offset)
> + offset = buf->handles * 4 + TPM_HEADER_SIZE;
> + head = (struct tpm_header *)buf->data;
> + if (tpm_buf_length(buf) == offset)
> head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
> }
> }
>
> - rc = tpm_buf_fill_hmac_session(chip, &buf);
> + rc = tpm_buf_fill_hmac_session(chip, buf);
> if (rc)
> - goto out;
> + return rc;
>
> - rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
> - rc = tpm_buf_check_hmac_response(chip, &buf, rc);
> + rc = tpm_transmit_cmd(chip, buf, 6, "unsealing");
> + rc = tpm_buf_check_hmac_response(chip, buf, rc);
>
> if (!rc) {
> data_len = be16_to_cpup(
> - (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
> - if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE) {
> - rc = -EFAULT;
> - goto out;
> - }
> + (__be16 *)&buf->data[TPM_HEADER_SIZE + 4]);
> + if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE)
> + return -EFAULT;
>
> - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) {
> - rc = -EFAULT;
> - goto out;
> - }
> - data = &buf.data[TPM_HEADER_SIZE + 6];
> + if (tpm_buf_length(buf) < TPM_HEADER_SIZE + 6 + data_len)
> + return -EFAULT;
> + data = &buf->data[TPM_HEADER_SIZE + 6];
>
> if (payload->old_format) {
> /* migratable flag is at the end of the key */
> @@ -566,8 +569,6 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
> }
> }
>
> -out:
> - tpm_buf_destroy(&buf);
> return tpm_ret_to_err(rc);
> }
>
> --
> 2.55.0
>
https://lore.kernel.org/linux-integrity/20260522013555.1063716-1-jarkko@kernel.org/#t
This is the most recent version. I would merge it by itself but the
lack of review feedback has prevented it. Just making a remark.
BR, Jarkko
next prev parent reply other threads:[~2026-07-11 18:15 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-11 16:01 [PATCH v2 00/10] tpm: Reorganize public headers and extract tpm-buf for standalone reuse Ross Philipson
2026-07-11 16:01 ` [PATCH v2 01/10] tpm: Initial step to reorganize TPM public headers Ross Philipson
2026-07-11 16:01 ` [PATCH v2 02/10] tpm: Move TPM1 specific definitions to the command header Ross Philipson
2026-07-11 16:01 ` [PATCH v2 03/10] tpm: Move TPM2 " Ross Philipson
2026-07-11 16:01 ` [PATCH v2 04/10] tpm: Move TPM common base " Ross Philipson
2026-07-11 16:01 ` [PATCH v2 05/10] tpm: Move platform specific definitions to the new PTP header Ross Philipson
2026-07-11 16:01 ` [PATCH v2 06/10] tpm: Remove main TPM header from TPM event log header Ross Philipson
2026-07-11 16:01 ` [PATCH v2 07/10] tpm-buf: Merge TPM_BUF_BOUNDARY_ERROR and TPM_BUF_OVERFLOW Ross Philipson
2026-07-11 16:01 ` [PATCH v2 08/10] tpm-buf: Remove chip parameter from tpm_buf_append_handle() Ross Philipson
2026-07-11 16:01 ` [PATCH v2 09/10] tpm-buf: Memory-safe allocations Ross Philipson
2026-07-11 18:15 ` Jarkko Sakkinen [this message]
2026-07-11 16:01 ` [PATCH v2 10/10] tpm-buf: Add TPM buffer support header for standalone reuse Ross Philipson
2026-07-11 18:18 ` Jarkko Sakkinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alKIV4oyQPu_BWaC@kernel.org \
--to=jarkko@kernel.org \
--cc=James.Bottomley@hansenpartnership.com \
--cc=andrew.cooper3@citrix.com \
--cc=ardb@kernel.org \
--cc=bp@alien8.de \
--cc=corbet@lwn.net \
--cc=daniel.kiper@oracle.com \
--cc=dave.hansen@linux.intel.com \
--cc=davem@davemloft.net \
--cc=dpsmith@apertussolutions.com \
--cc=herbert@gondor.apana.org.au \
--cc=hpa@zytor.com \
--cc=kanth.ghatraju@oracle.com \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=mingo@redhat.com \
--cc=mjg59@srcf.ucam.org \
--cc=peterhuewe@gmx.de \
--cc=ross.philipson@gmail.com \
--cc=tglx@linutronix.de \
--cc=trenchboot-devel@googlegroups.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.