CVE-2026-46096
Description
In the Linux kernel, the following vulnerability has been resolved:
tpm2-sessions: Fix missing tpm_buf_destroy() in tpm2_read_public()
tpm2_read_public() calls tpm_buf_init() but fails to call tpm_buf_destroy() on two exit paths, leaking a page allocation:
1. When name_size() returns an error (unrecognized hash algorithm), the function returns directly without destroying the buffer.
2. On the success path, the buffer is never destroyed before returning.
All other error paths in the function correctly call tpm_buf_destroy() before returning.
Fix both by adding the missing tpm_buf_destroy() calls.
Affected products
1Patches
6f8775d9d9062tpm2-sessions: Fix missing tpm_buf_destroy() in tpm2_read_public()
1 file changed · +4 −2
drivers/char/tpm/tpm2-sessions.c+4 −2 modifieddiff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 3f389e2f6f580b..6e53a25f61d491 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -203,8 +203,10 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) rc = tpm_buf_read_u16(&buf, &offset); name_size_alg = name_size(&buf.data[offset]); - if (name_size_alg < 0) + if (name_size_alg < 0) { + tpm_buf_destroy(&buf); return name_size_alg; + } if (rc != name_size_alg) { tpm_buf_destroy(&buf); @@ -217,6 +219,7 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) } memcpy(name, &buf.data[offset], rc); + tpm_buf_destroy(&buf); return name_size_alg; } #endif /* CONFIG_TCG_TPM2_HMAC */ -- cgit 1.3-korg
2f434be87e25tpm2-sessions: Fix missing tpm_buf_destroy() in tpm2_read_public()
1 file changed · +4 −2
drivers/char/tpm/tpm2-sessions.c+4 −2 modifieddiff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 3b1cf1ca042005..c4da6fde748f41 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -203,8 +203,10 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) rc = tpm_buf_read_u16(&buf, &offset); name_size_alg = name_size(&buf.data[offset]); - if (name_size_alg < 0) + if (name_size_alg < 0) { + tpm_buf_destroy(&buf); return name_size_alg; + } if (rc != name_size_alg) { tpm_buf_destroy(&buf); @@ -217,6 +219,7 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) } memcpy(name, &buf.data[offset], rc); + tpm_buf_destroy(&buf); return name_size_alg; } #endif /* CONFIG_TCG_TPM2_HMAC */ -- cgit 1.3-korg
f0f75a3d98b7tpm2-sessions: Fix missing tpm_buf_destroy() in tpm2_read_public()
1 file changed · +4 −2
drivers/char/tpm/tpm2-sessions.c+4 −2 modifieddiff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 3b1cf1ca042005..c4da6fde748f41 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -203,8 +203,10 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) rc = tpm_buf_read_u16(&buf, &offset); name_size_alg = name_size(&buf.data[offset]); - if (name_size_alg < 0) + if (name_size_alg < 0) { + tpm_buf_destroy(&buf); return name_size_alg; + } if (rc != name_size_alg) { tpm_buf_destroy(&buf); @@ -217,6 +219,7 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) } memcpy(name, &buf.data[offset], rc); + tpm_buf_destroy(&buf); return name_size_alg; } #endif /* CONFIG_TCG_TPM2_HMAC */ -- cgit 1.3-korg
f0f75a3d98b7tpm2-sessions: Fix missing tpm_buf_destroy() in tpm2_read_public()
1 file changed · +4 −2
drivers/char/tpm/tpm2-sessions.c+4 −2 modifieddiff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 3b1cf1ca042005..c4da6fde748f41 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -203,8 +203,10 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) rc = tpm_buf_read_u16(&buf, &offset); name_size_alg = name_size(&buf.data[offset]); - if (name_size_alg < 0) + if (name_size_alg < 0) { + tpm_buf_destroy(&buf); return name_size_alg; + } if (rc != name_size_alg) { tpm_buf_destroy(&buf); @@ -217,6 +219,7 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) } memcpy(name, &buf.data[offset], rc); + tpm_buf_destroy(&buf); return name_size_alg; } #endif /* CONFIG_TCG_TPM2_HMAC */ -- cgit 1.3-korg
2f434be87e25tpm2-sessions: Fix missing tpm_buf_destroy() in tpm2_read_public()
1 file changed · +4 −2
drivers/char/tpm/tpm2-sessions.c+4 −2 modifieddiff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 3b1cf1ca042005..c4da6fde748f41 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -203,8 +203,10 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) rc = tpm_buf_read_u16(&buf, &offset); name_size_alg = name_size(&buf.data[offset]); - if (name_size_alg < 0) + if (name_size_alg < 0) { + tpm_buf_destroy(&buf); return name_size_alg; + } if (rc != name_size_alg) { tpm_buf_destroy(&buf); @@ -217,6 +219,7 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) } memcpy(name, &buf.data[offset], rc); + tpm_buf_destroy(&buf); return name_size_alg; } #endif /* CONFIG_TCG_TPM2_HMAC */ -- cgit 1.3-korg
f8775d9d9062tpm2-sessions: Fix missing tpm_buf_destroy() in tpm2_read_public()
1 file changed · +4 −2
drivers/char/tpm/tpm2-sessions.c+4 −2 modifieddiff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 3f389e2f6f580b..6e53a25f61d491 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -203,8 +203,10 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) rc = tpm_buf_read_u16(&buf, &offset); name_size_alg = name_size(&buf.data[offset]); - if (name_size_alg < 0) + if (name_size_alg < 0) { + tpm_buf_destroy(&buf); return name_size_alg; + } if (rc != name_size_alg) { tpm_buf_destroy(&buf); @@ -217,6 +219,7 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) } memcpy(name, &buf.data[offset], rc); + tpm_buf_destroy(&buf); return name_size_alg; } #endif /* CONFIG_TCG_TPM2_HMAC */ -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing tpm_buf_destroy() calls in tpm2_read_public() on two exit paths cause a page allocation to be leaked."
Attack vector
An attacker who can trigger a TPM2_ReadPublic command that results in an unrecognized hash algorithm (causing name_size() to return an error) will cause the function to return early without destroying the TPM buffer, leaking a page allocation [patch_id=2659739]. Similarly, on the normal success path the buffer was never destroyed before returning, so any caller of tpm2_read_public() would leak a page. The vulnerability is reachable through any kernel code path that calls tpm2_read_public() with a TPM handle, which may include user-facing TPM device operations.
Affected code
The function tpm2_read_public() in drivers/char/tpm/tpm2-sessions.c is affected [patch_id=2659739]. The buffer allocated by tpm_buf_init() was not freed on the early-return path when name_size() returns a negative value, nor on the normal success path after memcpy().
What the fix does
The patch adds tpm_buf_destroy(&buf) in two places in tpm2_read_public() [patch_id=2659739]. First, inside the error-handling block for when name_size_alg < 0, the buffer is now destroyed before returning the error code. Second, on the success path after memcpy(), tpm_buf_destroy(&buf) is called before the final return. These additions ensure that every call to tpm_buf_init() is paired with a corresponding tpm_buf_destroy(), preventing the page leak.
Preconditions
- configThe kernel must be built with CONFIG_TCG_TPM2_HMAC enabled (the #ifdef guard around the function).
- inputAn attacker must be able to trigger a call to tpm2_read_public() with a TPM handle that causes name_size() to return an error (e.g., an unrecognized hash algorithm), or simply invoke the function normally to hit the success-path leak.
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.