All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] tpm: Cleanup class for tpm_buf
@ 2025-06-26 10:19 Jarkko Sakkinen
  2025-06-26 14:50 ` James Bottomley
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Jarkko Sakkinen @ 2025-06-26 10:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: keyrings, Jarkko Sakkinen, Peter Huewe, Jarkko Sakkinen,
	Jason Gunthorpe, James Bottomley, Mimi Zohar, David Howells,
	Paul Moore, James Morris, Serge E. Hallyn,
	open list:TPM DEVICE DRIVER, open list:SECURITY SUBSYSTEM

From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>

Create a cleanup class for struct tpm_buf using DEFINE_CLASS(), which will
guarantee that the heap allocated memory will be freed automatically for
the transient instances of this structure, when they go out of scope.

Wrap this all into help macro CLASS_TPM_BUF().

A TPM buffer can now be declared trivially:

    CLASS_TPM_BUF(buf, buf_size);

Before use caller needs to check that `buf` is not NULL, but other that
there are no other memory management responsibilities.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
---
v2:
- Implement also memory allocation using the cleanup class.
- Rewrote the commit message.
- Implemented CLASS_TPM_BUF() helper macro.
---
 drivers/char/tpm/tpm-buf.c                |  63 +++---
 drivers/char/tpm/tpm-sysfs.c              |  19 +-
 drivers/char/tpm/tpm1-cmd.c               | 144 ++++++------
 drivers/char/tpm/tpm2-cmd.c               | 261 ++++++++++------------
 drivers/char/tpm/tpm2-sessions.c          | 116 +++++-----
 drivers/char/tpm/tpm2-space.c             |  42 ++--
 drivers/char/tpm/tpm_vtpm_proxy.c         |  29 +--
 include/linux/tpm.h                       |  20 +-
 security/keys/trusted-keys/trusted_tpm1.c |  35 +--
 security/keys/trusted-keys/trusted_tpm2.c | 150 ++++++-------
 10 files changed, 394 insertions(+), 485 deletions(-)

diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c
index dc882fc9fa9e..2bc6e6e9c4e8 100644
--- a/drivers/char/tpm/tpm-buf.c
+++ b/drivers/char/tpm/tpm-buf.c
@@ -7,24 +7,38 @@
 #include <linux/module.h>
 #include <linux/tpm.h>
 
+#undef pr_fmt
+#define pr_fmt(fmt) "tpm_buf: " fmt
+
 /**
- * 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
+ * tpm_buf_alloc() - Allocate a &tpm_buf instance
+ * @size:	the buffer size in bytes
+ *
+ * As &tpm_buf header is placed in the beginning of the buffer before contents,
+ * the total capacity will be a eight bytes less than the requested size. E.g,
+ * if 4096 bytes is requested, the capacity for data is 4088 bytes.
  *
- * Return: 0 or -ENOMEM
+ * Return:
+ * * &tpm_buf:	success
+ * * NULL:	out of memory
  */
-int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
+struct tpm_buf *tpm_buf_alloc(u16 size)
 {
-	buf->data = (u8 *)__get_free_page(GFP_KERNEL);
-	if (!buf->data)
-		return -ENOMEM;
+	struct tpm_buf *buf;
 
-	tpm_buf_reset(buf, tag, ordinal);
-	return 0;
+	if (size < sizeof(*buf)) {
+		pr_warn("too small buffer size: %lu\n", size);
+		return NULL;
+	}
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (!buf)
+		return NULL;
+
+	buf->capacity = size - sizeof(*buf);
+	return buf;
 }
-EXPORT_SYMBOL_GPL(tpm_buf_init);
+EXPORT_SYMBOL_GPL(tpm_buf_alloc);
 
 /**
  * tpm_buf_reset() - Initialize a TPM command
@@ -48,23 +62,6 @@ void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal)
 }
 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
- */
-int tpm_buf_init_sized(struct tpm_buf *buf)
-{
-	buf->data = (u8 *)__get_free_page(GFP_KERNEL);
-	if (!buf->data)
-		return -ENOMEM;
-
-	tpm_buf_reset_sized(buf);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(tpm_buf_init_sized);
-
 /**
  * tpm_buf_reset_sized() - Initialize a sized buffer
  * @buf:	A &tpm_buf
@@ -78,12 +75,6 @@ void tpm_buf_reset_sized(struct tpm_buf *buf)
 }
 EXPORT_SYMBOL_GPL(tpm_buf_reset_sized);
 
-void tpm_buf_destroy(struct tpm_buf *buf)
-{
-	free_page((unsigned long)buf->data);
-}
-EXPORT_SYMBOL_GPL(tpm_buf_destroy);
-
 /**
  * tpm_buf_length() - Return the number of bytes consumed by the data
  * @buf:	A &tpm_buf
@@ -108,7 +99,7 @@ void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length)
 	if (buf->flags & TPM_BUF_OVERFLOW)
 		return;
 
-	if ((buf->length + new_length) > PAGE_SIZE) {
+	if ((buf->length + new_length) > buf->capacity) {
 		WARN(1, "tpm_buf: write overflow\n");
 		buf->flags |= TPM_BUF_OVERFLOW;
 		return;
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 94231f052ea7..415065ff5267 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -32,28 +32,29 @@ struct tpm_readpubek_out {
 static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
-	struct tpm_buf tpm_buf;
+	CLASS_TPM_BUF(tpm_buf, PAGE_SIZE);
 	struct tpm_readpubek_out *out;
 	int i;
 	char *str = buf;
 	struct tpm_chip *chip = to_tpm_chip(dev);
 	char anti_replay[20];
 
+	if (!tpm_buf)
+		return -ENOMEM;
+
 	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_append(&tpm_buf, anti_replay, sizeof(anti_replay));
+	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,
+	if (tpm_transmit_cmd(chip, tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE,
 			     "attempting to read the PUBEK"))
-		goto out_buf;
+		goto out_ops;
 
-	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,8 +72,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 cf64c7385105..7732aa443062 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -323,19 +323,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;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 
-	dev_info(&chip->dev, "starting up the TPM manually\n");
+	if (!buf)
+		return -ENOMEM;
 
-	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
-	if (rc < 0)
-		return rc;
+	dev_info(&chip->dev, "starting up the TPM manually\n");
 
-	tpm_buf_append_u16(&buf, TPM_ST_CLEAR);
+	tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
+	tpm_buf_append_u16(buf, TPM_ST_CLEAR);
 
-	rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM");
-	tpm_buf_destroy(&buf);
+	rc = tpm_transmit_cmd(chip, buf, 0, "attempting to start the TPM");
 	return rc;
 }
 
@@ -463,18 +462,17 @@ 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;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 
-	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
-	if (rc)
-		return rc;
+	if (!buf)
+		return -ENOMEM;
 
-	tpm_buf_append_u32(&buf, pcr_idx);
-	tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE);
+	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);
+	rc = tpm_transmit_cmd(chip, buf, TPM_DIGEST_SIZE, log_msg);
 	return rc;
 }
 
@@ -482,31 +480,31 @@ int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash,
 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;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 
-	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP);
-	if (rc)
-		return rc;
+	if (!buf)
+		return -ENOMEM;
+
+	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);
@@ -529,83 +527,75 @@ struct tpm1_get_random_out {
  */
 int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	struct tpm1_get_random_out *out;
 	u32 num_bytes =  min_t(u32, max, TPM_MAX_RNG_DATA);
-	struct tpm_buf buf;
+	unsigned int expected;
 	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;
+	if (!buf)
+		return -ENOMEM;
+
+	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;
+
+		expected = TPM_HEADER_SIZE + sizeof(out->rng_data_len) + recd;
+		if (tpm_buf_length(buf) < expected)
+			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;
 }
 
 #define TPM_ORD_PCRREAD 21
 int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)
 {
-	struct tpm_buf buf;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 
-	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD);
-	if (rc)
-		return rc;
+	if (!buf)
+		return -ENOMEM;
 
-	tpm_buf_append_u32(&buf, pcr_idx);
+	tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD);
+	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;
-
-	if (tpm_buf_length(&buf) < TPM_DIGEST_SIZE) {
-		rc = -EFAULT;
-		goto out;
-	}
+		return rc;
 
-	memcpy(res_buf, &buf.data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE);
+	if (tpm_buf_length(buf) < TPM_DIGEST_SIZE)
+		return -EFAULT;
 
-out:
-	tpm_buf_destroy(&buf);
+	memcpy(res_buf, &buf->data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE);
 	return rc;
 }
 
@@ -619,15 +609,14 @@ 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;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 
-	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
-	if (rc)
-		return rc;
+	if (!buf)
+		return -ENOMEM;
 
-	rc = tpm_transmit_cmd(chip, &buf, 0, "continue selftest");
-	tpm_buf_destroy(&buf);
+	tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
+	rc = tpm_transmit_cmd(chip, buf, 0, "continue selftest");
 	return rc;
 }
 
@@ -741,23 +730,24 @@ int tpm1_auto_startup(struct tpm_chip *chip)
  */
 int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
-	struct tpm_buf buf;
 	unsigned int try;
 	int rc;
 
+	if (!buf)
+		return -ENOMEM;
 
 	/* 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");
 
-	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
-	if (rc)
-		return rc;
+	tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
+
 	/* 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
@@ -772,7 +762,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)
@@ -782,8 +772,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 524d802ede26..0399600a26fc 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -165,14 +165,17 @@ struct tpm2_pcr_read_out {
 int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
 		  struct tpm_digest *digest, u16 *digest_size_ptr)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	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;
 
+	if (!buf)
+		return -ENOMEM;
+
 	if (pcr_idx >= TPM2_PLATFORM_PCR)
 		return -EINVAL;
 
@@ -187,23 +190,21 @@ 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;
+	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;
 
-	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)) {
@@ -216,7 +217,6 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
 
 	memcpy(digest->digest, out->digest, digest_size);
 out:
-	tpm_buf_destroy(&buf);
 	return rc;
 }
 
@@ -232,46 +232,42 @@ 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;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 	int i;
 
+	if (!buf)
+		return -ENOMEM;
+
 	if (!disable_pcr_integrity) {
 		rc = tpm2_start_auth_session(chip);
 		if (rc)
 			return rc;
 	}
 
-	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
-	if (rc) {
-		if (!disable_pcr_integrity)
-			tpm2_end_auth_session(chip);
-		return rc;
-	}
+	tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
 
 	if (!disable_pcr_integrity) {
-		tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
-		tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
+		tpm_buf_append_name(chip, buf, pcr_idx, NULL);
+		tpm_buf_append_hmac_session(chip, buf, 0, NULL, 0);
 	} else {
-		tpm_buf_append_handle(chip, &buf, pcr_idx);
-		tpm_buf_append_auth(chip, &buf, 0, NULL, 0);
+		tpm_buf_append_handle(chip, buf, pcr_idx);
+		tpm_buf_append_auth(chip, buf, 0, 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)
-		tpm_buf_fill_hmac_session(chip, &buf);
-	rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
+		tpm_buf_fill_hmac_session(chip, buf);
+	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;
 }
@@ -294,9 +290,9 @@ struct tpm2_get_random_out {
  */
 int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	struct tpm2_get_random_out *out;
 	struct tpm_header *head;
-	struct tpm_buf buf;
 	u32 recd;
 	u32 num_bytes = max;
 	int err;
@@ -308,43 +304,40 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
 	if (!num_bytes || max > TPM_MAX_RNG_DATA)
 		return -EINVAL;
 
+	if (!buf)
+		return -ENOMEM;
+
 	err = tpm2_start_auth_session(chip);
 	if (err)
 		return err;
 
-	err = tpm_buf_init(&buf, 0, 0);
-	if (err) {
-		tpm2_end_auth_session(chip);
-		return err;
-	}
-
 	do {
-		tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
-		tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT
+		tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
+		tpm_buf_append_hmac_session_opt(chip, buf, TPM2_SA_ENCRYPT
 						| TPM2_SA_CONTINUE_SESSION,
 						NULL, 0);
-		tpm_buf_append_u16(&buf, num_bytes);
-		tpm_buf_fill_hmac_session(chip, &buf);
-		err = tpm_transmit_cmd(chip, &buf,
+		tpm_buf_append_u16(buf, num_bytes);
+		tpm_buf_fill_hmac_session(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;
 		}
 
-		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) {
@@ -358,11 +351,9 @@ 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;
 }
@@ -374,20 +365,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;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 
-	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
-	if (rc) {
+	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_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);
 
@@ -413,20 +402,21 @@ struct tpm2_get_cap_out {
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
 			const char *desc)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	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);
+	if (!buf)
+		return -ENOMEM;
+
+	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
@@ -438,7 +428,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);
@@ -455,15 +444,14 @@ EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);
  */
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
 {
-	struct tpm_buf buf;
-	int rc;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 
-	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
-	if (rc)
+	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_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");
 }
 
 /**
@@ -481,19 +469,18 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
  */
 static int tpm2_do_selftest(struct tpm_chip *chip)
 {
-	struct tpm_buf buf;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	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;
+	if (!buf)
+		return -ENOMEM;
 
-		tpm_buf_append_u8(&buf, full);
-		rc = tpm_transmit_cmd(chip, &buf, 0,
+	for (full = 0; full < 2; full++) {
+		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");
-		tpm_buf_destroy(&buf);
 
 		if (rc == TPM2_RC_TESTING)
 			rc = TPM2_RC_SUCCESS;
@@ -518,24 +505,24 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
  */
 int tpm2_probe(struct tpm_chip *chip)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	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);
+	if (!buf)
+		return -ENOMEM;
+
+	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);
@@ -574,8 +561,8 @@ struct tpm2_pcr_selection {
 
 ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	struct tpm2_pcr_selection pcr_selection;
-	struct tpm_buf buf;
 	void *marker;
 	void *end;
 	void *pcr_select_offset;
@@ -587,41 +574,38 @@ 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;
+	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_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]);
 
 	chip->allocated_banks = kcalloc(nr_possible_banks,
 					sizeof(*chip->allocated_banks),
 					GFP_KERNEL);
-	if (!chip->allocated_banks) {
-		rc = -ENOMEM;
-		goto out;
-	}
+	if (!chip->allocated_banks)
+		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];
 
+	return rc;
 	for (i = 0; i < nr_possible_banks; i++) {
 		pcr_select_offset = marker +
 			offsetof(struct tpm2_pcr_selection, size_of_select);
-		if (pcr_select_offset >= end) {
-			rc = -EFAULT;
-			break;
-		}
+		if (pcr_select_offset >= end)
+			return -EFAULT;
 
 		memcpy(&pcr_selection, marker, sizeof(pcr_selection));
 		hash_alg = be16_to_cpu(pcr_selection.hash_alg);
@@ -633,7 +617,7 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
 
 			rc = tpm2_init_bank_info(chip, nr_alloc_banks);
 			if (rc < 0)
-				break;
+				return rc;
 
 			nr_alloc_banks++;
 		}
@@ -645,21 +629,21 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
 	}
 
 	chip->nr_allocated_banks = nr_alloc_banks;
-out:
-	tpm_buf_destroy(&buf);
-
-	return rc;
+	return 0;
 }
 
 int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
 {
-	struct tpm_buf buf;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	u32 nr_commands;
 	__be32 *attrs;
 	u32 cc;
 	int i;
 	int rc;
 
+	if (!buf)
+		return -ENOMEM;
+
 	rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL);
 	if (rc)
 		goto out;
@@ -676,30 +660,24 @@ 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)
-		goto out;
+	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);
 
-	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;
@@ -711,8 +689,6 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
 		}
 	}
 
-	tpm_buf_destroy(&buf);
-
 out:
 	if (rc > 0)
 		rc = -ENODEV;
@@ -733,20 +709,17 @@ EXPORT_SYMBOL_GPL(tpm2_get_cc_attrs_tbl);
 
 static int tpm2_startup(struct tpm_chip *chip)
 {
-	struct tpm_buf buf;
-	int rc;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 
-	dev_info(&chip->dev, "starting up the TPM manually\n");
+	if (!buf)
+		return -ENOMEM;
 
-	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
-	if (rc < 0)
-		return rc;
+	dev_info(&chip->dev, "starting up the TPM manually\n");
 
-	tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
-	rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM");
-	tpm_buf_destroy(&buf);
+	tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
+	tpm_buf_append_u16(buf, TPM2_SU_CLEAR);
 
-	return rc;
+	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 7b5049b3d476..c179198b0645 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -182,19 +182,17 @@ static int tpm2_parse_read_public(char *name, struct tpm_buf *buf)
 
 static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
 {
-	struct tpm_buf buf;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 
-	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
-	if (rc)
-		return rc;
+	if (!buf)
+		return -ENOMEM;
 
-	tpm_buf_append_u32(&buf, handle);
-	rc = tpm_transmit_cmd(chip, &buf, 0, "read public");
+	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, "read public");
 	if (rc == TPM2_RC_SUCCESS)
-		rc = tpm2_parse_read_public(name, &buf);
-
-	tpm_buf_destroy(&buf);
+		rc = tpm2_parse_read_public(name, buf);
 
 	return rc;
 }
@@ -968,8 +966,8 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
  */
 int tpm2_start_auth_session(struct tpm_chip *chip)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	struct tpm2_auth *auth;
-	struct tpm_buf buf;
 	u32 null_key;
 	int rc;
 
@@ -978,6 +976,9 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
 		return 0;
 	}
 
+	if (!buf)
+		return -ENOMEM;
+
 	auth = kzalloc(sizeof(*auth), GFP_KERNEL);
 	if (!auth)
 		return -ENOMEM;
@@ -988,41 +989,36 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
 
 	auth->session = TPM_HEADER_SIZE;
 
-	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS);
-	if (rc)
-		goto out;
-
+	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 */
-	tpm_buf_append_salt(&buf, chip, auth);
+	tpm_buf_append_salt(buf, chip, auth);
 	/* 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;
@@ -1243,19 +1239,15 @@ 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)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
+	CLASS_TPM_BUF(template, PAGE_SIZE);
 	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;
+	if (!buf || !template)
+		return -ENOMEM;
 
-	rc = tpm_buf_init_sized(&template);
-	if (rc) {
-		tpm_buf_destroy(&buf);
-		return rc;
-	}
+	tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY);
+	tpm_buf_reset_sized(template);
 
 	/*
 	 * create the template.  Note: in order for userspace to
@@ -1267,75 +1259,71 @@ 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,
-			      "attempting to create NULL primary");
+	rc = tpm_transmit_cmd(chip, buf, 0, "creating a primary key");
 
 	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 60354cd53b5c..df9f1a01b233 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -71,24 +71,24 @@ 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;
+	CLASS_TPM_BUF(tbuf, PAGE_SIZE);
 	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;
+	if (!tbuf)
+		return -ENOMEM;
+
+	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) {
@@ -103,64 +103,54 @@ 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;
+	CLASS_TPM_BUF(tbuf, PAGE_SIZE);
 	unsigned int body_size;
 	int rc;
 
-	rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);
-	if (rc)
-		return rc;
+	if (!tbuf)
+		return -ENOMEM;
 
-	tpm_buf_append_u32(&tbuf, handle);
+	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 0818bb517805..87152a4b68ce 100644
--- a/drivers/char/tpm/tpm_vtpm_proxy.c
+++ b/drivers/char/tpm/tpm_vtpm_proxy.c
@@ -395,40 +395,35 @@ 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;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 	const struct tpm_header *header;
 	struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev);
 
+	if (!buf)
+		return -ENOMEM;
+
 	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 804fbbe3873d..05dbb47dd1ef 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -375,13 +375,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 handles;
+	u16 flags;
+	u16 capacity;
+	u16 length;
+	u16 handles;
+	u8 data[];
 };
 
 enum tpm2_object_attributes {
@@ -412,11 +414,9 @@ struct tpm2_hash {
 	unsigned int tpm_id;
 };
 
-int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal);
+struct tpm_buf *tpm_buf_alloc(u16 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);
 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);
@@ -427,6 +427,10 @@ u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset);
 u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset);
 void tpm_buf_append_handle(struct tpm_chip *chip, struct tpm_buf *buf, u32 handle);
 
+DEFINE_CLASS(tpm_buf, struct tpm_buf *, kfree(_T), tpm_buf_alloc(size), u16 size);
+
+#define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
+
 /*
  * Check if TPM device is in the firmware upgrade mode.
  */
diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
index 89c9798d1800..059c9872b34f 100644
--- a/security/keys/trusted-keys/trusted_tpm1.c
+++ b/security/keys/trusted-keys/trusted_tpm1.c
@@ -356,21 +356,26 @@ static int TSS_checkhmac2(unsigned char *buffer,
  */
 int trusted_tpm_send(unsigned char *cmd, size_t buflen)
 {
-	struct tpm_buf buf;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	int rc;
 
 	if (!chip)
 		return -ENODEV;
 
+	if (!buf)
+		return -ENOMEM;
+
+	if (buflen > buf->capacity)
+		return -EINVAL;
+
 	rc = tpm_try_get_ops(chip);
 	if (rc)
 		return rc;
 
-	buf.flags = 0;
-	buf.length = buflen;
-	buf.data = cmd;
+	tpm_buf_append(buf, cmd, buflen);
+
 	dump_tpm_buf(cmd);
-	rc = tpm_transmit_cmd(chip, &buf, 4, "sending data");
+	rc = tpm_transmit_cmd(chip, buf, 4, "sending command");
 	dump_tpm_buf(cmd);
 
 	if (rc > 0)
@@ -672,23 +677,21 @@ 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;
+	CLASS_TPM_BUF(tb, PAGE_SIZE);
 	int ret;
 
-	ret = tpm_buf_init(&tb, 0, 0);
-	if (ret)
-		return ret;
+	if (!tb)
+		return -ENOMEM;
 
 	/* 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;
 }
 
@@ -698,14 +701,13 @@ 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;
+	CLASS_TPM_BUF(tb, PAGE_SIZE);
 	int ret;
 
-	ret = tpm_buf_init(&tb, 0, 0);
-	if (ret)
-		return ret;
+	if (!tb)
+		return -ENOMEM;
 
-	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);
@@ -713,7 +715,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 024be262702f..1b807ecfdfea 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -241,14 +241,18 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		      struct trusted_key_payload *payload,
 		      struct trusted_key_options *options)
 {
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
+	CLASS_TPM_BUF(sized, PAGE_SIZE);
 	off_t offset = TPM_HEADER_SIZE;
-	struct tpm_buf buf, sized;
 	int blob_len = 0;
 	u32 hash;
 	u32 flags;
 	int i;
 	int rc;
 
+	if (!buf || !sized)
+		return -ENOMEM;
+
 	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
 		if (options->hash == tpm2_hash_map[i].crypto_id) {
 			hash = tpm2_hash_map[i].tpm_id;
@@ -270,89 +274,76 @@ 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) {
-		tpm2_end_auth_session(chip);
-		goto out_put;
-	}
-
-	rc = tpm_buf_init_sized(&sized);
-	if (rc) {
-		tpm_buf_destroy(&buf);
-		tpm2_end_auth_session(chip);
-		goto out_put;
-	}
-
-	tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
-	tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
+	tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+	tpm_buf_reset_sized(sized);
+	tpm_buf_append_name(chip, buf, options->keyhandle, NULL);
+	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_OVERFLOW) {
+	if (buf->flags & TPM_BUF_OVERFLOW) {
 		rc = -E2BIG;
 		tpm2_end_auth_session(chip);
 		goto out;
 	}
 
-	tpm_buf_fill_hmac_session(chip, &buf);
-	rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
-	rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+	tpm_buf_fill_hmac_session(chip, buf);
+	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_BOUNDARY_ERROR) {
+	blob_len = tpm_buf_read_u32(buf, &offset);
+	if (blob_len > MAX_BLOB_SIZE || buf->flags & TPM_BUF_BOUNDARY_ERROR) {
 		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);
 
 out:
-	tpm_buf_destroy(&sized);
-	tpm_buf_destroy(&buf);
-
 	if (rc > 0) {
 		if (tpm2_rc_value(rc) == TPM2_RC_HASH)
 			rc = -EINVAL;
@@ -387,7 +378,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 			 struct trusted_key_options *options,
 			 u32 *blob_handle)
 {
-	struct tpm_buf buf;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	unsigned int private_len;
 	unsigned int public_len;
 	unsigned int blob_len;
@@ -395,6 +386,9 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 	int rc;
 	u32 attrs;
 
+	if (!buf)
+		return -ENOMEM;
+
 	rc = tpm2_key_decode(payload, options, &blob);
 	if (rc) {
 		/* old form */
@@ -438,35 +432,29 @@ 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) {
-		tpm2_end_auth_session(chip);
-		return rc;
-	}
-
-	tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
-	tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
+	tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+	tpm_buf_append_name(chip, buf, options->keyhandle, NULL);
+	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_OVERFLOW) {
+	if (buf->flags & TPM_BUF_OVERFLOW) {
 		rc = -E2BIG;
 		tpm2_end_auth_session(chip);
 		goto out;
 	}
 
-	tpm_buf_fill_hmac_session(chip, &buf);
-	rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
-	rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+	tpm_buf_fill_hmac_session(chip, buf);
+	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]);
+			(__be32 *)&buf->data[TPM_HEADER_SIZE]);
 
 out:
 	if (blob != payload->blob)
 		kfree(blob);
-	tpm_buf_destroy(&buf);
 
 	if (rc > 0)
 		rc = -EPERM;
@@ -491,25 +479,23 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 			   struct trusted_key_options *options,
 			   u32 blob_handle)
 {
-	struct tpm_buf buf;
+	CLASS_TPM_BUF(buf, PAGE_SIZE);
 	u16 data_len;
 	u8 *data;
 	int rc;
 
+	if (!buf)
+		return -ENOMEM;
+
 	rc = tpm2_start_auth_session(chip);
 	if (rc)
 		return rc;
 
-	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
-	if (rc) {
-		tpm2_end_auth_session(chip);
-		return rc;
-	}
-
-	tpm_buf_append_name(chip, &buf, blob_handle, NULL);
+	tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+	tpm_buf_append_name(chip, buf, blob_handle, NULL);
 
 	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 {
@@ -524,32 +510,28 @@ 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);
-		tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT,
+		tpm_buf_append_hmac_session_opt(chip, buf, TPM2_SA_ENCRYPT,
 						NULL, 0);
 	}
 
-	tpm_buf_fill_hmac_session(chip, &buf);
-	rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
-	rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+	tpm_buf_fill_hmac_session(chip, buf);
+	rc = tpm_transmit_cmd(chip, buf, 6, "unsealing");
+	rc = tpm_buf_check_hmac_response(chip, buf, rc);
 	if (rc > 0)
 		rc = -EPERM;
 
 	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 +548,6 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 		}
 	}
 
-out:
-	tpm_buf_destroy(&buf);
 	return rc;
 }
 
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
  2025-06-26 10:19 [PATCH v2] tpm: Cleanup class for tpm_buf Jarkko Sakkinen
@ 2025-06-26 14:50 ` James Bottomley
  2025-06-26 18:11   ` Jarkko Sakkinen
  2025-06-26 21:59 ` kernel test robot
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: James Bottomley @ 2025-06-26 14:50 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel
  Cc: keyrings, Jarkko Sakkinen, Peter Huewe, Jason Gunthorpe,
	Mimi Zohar, David Howells, Paul Moore, James Morris,
	Serge E. Hallyn, open list:TPM DEVICE DRIVER,
	open list:SECURITY SUBSYSTEM

