[PATCH] tpm: fix off-by-four bounds check in tpm2_get_random()

Jiangshan Yi posted 1 patch 3 weeks, 2 days ago
drivers/char/tpm/tpm2-cmd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] tpm: fix off-by-four bounds check in tpm2_get_random()
Posted by Jiangshan Yi 3 weeks, 2 days ago
When the response carries the TPM2_ST_SESSIONS tag, tpm2_get_random()
skips the 4-byte parameter size field before locating the random data,
but the bounds check still validates the response length against
TPM_HEADER_SIZE.  A truncated response can pass the check and make
memcpy() read up to 4 bytes past the response end, so stale buffer
contents end up in the caller's random bytes.

Fix this by checking the response length against 'offset', which
already includes the skipped parameter size field.

Fixes: 1b6d7f9eb150 ("tpm: add session encryption protection to tpm2_get_random()")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260902074839.417419-1-yijiangshan%40kylinos.cn
Cc: stable@vger.kernel.org
Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
---
 drivers/char/tpm/tpm2-cmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 48cec39995fe..d74df7808a3f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -305,7 +305,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
 		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) <
-		    TPM_HEADER_SIZE +
+		    offset +
 		    offsetof(struct tpm2_get_random_out, buffer) +
 		    recd) {
 			tpm2_end_auth_session(chip);
-- 
2.25.1
Re: [PATCH] tpm: fix off-by-four bounds check in tpm2_get_random()
Posted by Jarkko Sakkinen 2 weeks, 2 days ago
On Thu, Sep 03, 2026 at 11:58:37AM +0800, Jiangshan Yi wrote:
> When the response carries the TPM2_ST_SESSIONS tag, tpm2_get_random()
> skips the 4-byte parameter size field before locating the random data,
> but the bounds check still validates the response length against
> TPM_HEADER_SIZE.  A truncated response can pass the check and make
> memcpy() read up to 4 bytes past the response end, so stale buffer
> contents end up in the caller's random bytes.
> 
> Fix this by checking the response length against 'offset', which
> already includes the skipped parameter size field.
> 
> Fixes: 1b6d7f9eb150 ("tpm: add session encryption protection to tpm2_get_random()")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/patchset/20260902074839.417419-1-yijiangshan%40kylinos.cn
> Cc: stable@vger.kernel.org
> Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
> ---
>  drivers/char/tpm/tpm2-cmd.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index 48cec39995fe..d74df7808a3f 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -305,7 +305,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
>  		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) <
> -		    TPM_HEADER_SIZE +
> +		    offset +
>  		    offsetof(struct tpm2_get_random_out, buffer) +
>  		    recd) {
>  			tpm2_end_auth_session(chip);
> -- 
> 2.25.1
> 


Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>

BR, Jarkko