| From f9d4d9b5a5ef2f017bc344fb65a58a902517173b Mon Sep 17 00:00:00 2001 |
| From: Jeremy Boone <jeremy.boone@nccgroup.trust> |
| Date: Thu, 8 Feb 2018 12:31:16 -0800 |
| Subject: tpm_i2c_nuvoton: fix potential buffer overruns caused by bit glitches on the bus |
| |
| From: Jeremy Boone <jeremy.boone@nccgroup.trust> |
| |
| commit f9d4d9b5a5ef2f017bc344fb65a58a902517173b upstream. |
| |
| Discrete TPMs are often connected over slow serial buses which, on |
| some platforms, can have glitches causing bit flips. In all the |
| driver _recv() functions, we need to use a u32 to unmarshal the |
| response size, otherwise a bit flip of the 31st bit would cause the |
| expected variable to go negative, which would then try to read a huge |
| amount of data. Also sanity check that the expected amount of data is |
| large enough for the TPM header. |
| |
| Signed-off-by: Jeremy Boone <jeremy.boone@nccgroup.trust> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> |
| Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: James Morris <james.morris@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/char/tpm/tpm_i2c_nuvoton.c | 8 ++++++-- |
| 1 file changed, 6 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/char/tpm/tpm_i2c_nuvoton.c |
| +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c |
| @@ -281,7 +281,11 @@ static int i2c_nuvoton_recv(struct tpm_c |
| struct device *dev = chip->dev.parent; |
| struct i2c_client *client = to_i2c_client(dev); |
| s32 rc; |
| - int expected, status, burst_count, retries, size = 0; |
| + int status; |
| + int burst_count; |
| + int retries; |
| + int size = 0; |
| + u32 expected; |
| |
| if (count < TPM_HEADER_SIZE) { |
| i2c_nuvoton_ready(chip); /* return to idle */ |
| @@ -323,7 +327,7 @@ static int i2c_nuvoton_recv(struct tpm_c |
| * to machine native |
| */ |
| expected = be32_to_cpu(*(__be32 *) (buf + 2)); |
| - if (expected > count) { |
| + if (expected > count || expected < size) { |
| dev_err(dev, "%s() expected > count\n", __func__); |
| size = -EIO; |
| continue; |