On Thu, 2025-06-26 at 13:19 +0300, Jarkko Sakkinen wrote:
> From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> 
> Create a cleanup class for struct tpm_buf using DEFINE_CLASS(), which
> will guarantee that the heap allocated memory will be freed
> automatically for the transient instances of this structure, when
> they go out of scope.
> 
> Wrap this all into help macro CLASS_TPM_BUF().
> 
> A TPM buffer can now be declared trivially:
> 
>     CLASS_TPM_BUF(buf, buf_size);

Well, that's not all ... you're also adding a size to the API that we
didn't have before, which should at least be documented in the commit
message and probably be a separate patch.

What is the reason for this, though?  The reason we currently use a
page is that it's easy for the OS to manage (no slab fragmentation
issues).  The TCG reference platform defines this to be just under 4k
(actually 4096-0x80) precisely because TPM implementations don't do
scatter gather, so they don't want it going over an ARM page, so
there's no danger of us ever needing more than a page.

Regards,

James


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
  2025-06-26 14:50 ` James Bottomley
@ 2025-06-26 18:11   ` Jarkko Sakkinen
  2025-06-26 22:35     ` Jarkko Sakkinen
  0 siblings, 1 reply; 9+ messages in thread
From: Jarkko Sakkinen @ 2025-06-26 18:11 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-kernel, keyrings, Jarkko Sakkinen, Peter Huewe,
	Jason Gunthorpe, Mimi Zohar, David Howells, Paul Moore,
	James Morris, Serge E. Hallyn, open list:TPM DEVICE DRIVER,
	open list:SECURITY SUBSYSTEM

On Thu, Jun 26, 2025 at 10:50:22AM -0400, James Bottomley wrote:
> On Thu, 2025-06-26 at 13:19 +0300, Jarkko Sakkinen wrote:
> > From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> > 
> > Create a cleanup class for struct tpm_buf using DEFINE_CLASS(), which
> > will guarantee that the heap allocated memory will be freed
> > automatically for the transient instances of this structure, when
> > they go out of scope.
> > 
> > Wrap this all into help macro CLASS_TPM_BUF().
> > 
> > A TPM buffer can now be declared trivially:
> > 
> >     CLASS_TPM_BUF(buf, buf_size);
> 
> Well, that's not all ... you're also adding a size to the API that we
> didn't have before, which should at least be documented in the commit
> message and probably be a separate patch.
> 
> What is the reason for this, though?  The reason we currently use a
> page is that it's easy for the OS to manage (no slab fragmentation
> issues).  The TCG reference platform defines this to be just under 4k
> (actually 4096-0x80) precisely because TPM implementations don't do
> scatter gather, so they don't want it going over an ARM page, so
> there's no danger of us ever needing more than a page.

Thanks for the valuable feedback.

I can drop "buf_size" parameter. It is not a priority, and I also
agree with your comments.

> 
> Regards,
> 
> James

BR, Jarkko

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
  2025-06-26 10:19 [PATCH v2] tpm: Cleanup class for tpm_buf Jarkko Sakkinen
  2025-06-26 14:50 ` James Bottomley
@ 2025-06-26 21:59 ` kernel test robot
  2025-06-27 21:41 ` Dan Carpenter
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-06-26 21:59 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: llvm, oe-kbuild-all

Hi Jarkko,

kernel test robot noticed the following build warnings:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on char-misc/char-misc-next char-misc/char-misc-linus linus/master v6.16-rc3 next-20250626]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jarkko-Sakkinen/tpm-Cleanup-class-for-tpm_buf/20250626-182148
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250626101935.1007898-1-jarkko%40kernel.org
patch subject: [PATCH v2] tpm: Cleanup class for tpm_buf
config: arm64-randconfig-001-20250627 (https://download.01.org/0day-ci/archive/20250627/202506270544.5uEqUaOS-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250627/202506270544.5uEqUaOS-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506270544.5uEqUaOS-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/char/tpm/tpm1-cmd.c:21:
   include/linux/tpm_eventlog.h:167:6: warning: variable 'mapping_size' set but not used [-Wunused-but-set-variable]
     167 |         int mapping_size;
         |             ^
>> drivers/char/tpm/tpm1-cmd.c:326:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     326 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm1-cmd.c:465:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     465 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm1-cmd.c:483:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     483 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm1-cmd.c:530:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     530 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm1-cmd.c:581:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     581 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm1-cmd.c:612:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     612 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm1-cmd.c:733:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     733 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   8 warnings generated.
--
   In file included from drivers/char/tpm/tpm2-space.c:16:
   In file included from drivers/char/tpm/tpm.h:28:
   include/linux/tpm_eventlog.h:167:6: warning: variable 'mapping_size' set but not used [-Wunused-but-set-variable]
     167 |         int mapping_size;
         |             ^
>> drivers/char/tpm/tpm2-space.c:74:22: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
      74 |         CLASS_TPM_BUF(tbuf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-space.c:123:22: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     123 |         CLASS_TPM_BUF(tbuf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   3 warnings generated.
--
   In file included from drivers/char/tpm/tpm2-cmd.c:14:
   In file included from drivers/char/tpm/tpm.h:28:
   include/linux/tpm_eventlog.h:167:6: warning: variable 'mapping_size' set but not used [-Wunused-but-set-variable]
     167 |         int mapping_size;
         |             ^
>> drivers/char/tpm/tpm2-cmd.c:168:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     168 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:235:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     235 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:293:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     293 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:368:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     368 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:405:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     405 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:447:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     447 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:472:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     472 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:508:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     508 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:564:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     564 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:637:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     637 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   drivers/char/tpm/tpm2-cmd.c:712:21: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
     712 |         CLASS_TPM_BUF(buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   12 warnings generated.
--
   In file included from drivers/char/tpm/tpm-sysfs.c:16:
   In file included from drivers/char/tpm/tpm.h:28:
   include/linux/tpm_eventlog.h:167:6: warning: variable 'mapping_size' set but not used [-Wunused-but-set-variable]
     167 |         int mapping_size;
         |             ^
>> drivers/char/tpm/tpm-sysfs.c:35:25: warning: implicit conversion from 'unsigned long' to 'u16' (aka 'unsigned short') changes value from 65536 to 0 [-Wconstant-conversion]
      35 |         CLASS_TPM_BUF(tpm_buf, PAGE_SIZE);
         |         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
   include/vdso/page.h:15:30: note: expanded from macro 'PAGE_SIZE'
      15 | #define PAGE_SIZE       (_AC(1,UL) << CONFIG_PAGE_SHIFT)
         |                                    ^
   include/linux/tpm.h:430:54: note: expanded from macro 'CLASS_TPM_BUF'
     430 | #define CLASS_TPM_BUF(buf, size) CLASS(tpm_buf, buf)(size)
         |                                  ~~~~~~~~~~~~~~~~~~~ ^~~~
   2 warnings generated.


vim +326 drivers/char/tpm/tpm1-cmd.c

   313	
   314	/**
   315	 * tpm1_startup() - turn on the TPM
   316	 * @chip: TPM chip to use
   317	 *
   318	 * Normally the firmware should start the TPM. This function is provided as a
   319	 * workaround if this does not happen. A legal case for this could be for
   320	 * example when a TPM emulator is used.
   321	 *
   322	 * Return: same as tpm_transmit_cmd()
   323	 */
   324	static int tpm1_startup(struct tpm_chip *chip)
   325	{
 > 326		CLASS_TPM_BUF(buf, PAGE_SIZE);
   327		int rc;
   328	
   329		if (!buf)
   330			return -ENOMEM;
   331	
   332		dev_info(&chip->dev, "starting up the TPM manually\n");
   333	
   334		tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
   335		tpm_buf_append_u16(buf, TPM_ST_CLEAR);
   336	
   337		rc = tpm_transmit_cmd(chip, buf, 0, "attempting to start the TPM");
   338		return rc;
   339	}
   340	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
  2025-06-26 18:11   ` Jarkko Sakkinen
@ 2025-06-26 22:35     ` Jarkko Sakkinen
  0 siblings, 0 replies; 9+ messages in thread
From: Jarkko Sakkinen @ 2025-06-26 22:35 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-kernel, keyrings, Jarkko Sakkinen, Peter Huewe,
	Jason Gunthorpe, Mimi Zohar, David Howells, Paul Moore,
	James Morris, Serge E. Hallyn, open list:TPM DEVICE DRIVER,
	open list:SECURITY SUBSYSTEM

On Thu, Jun 26, 2025 at 09:11:05PM +0300, Jarkko Sakkinen wrote:
> On Thu, Jun 26, 2025 at 10:50:22AM -0400, James Bottomley wrote:
> > On Thu, 2025-06-26 at 13:19 +0300, Jarkko Sakkinen wrote:
> > > From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> > > 
> > > Create a cleanup class for struct tpm_buf using DEFINE_CLASS(), which
> > > will guarantee that the heap allocated memory will be freed
> > > automatically for the transient instances of this structure, when
> > > they go out of scope.
> > > 
> > > Wrap this all into help macro CLASS_TPM_BUF().
> > > 
> > > A TPM buffer can now be declared trivially:
> > > 
> > >     CLASS_TPM_BUF(buf, buf_size);
> > 
> > Well, that's not all ... you're also adding a size to the API that we
> > didn't have before, which should at least be documented in the commit
> > message and probably be a separate patch.
> > 
> > What is the reason for this, though?  The reason we currently use a
> > page is that it's easy for the OS to manage (no slab fragmentation
> > issues).  The TCG reference platform defines this to be just under 4k
> > (actually 4096-0x80) precisely because TPM implementations don't do
> > scatter gather, so they don't want it going over an ARM page, so
> > there's no danger of us ever needing more than a page.
> 
> Thanks for the valuable feedback.
> 
> I can drop "buf_size" parameter. It is not a priority, and I also
> agree with your comments.

I also noticed that I had changed one log message in tpm2-sessions.c. It
was unintended i.e. a spurious change. I'll revert that one too.

I'll split this into more reasonable portions for next version so these
should be easier to review then.

BR, Jarkko

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
@ 2025-06-27 21:13 kernel test robot
  0 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-06-27 21:13 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp, Dan Carpenter

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20250626101935.1007898-1-jarkko@kernel.org>
References: <20250626101935.1007898-1-jarkko@kernel.org>
TO: Jarkko Sakkinen <jarkko@kernel.org>

Hi Jarkko,

kernel test robot noticed the following build warnings:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on char-misc/char-misc-next char-misc/char-misc-linus linus/master v6.16-rc3 next-20250627]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jarkko-Sakkinen/tpm-Cleanup-class-for-tpm_buf/20250626-182148
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250626101935.1007898-1-jarkko%40kernel.org
patch subject: [PATCH v2] tpm: Cleanup class for tpm_buf
:::::: branch date: 35 hours ago
:::::: commit date: 35 hours ago
config: x86_64-randconfig-161-20250627 (https://download.01.org/0day-ci/archive/20250628/202506280550.7lqjVBcB-lkp@intel.com/config)
compiler: clang version 20.1.7 (https://github.com/llvm/llvm-project 6146a88f60492b520a36f8f8f3231e15f3cc6082)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>
| Closes: https://lore.kernel.org/r/202506280550.7lqjVBcB-lkp@intel.com/

smatch warnings:
drivers/char/tpm/tpm2-cmd.c:575 tpm2_get_pcr_allocation() warn: iterator 'i' not incremented

vim +/i +575 drivers/char/tpm/tpm2-cmd.c

1db15344f874f65 Nayna Jain      2017-01-30  561  
fa4f99c05320eb2 Nayna Jain      2019-07-11  562  ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
1db15344f874f65 Nayna Jain      2017-01-30  563  {
ce255545c9add8c Jarkko Sakkinen 2025-06-26  564  	CLASS_TPM_BUF(buf, PAGE_SIZE);
1db15344f874f65 Nayna Jain      2017-01-30  565  	struct tpm2_pcr_selection pcr_selection;
1db15344f874f65 Nayna Jain      2017-01-30  566  	void *marker;
1db15344f874f65 Nayna Jain      2017-01-30  567  	void *end;
1db15344f874f65 Nayna Jain      2017-01-30  568  	void *pcr_select_offset;
1db15344f874f65 Nayna Jain      2017-01-30  569  	u32 sizeof_pcr_selection;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  570  	u32 nr_possible_banks;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  571  	u32 nr_alloc_banks = 0;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  572  	u16 hash_alg;
1db15344f874f65 Nayna Jain      2017-01-30  573  	u32 rsp_len;
1db15344f874f65 Nayna Jain      2017-01-30  574  	int rc;
1db15344f874f65 Nayna Jain      2017-01-30 @575  	int i = 0;
1db15344f874f65 Nayna Jain      2017-01-30  576  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  577  	if (!buf)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  578  		return -ENOMEM;
1db15344f874f65 Nayna Jain      2017-01-30  579  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  580  	tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  581  	tpm_buf_append_u32(buf, TPM2_CAP_PCRS);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  582  	tpm_buf_append_u32(buf, 0);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  583  	tpm_buf_append_u32(buf, 1);
1db15344f874f65 Nayna Jain      2017-01-30  584  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  585  	rc = tpm_transmit_cmd(chip, buf, 9, "get tpm pcr allocation");
1db15344f874f65 Nayna Jain      2017-01-30  586  	if (rc)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  587  		return rc;
1db15344f874f65 Nayna Jain      2017-01-30  588  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  589  	nr_possible_banks = be32_to_cpup(
ce255545c9add8c Jarkko Sakkinen 2025-06-26  590  		(__be32 *)&buf->data[TPM_HEADER_SIZE + 5]);
1db15344f874f65 Nayna Jain      2017-01-30  591  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  592  	chip->allocated_banks = kcalloc(nr_possible_banks,
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  593  					sizeof(*chip->allocated_banks),
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  594  					GFP_KERNEL);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  595  	if (!chip->allocated_banks)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  596  		return -ENOMEM;
1db15344f874f65 Nayna Jain      2017-01-30  597  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  598  	marker = &buf->data[TPM_HEADER_SIZE + 9];
1db15344f874f65 Nayna Jain      2017-01-30  599  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  600  	rsp_len = be32_to_cpup((__be32 *)&buf->data[2]);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  601  	end = &buf->data[rsp_len];
1db15344f874f65 Nayna Jain      2017-01-30  602  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  603  	return rc;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  604  	for (i = 0; i < nr_possible_banks; i++) {
1db15344f874f65 Nayna Jain      2017-01-30  605  		pcr_select_offset = marker +
1db15344f874f65 Nayna Jain      2017-01-30  606  			offsetof(struct tpm2_pcr_selection, size_of_select);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  607  		if (pcr_select_offset >= end)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  608  			return -EFAULT;
1db15344f874f65 Nayna Jain      2017-01-30  609  
1db15344f874f65 Nayna Jain      2017-01-30  610  		memcpy(&pcr_selection, marker, sizeof(pcr_selection));
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  611  		hash_alg = be16_to_cpu(pcr_selection.hash_alg);
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  612  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  613  		pcr_select_offset = memchr_inv(pcr_selection.pcr_select, 0,
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  614  					       pcr_selection.size_of_select);
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  615  		if (pcr_select_offset) {
879b589210a9a0c Roberto Sassu   2019-02-06  616  			chip->allocated_banks[nr_alloc_banks].alg_id = hash_alg;
879b589210a9a0c Roberto Sassu   2019-02-06  617  
879b589210a9a0c Roberto Sassu   2019-02-06  618  			rc = tpm2_init_bank_info(chip, nr_alloc_banks);
879b589210a9a0c Roberto Sassu   2019-02-06  619  			if (rc < 0)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  620  				return rc;
879b589210a9a0c Roberto Sassu   2019-02-06  621  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  622  			nr_alloc_banks++;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  623  		}
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  624  
1db15344f874f65 Nayna Jain      2017-01-30  625  		sizeof_pcr_selection = sizeof(pcr_selection.hash_alg) +
1db15344f874f65 Nayna Jain      2017-01-30  626  			sizeof(pcr_selection.size_of_select) +
1db15344f874f65 Nayna Jain      2017-01-30  627  			pcr_selection.size_of_select;
1db15344f874f65 Nayna Jain      2017-01-30  628  		marker = marker + sizeof_pcr_selection;
1db15344f874f65 Nayna Jain      2017-01-30  629  	}
1db15344f874f65 Nayna Jain      2017-01-30  630  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  631  	chip->nr_allocated_banks = nr_alloc_banks;
ce255545c9add8c Jarkko Sakkinen 2025-06-26  632  	return 0;
1db15344f874f65 Nayna Jain      2017-01-30  633  }
61841be6358c03e Jarkko Sakkinen 2017-02-15  634  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
  2025-06-26 10:19 [PATCH v2] tpm: Cleanup class for tpm_buf Jarkko Sakkinen
  2025-06-26 14:50 ` James Bottomley
  2025-06-26 21:59 ` kernel test robot
@ 2025-06-27 21:41 ` Dan Carpenter
  2025-06-28  2:14 ` Jarkko Sakkinen
  2025-06-29 18:30 ` kernel test robot
  4 siblings, 0 replies; 9+ messages in thread
From: Dan Carpenter @ 2025-06-27 21:41 UTC (permalink / raw)
  To: oe-kbuild, Jarkko Sakkinen; +Cc: lkp, oe-kbuild-all

Hi Jarkko,

kernel test robot noticed the following build warnings:

https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jarkko-Sakkinen/tpm-Cleanup-class-for-tpm_buf/20250626-182148
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250626101935.1007898-1-jarkko%40kernel.org
patch subject: [PATCH v2] tpm: Cleanup class for tpm_buf
config: x86_64-randconfig-161-20250627 (https://download.01.org/0day-ci/archive/20250628/202506280550.7lqjVBcB-lkp@intel.com/config)
compiler: clang version 20.1.7 (https://github.com/llvm/llvm-project 6146a88f60492b520a36f8f8f3231e15f3cc6082)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202506280550.7lqjVBcB-lkp@intel.com/

smatch warnings:
drivers/char/tpm/tpm2-cmd.c:575 tpm2_get_pcr_allocation() warn: iterator 'i' not incremented

vim +/i +575 drivers/char/tpm/tpm2-cmd.c

fa4f99c05320eb2 Nayna Jain      2019-07-11  562  ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
1db15344f874f65 Nayna Jain      2017-01-30  563  {
ce255545c9add8c Jarkko Sakkinen 2025-06-26  564  	CLASS_TPM_BUF(buf, PAGE_SIZE);
1db15344f874f65 Nayna Jain      2017-01-30  565  	struct tpm2_pcr_selection pcr_selection;
1db15344f874f65 Nayna Jain      2017-01-30  566  	void *marker;
1db15344f874f65 Nayna Jain      2017-01-30  567  	void *end;
1db15344f874f65 Nayna Jain      2017-01-30  568  	void *pcr_select_offset;
1db15344f874f65 Nayna Jain      2017-01-30  569  	u32 sizeof_pcr_selection;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  570  	u32 nr_possible_banks;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  571  	u32 nr_alloc_banks = 0;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  572  	u16 hash_alg;
1db15344f874f65 Nayna Jain      2017-01-30  573  	u32 rsp_len;
1db15344f874f65 Nayna Jain      2017-01-30  574  	int rc;
1db15344f874f65 Nayna Jain      2017-01-30 @575  	int i = 0;
1db15344f874f65 Nayna Jain      2017-01-30  576  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  577  	if (!buf)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  578  		return -ENOMEM;
1db15344f874f65 Nayna Jain      2017-01-30  579  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  580  	tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  581  	tpm_buf_append_u32(buf, TPM2_CAP_PCRS);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  582  	tpm_buf_append_u32(buf, 0);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  583  	tpm_buf_append_u32(buf, 1);
1db15344f874f65 Nayna Jain      2017-01-30  584  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  585  	rc = tpm_transmit_cmd(chip, buf, 9, "get tpm pcr allocation");
1db15344f874f65 Nayna Jain      2017-01-30  586  	if (rc)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  587  		return rc;
1db15344f874f65 Nayna Jain      2017-01-30  588  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  589  	nr_possible_banks = be32_to_cpup(
ce255545c9add8c Jarkko Sakkinen 2025-06-26  590  		(__be32 *)&buf->data[TPM_HEADER_SIZE + 5]);
1db15344f874f65 Nayna Jain      2017-01-30  591  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  592  	chip->allocated_banks = kcalloc(nr_possible_banks,
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  593  					sizeof(*chip->allocated_banks),
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  594  					GFP_KERNEL);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  595  	if (!chip->allocated_banks)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  596  		return -ENOMEM;
1db15344f874f65 Nayna Jain      2017-01-30  597  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  598  	marker = &buf->data[TPM_HEADER_SIZE + 9];
1db15344f874f65 Nayna Jain      2017-01-30  599  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  600  	rsp_len = be32_to_cpup((__be32 *)&buf->data[2]);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  601  	end = &buf->data[rsp_len];
1db15344f874f65 Nayna Jain      2017-01-30  602  
ce255545c9add8c Jarkko Sakkinen 2025-06-26  603  	return rc;
                                                        ^^^^^^^^^^
Presumably this was not intentional?

bcfff8384f6c4e6 Roberto Sassu   2019-02-06  604  	for (i = 0; i < nr_possible_banks; i++) {
1db15344f874f65 Nayna Jain      2017-01-30  605  		pcr_select_offset = marker +
1db15344f874f65 Nayna Jain      2017-01-30  606  			offsetof(struct tpm2_pcr_selection, size_of_select);
ce255545c9add8c Jarkko Sakkinen 2025-06-26  607  		if (pcr_select_offset >= end)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  608  			return -EFAULT;
1db15344f874f65 Nayna Jain      2017-01-30  609  
1db15344f874f65 Nayna Jain      2017-01-30  610  		memcpy(&pcr_selection, marker, sizeof(pcr_selection));
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  611  		hash_alg = be16_to_cpu(pcr_selection.hash_alg);
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  612  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  613  		pcr_select_offset = memchr_inv(pcr_selection.pcr_select, 0,
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  614  					       pcr_selection.size_of_select);
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  615  		if (pcr_select_offset) {
879b589210a9a0c Roberto Sassu   2019-02-06  616  			chip->allocated_banks[nr_alloc_banks].alg_id = hash_alg;
879b589210a9a0c Roberto Sassu   2019-02-06  617  
879b589210a9a0c Roberto Sassu   2019-02-06  618  			rc = tpm2_init_bank_info(chip, nr_alloc_banks);
879b589210a9a0c Roberto Sassu   2019-02-06  619  			if (rc < 0)
ce255545c9add8c Jarkko Sakkinen 2025-06-26  620  				return rc;
879b589210a9a0c Roberto Sassu   2019-02-06  621  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  622  			nr_alloc_banks++;
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  623  		}
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  624  
1db15344f874f65 Nayna Jain      2017-01-30  625  		sizeof_pcr_selection = sizeof(pcr_selection.hash_alg) +
1db15344f874f65 Nayna Jain      2017-01-30  626  			sizeof(pcr_selection.size_of_select) +
1db15344f874f65 Nayna Jain      2017-01-30  627  			pcr_selection.size_of_select;
1db15344f874f65 Nayna Jain      2017-01-30  628  		marker = marker + sizeof_pcr_selection;
1db15344f874f65 Nayna Jain      2017-01-30  629  	}
1db15344f874f65 Nayna Jain      2017-01-30  630  
bcfff8384f6c4e6 Roberto Sassu   2019-02-06  631  	chip->nr_allocated_banks = nr_alloc_banks;
ce255545c9add8c Jarkko Sakkinen 2025-06-26  632  	return 0;
1db15344f874f65 Nayna Jain      2017-01-30  633  }

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
  2025-06-26 10:19 [PATCH v2] tpm: Cleanup class for tpm_buf Jarkko Sakkinen
                   ` (2 preceding siblings ...)
  2025-06-27 21:41 ` Dan Carpenter
@ 2025-06-28  2:14 ` Jarkko Sakkinen
  2025-06-29 18:30 ` kernel test robot
  4 siblings, 0 replies; 9+ messages in thread
From: Jarkko Sakkinen @ 2025-06-28  2:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: keyrings, Jarkko Sakkinen, Peter Huewe, Jason Gunthorpe,
	James Bottomley, Mimi Zohar, David Howells, Paul Moore,
	James Morris, Serge E. Hallyn, open list:TPM DEVICE DRIVER,
	open list:SECURITY SUBSYSTEM

On Thu, Jun 26, 2025 at 01:19:33PM +0300, Jarkko Sakkinen wrote:
> From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> 
> Create a cleanup class for struct tpm_buf using DEFINE_CLASS(), which will
> guarantee that the heap allocated memory will be freed automatically for
> the transient instances of this structure, when they go out of scope.
> 
> Wrap this all into help macro CLASS_TPM_BUF().
> 
> A TPM buffer can now be declared trivially:
> 
>     CLASS_TPM_BUF(buf, buf_size);

Right, so learning this while doing and probably DEFINE_CLASS() would be
a bad idea :-) There's a better fit in cleanup.h: DEFINE_FREE() and
__free().

Given thatintroduction of tpm_buf_alloc() wipes out tpm_buf_destroy(),
we don't need to create any new wrappers with DEFINE_FREE() as
linux/slab.h has kfree() covered already.

This leads up to "one step backwards" solution i.e., explicitly call
tpm_buf_alloc() and implictly destroy (null checks are left out from
examples):

	struct tpm_buf *buf __free(kfree) = tpm_buf_alloc();
	/* 
	 * I dropped buf_size as it will be gone in v3 as requested by
	 * James earlier.
	 */

	 /* Or: */
	struct tpm_buf *buf2 __free(kfree) = NULL;

	/* ... */
	buf2 = tpm_buf_alloc();

OFF-TOPIC: while doing this patch I noticed maybe 3-5 location where
we have do this:

1. Init something that is more complex to rollback than rolling back
   tpm_buf (which is kfree).
2. Init tpm_buf.
3. After this guaranteed success.

Only reason for doing the rollback for the "more complex to rollback
thing" is that stupid placement of tpm_buf_init(). There's no additional
conditionally failing steps after it.

I need to relocate these code blocks and do a reorders as split patches
and place them to the head of the patch set.

This was mostly reminder for myself :-) 

BR, Jarkko

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] tpm: Cleanup class for tpm_buf
  2025-06-26 10:19 [PATCH v2] tpm: Cleanup class for tpm_buf Jarkko Sakkinen
                   ` (3 preceding siblings ...)
  2025-06-28  2:14 ` Jarkko Sakkinen
@ 2025-06-29 18:30 ` kernel test robot
  4 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-06-29 18:30 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: oe-kbuild-all

Hi Jarkko,

kernel test robot noticed the following build warnings:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on char-misc/char-misc-next char-misc/char-misc-linus linus/master v6.16-rc3 next-20250627]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jarkko-Sakkinen/tpm-Cleanup-class-for-tpm_buf/20250626-182148
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250626101935.1007898-1-jarkko%40kernel.org
patch subject: [PATCH v2] tpm: Cleanup class for tpm_buf
config: sh-randconfig-r111-20250629 (https://download.01.org/0day-ci/archive/20250630/202506300442.B7u3tOmo-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 12.4.0
reproduce: (https://download.01.org/0day-ci/archive/20250630/202506300442.B7u3tOmo-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506300442.B7u3tOmo-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> security/keys/trusted-keys/trusted_tpm2.c:244:9: sparse: sparse: cast truncates bits from constant value (10000 becomes 0)
   security/keys/trusted-keys/trusted_tpm2.c:245:9: sparse: sparse: cast truncates bits from constant value (10000 becomes 0)
   security/keys/trusted-keys/trusted_tpm2.c:381:9: sparse: sparse: cast truncates bits from constant value (10000 becomes 0)
   security/keys/trusted-keys/trusted_tpm2.c:482:9: sparse: sparse: cast truncates bits from constant value (10000 becomes 0)
--
   security/keys/trusted-keys/trusted_tpm1.c:194:19: sparse: sparse: cast to restricted __be32
   security/keys/trusted-keys/trusted_tpm1.c:195:15: sparse: sparse: cast to restricted __be16
   security/keys/trusted-keys/trusted_tpm1.c:282:19: sparse: sparse: cast to restricted __be32
   security/keys/trusted-keys/trusted_tpm1.c:283:15: sparse: sparse: cast to restricted __be16
   security/keys/trusted-keys/trusted_tpm1.c:430:21: sparse: sparse: cast to restricted __be32
   security/keys/trusted-keys/trusted_tpm1.c:454:19: sparse: sparse: cast to restricted __be32
   security/keys/trusted-keys/trusted_tpm1.c:519:17: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] ordinal @@     got restricted __be32 [usertype] @@
   security/keys/trusted-keys/trusted_tpm1.c:519:17: sparse:     expected unsigned int [usertype] ordinal
   security/keys/trusted-keys/trusted_tpm1.c:519:17: sparse:     got restricted __be32 [usertype]
   security/keys/trusted-keys/trusted_tpm1.c:520:17: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] datsize @@     got restricted __be32 [usertype] @@
   security/keys/trusted-keys/trusted_tpm1.c:520:17: sparse:     expected unsigned int [usertype] datsize
   security/keys/trusted-keys/trusted_tpm1.c:520:17: sparse:     got restricted __be32 [usertype]
   security/keys/trusted-keys/trusted_tpm1.c:521:17: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] pcrsize @@     got restricted __be32 [usertype] @@
   security/keys/trusted-keys/trusted_tpm1.c:521:17: sparse:     expected unsigned int [usertype] pcrsize
   security/keys/trusted-keys/trusted_tpm1.c:521:17: sparse:     got restricted __be32 [usertype]
   security/keys/trusted-keys/trusted_tpm1.c:567:24: sparse: sparse: cast to restricted __be32
   security/keys/trusted-keys/trusted_tpm1.c:568:23: sparse: sparse: cast to restricted __be32
   security/keys/trusted-keys/trusted_tpm1.c:620:17: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] ordinal @@     got restricted __be32 [usertype] @@
   security/keys/trusted-keys/trusted_tpm1.c:620:17: sparse:     expected unsigned int [usertype] ordinal
   security/keys/trusted-keys/trusted_tpm1.c:620:17: sparse:     got restricted __be32 [usertype]
   security/keys/trusted-keys/trusted_tpm1.c:659:20: sparse: sparse: cast to restricted __be32
>> security/keys/trusted-keys/trusted_tpm1.c:359:9: sparse: sparse: cast truncates bits from constant value (10000 becomes 0)
   security/keys/trusted-keys/trusted_tpm1.c:680:9: sparse: sparse: cast truncates bits from constant value (10000 becomes 0)
   security/keys/trusted-keys/trusted_tpm1.c:704:9: sparse: sparse: cast truncates bits from constant value (10000 becomes 0)

vim +244 security/keys/trusted-keys/trusted_tpm2.c

   230	
   231	/**
   232	 * tpm2_seal_trusted() - seal the payload of a trusted key
   233	 *
   234	 * @chip: TPM chip to use
   235	 * @payload: the key data in clear and encrypted form
   236	 * @options: authentication values and other options
   237	 *
   238	 * Return: < 0 on error and 0 on success.
   239	 */
   240	int tpm2_seal_trusted(struct tpm_chip *chip,
   241			      struct trusted_key_payload *payload,
   242			      struct trusted_key_options *options)
   243	{
 > 244		CLASS_TPM_BUF(buf, PAGE_SIZE);
   245		CLASS_TPM_BUF(sized, PAGE_SIZE);
   246		off_t offset = TPM_HEADER_SIZE;
   247		int blob_len = 0;
   248		u32 hash;
   249		u32 flags;
   250		int i;
   251		int rc;
   252	
   253		if (!buf || !sized)
   254			return -ENOMEM;
   255	
   256		for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
   257			if (options->hash == tpm2_hash_map[i].crypto_id) {
   258				hash = tpm2_hash_map[i].tpm_id;
   259				break;
   260			}
   261		}
   262	
   263		if (i == ARRAY_SIZE(tpm2_hash_map))
   264			return -EINVAL;
   265	
   266		if (!options->keyhandle)
   267			return -EINVAL;
   268	
   269		rc = tpm_try_get_ops(chip);
   270		if (rc)
   271			return rc;
   272	
   273		rc = tpm2_start_auth_session(chip);
   274		if (rc)
   275			goto out_put;
   276	
   277		tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
   278		tpm_buf_reset_sized(sized);
   279		tpm_buf_append_name(chip, buf, options->keyhandle, NULL);
   280		tpm_buf_append_hmac_session(chip, buf, TPM2_SA_DECRYPT,
   281					    options->keyauth, TPM_DIGEST_SIZE);
   282	
   283		/* sensitive */
   284		tpm_buf_append_u16(sized, options->blobauth_len);
   285	
   286		if (options->blobauth_len)
   287			tpm_buf_append(sized, options->blobauth, options->blobauth_len);
   288	
   289		tpm_buf_append_u16(sized, payload->key_len);
   290		tpm_buf_append(sized, payload->key, payload->key_len);
   291		tpm_buf_append(buf, sized->data, sized->length);
   292	
   293		/* public */
   294		tpm_buf_reset_sized(sized);
   295		tpm_buf_append_u16(sized, TPM_ALG_KEYEDHASH);
   296		tpm_buf_append_u16(sized, hash);
   297	
   298		/* key properties */
   299		flags = 0;
   300		flags |= options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH;
   301		flags |= payload->migratable ? 0 : (TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_PARENT);
   302		tpm_buf_append_u32(sized, flags);
   303	
   304		/* policy */
   305		tpm_buf_append_u16(sized, options->policydigest_len);
   306		if (options->policydigest_len)
   307			tpm_buf_append(sized, options->policydigest, options->policydigest_len);
   308	
   309		/* public parameters */
   310		tpm_buf_append_u16(sized, TPM_ALG_NULL);
   311		tpm_buf_append_u16(sized, 0);
   312	
   313		tpm_buf_append(buf, sized->data, sized->length);
   314	
   315		/* outside info */
   316		tpm_buf_append_u16(buf, 0);
   317	
   318		/* creation PCR */
   319		tpm_buf_append_u32(buf, 0);
   320	
   321		if (buf->flags & TPM_BUF_OVERFLOW) {
   322			rc = -E2BIG;
   323			tpm2_end_auth_session(chip);
   324			goto out;
   325		}
   326	
   327		tpm_buf_fill_hmac_session(chip, buf);
   328		rc = tpm_transmit_cmd(chip, buf, 4, "sealing data");
   329		rc = tpm_buf_check_hmac_response(chip, buf, rc);
   330		if (rc)
   331			goto out;
   332	
   333		blob_len = tpm_buf_read_u32(buf, &offset);
   334		if (blob_len > MAX_BLOB_SIZE || buf->flags & TPM_BUF_BOUNDARY_ERROR) {
   335			rc = -E2BIG;
   336			goto out;
   337		}
   338		if (buf->length - offset < blob_len) {
   339			rc = -EFAULT;
   340			goto out;
   341		}
   342	
   343		blob_len = tpm2_key_encode(payload, options, &buf->data[offset],
   344					   blob_len);
   345	
   346	out:
   347		if (rc > 0) {
   348			if (tpm2_rc_value(rc) == TPM2_RC_HASH)
   349				rc = -EINVAL;
   350			else
   351				rc = -EPERM;
   352		}
   353		if (blob_len < 0)
   354			rc = blob_len;
   355		else
   356			payload->blob_len = blob_len;
   357	
   358	out_put:
   359		tpm_put_ops(chip);
   360		return rc;
   361	}
   362	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-06-29 18:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-26 10:19 [PATCH v2] tpm: Cleanup class for tpm_buf Jarkko Sakkinen
2025-06-26 14:50 ` James Bottomley
2025-06-26 18:11   ` Jarkko Sakkinen
2025-06-26 22:35     ` Jarkko Sakkinen
2025-06-26 21:59 ` kernel test robot
2025-06-27 21:41 ` Dan Carpenter
2025-06-28  2:14 ` Jarkko Sakkinen
2025-06-29 18:30 ` kernel test robot
  -- strict thread matches above, loose matches on Subject: below --
2025-06-27 21:13 kernel test robot

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.