]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 6 Mar 2018 18:26:11 +0000 (10:26 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 6 Mar 2018 18:26:11 +0000 (10:26 -0800)
added patches:
tpm-constify-transmit-data-pointers.patch
tpm-dev-common-reject-too-short-writes.patch
tpm-st33zp24-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
tpm_i2c_infineon-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
tpm_i2c_nuvoton-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
tpm_tis-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
tpm_tis_spi-use-dma-safe-memory-for-spi-transfers.patch

queue-4.9/series
queue-4.9/tpm-constify-transmit-data-pointers.patch [new file with mode: 0644]
queue-4.9/tpm-dev-common-reject-too-short-writes.patch [new file with mode: 0644]
queue-4.9/tpm-st33zp24-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch [new file with mode: 0644]
queue-4.9/tpm_i2c_infineon-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch [new file with mode: 0644]
queue-4.9/tpm_i2c_nuvoton-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch [new file with mode: 0644]
queue-4.9/tpm_tis-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch [new file with mode: 0644]
queue-4.9/tpm_tis_spi-use-dma-safe-memory-for-spi-transfers.patch [new file with mode: 0644]

index 14ea8ac7a1784541c2b8c5de8ffb2aacc1c7d1db..cd0474213fab14e1eecebca1b69567024564327d 100644 (file)
@@ -1 +1,8 @@
 bluetooth-btusb-use-dmi-matching-for-qca-reset_resume-quirking.patch
+tpm-st33zp24-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm_i2c_infineon-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm_i2c_nuvoton-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm_tis-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm-constify-transmit-data-pointers.patch
+tpm_tis_spi-use-dma-safe-memory-for-spi-transfers.patch
+tpm-dev-common-reject-too-short-writes.patch
diff --git a/queue-4.9/tpm-constify-transmit-data-pointers.patch b/queue-4.9/tpm-constify-transmit-data-pointers.patch
new file mode 100644 (file)
index 0000000..edb0eef
--- /dev/null
@@ -0,0 +1,156 @@
+From c37fbc09bd4977736f6bc4050c6f099c587052a7 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 7 Sep 2017 15:30:45 +0200
+Subject: tpm: constify transmit data pointers
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit c37fbc09bd4977736f6bc4050c6f099c587052a7 upstream.
+
+Making cmd_getticks 'const' introduced a couple of harmless warnings:
+
+drivers/char/tpm/tpm_tis_core.c: In function 'probe_itpm':
+drivers/char/tpm/tpm_tis_core.c:469:31: error: passing argument 2 of 'tpm_tis_send_data' discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
+  rc = tpm_tis_send_data(chip, cmd_getticks, len);
+drivers/char/tpm/tpm_tis_core.c:477:31: error: passing argument 2 of 'tpm_tis_send_data' discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
+  rc = tpm_tis_send_data(chip, cmd_getticks, len);
+drivers/char/tpm/tpm_tis_core.c:255:12: note: expected 'u8 * {aka unsigned char *}' but argument is of type 'const u8 * {aka const unsigned char *}'
+ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
+
+This changes the related functions to all take 'const' pointers
+so that gcc can see this as being correct. I had to slightly
+modify the logic around tpm_tis_spi_transfer() for this to work
+without introducing ugly casts.
+
+Cc: stable@vger.kernel.org
+Fixes: 5e35bd8e06b9 ("tpm_tis: make array cmd_getticks static const to shink object code size")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_tis.c      |    2 +-
+ drivers/char/tpm/tpm_tis_core.c |    4 ++--
+ drivers/char/tpm/tpm_tis_core.h |    4 ++--
+ drivers/char/tpm/tpm_tis_spi.c  |   25 +++++++++++--------------
+ 4 files changed, 16 insertions(+), 19 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -98,7 +98,7 @@ static int tpm_tcg_read_bytes(struct tpm
+ }
+ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
+-                             u8 *value)
++                             const u8 *value)
+ {
+       struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -257,7 +257,7 @@ out:
+  * tpm.c can skip polling for the data to be available as the interrupt is
+  * waited for here
+  */
+-static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
++static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
+ {
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       int rc, status, burstcnt;
+@@ -346,7 +346,7 @@ static void disable_interrupts(struct tp
+  * tpm.c can skip polling for the data to be available as the interrupt is
+  * waited for here
+  */
+-static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
++static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
+ {
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       int rc;
+--- a/drivers/char/tpm/tpm_tis_core.h
++++ b/drivers/char/tpm/tpm_tis_core.h
+@@ -98,7 +98,7 @@ struct tpm_tis_phy_ops {
+       int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
+                         u8 *result);
+       int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
+-                         u8 *value);
++                         const u8 *value);
+       int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result);
+       int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result);
+       int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src);
+@@ -128,7 +128,7 @@ static inline int tpm_tis_read32(struct
+ }
+ static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr,
+-                                    u16 len, u8 *value)
++                                    u16 len, const u8 *value)
+ {
+       return data->phy_ops->write_bytes(data, addr, len, value);
+ }
+--- a/drivers/char/tpm/tpm_tis_spi.c
++++ b/drivers/char/tpm/tpm_tis_spi.c
+@@ -58,7 +58,7 @@ static inline struct tpm_tis_spi_phy *to
+ }
+ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
+-                              u8 *buffer, u8 direction)
++                              u8 *in, const u8 *out)
+ {
+       struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
+       int ret = 0;
+@@ -72,7 +72,7 @@ static int tpm_tis_spi_transfer(struct t
+       while (len) {
+               transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+-              phy->tx_buf[0] = direction | (transfer_len - 1);
++              phy->tx_buf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+               phy->tx_buf[1] = 0xd4;
+               phy->tx_buf[2] = addr >> 8;
+               phy->tx_buf[3] = addr;
+@@ -113,14 +113,8 @@ static int tpm_tis_spi_transfer(struct t
+               spi_xfer.cs_change = 0;
+               spi_xfer.len = transfer_len;
+               spi_xfer.delay_usecs = 5;
+-
+-              if (direction) {
+-                      spi_xfer.tx_buf = NULL;
+-                      spi_xfer.rx_buf = buffer;
+-              } else {
+-                      spi_xfer.tx_buf = buffer;
+-                      spi_xfer.rx_buf = NULL;
+-              }
++              spi_xfer.tx_buf = out;
++              spi_xfer.rx_buf = in;
+               spi_message_init(&m);
+               spi_message_add_tail(&spi_xfer, &m);
+@@ -129,7 +123,10 @@ static int tpm_tis_spi_transfer(struct t
+                       goto exit;
+               len -= transfer_len;
+-              buffer += transfer_len;
++              if (in)
++                      in += transfer_len;
++              if (out)
++                      out += transfer_len;
+       }
+ exit:
+@@ -140,13 +137,13 @@ exit:
+ static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
+                                 u16 len, u8 *result)
+ {
+-      return tpm_tis_spi_transfer(data, addr, len, result, 0x80);
++      return tpm_tis_spi_transfer(data, addr, len, result, NULL);
+ }
+ static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
+-                                 u16 len, u8 *value)
++                                 u16 len, const u8 *value)
+ {
+-      return tpm_tis_spi_transfer(data, addr, len, value, 0);
++      return tpm_tis_spi_transfer(data, addr, len, NULL, value);
+ }
+ static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
diff --git a/queue-4.9/tpm-dev-common-reject-too-short-writes.patch b/queue-4.9/tpm-dev-common-reject-too-short-writes.patch
new file mode 100644 (file)
index 0000000..67d2e15
--- /dev/null
@@ -0,0 +1,45 @@
+From ee70bc1e7b63ac8023c9ff9475d8741e397316e7 Mon Sep 17 00:00:00 2001
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+Date: Fri, 8 Sep 2017 17:21:32 +0200
+Subject: tpm-dev-common: Reject too short writes
+
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+
+commit ee70bc1e7b63ac8023c9ff9475d8741e397316e7 upstream.
+
+tpm_transmit() does not offer an explicit interface to indicate the number
+of valid bytes in the communication buffer. Instead, it relies on the
+commandSize field in the TPM header that is encoded within the buffer.
+Therefore, ensure that a) enough data has been written to the buffer, so
+that the commandSize field is present and b) the commandSize field does not
+announce more data than has been written to the buffer.
+
+This should have been fixed with CVE-2011-1161 long ago, but apparently
+a correct version of that patch never made it into the kernel.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm-dev.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/char/tpm/tpm-dev.c
++++ b/drivers/char/tpm/tpm-dev.c
+@@ -136,6 +136,12 @@ static ssize_t tpm_write(struct file *fi
+               return -EFAULT;
+       }
++      if (in_size < 6 ||
++          in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) {
++              mutex_unlock(&priv->buffer_mutex);
++              return -EINVAL;
++      }
++
+       /* atomic tpm command send and result receive. We only hold the ops
+        * lock during this period so that the tpm can be unregistered even if
+        * the char dev is held open.
diff --git a/queue-4.9/tpm-st33zp24-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch b/queue-4.9/tpm-st33zp24-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
new file mode 100644 (file)
index 0000000..b166ba1
--- /dev/null
@@ -0,0 +1,49 @@
+From 6d24cd186d9fead3722108dec1b1c993354645ff Mon Sep 17 00:00:00 2001
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Date: Thu, 8 Feb 2018 12:29:09 -0800
+Subject: tpm: st33zp24: fix potential buffer overruns caused by bit glitches on the bus
+
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+
+commit 6d24cd186d9fead3722108dec1b1c993354645ff 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/st33zp24/st33zp24.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/st33zp24/st33zp24.c
++++ b/drivers/char/tpm/st33zp24/st33zp24.c
+@@ -458,7 +458,7 @@ static int st33zp24_recv(struct tpm_chip
+                           size_t count)
+ {
+       int size = 0;
+-      int expected;
++      u32 expected;
+       if (!chip)
+               return -EBUSY;
+@@ -475,7 +475,7 @@ static int st33zp24_recv(struct tpm_chip
+       }
+       expected = be32_to_cpu(*(__be32 *)(buf + 2));
+-      if (expected > count) {
++      if (expected > count || expected < TPM_HEADER_SIZE) {
+               size = -EIO;
+               goto out;
+       }
diff --git a/queue-4.9/tpm_i2c_infineon-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch b/queue-4.9/tpm_i2c_infineon-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
new file mode 100644 (file)
index 0000000..487df33
--- /dev/null
@@ -0,0 +1,50 @@
+From 9b8cb28d7c62568a5916bdd7ea1c9176d7f8f2ed Mon Sep 17 00:00:00 2001
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Date: Thu, 8 Feb 2018 12:30:01 -0800
+Subject: tpm_i2c_infineon: fix potential buffer overruns caused by bit glitches on the bus
+
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+
+commit 9b8cb28d7c62568a5916bdd7ea1c9176d7f8f2ed 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_infineon.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_i2c_infineon.c
++++ b/drivers/char/tpm/tpm_i2c_infineon.c
+@@ -437,7 +437,8 @@ static int recv_data(struct tpm_chip *ch
+ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+ {
+       int size = 0;
+-      int expected, status;
++      int status;
++      u32 expected;
+       if (count < TPM_HEADER_SIZE) {
+               size = -EIO;
+@@ -452,7 +453,7 @@ static int tpm_tis_i2c_recv(struct tpm_c
+       }
+       expected = be32_to_cpu(*(__be32 *)(buf + 2));
+-      if ((size_t) expected > count) {
++      if (((size_t) expected > count) || (expected < TPM_HEADER_SIZE)) {
+               size = -EIO;
+               goto out;
+       }
diff --git a/queue-4.9/tpm_i2c_nuvoton-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch b/queue-4.9/tpm_i2c_nuvoton-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
new file mode 100644 (file)
index 0000000..22596e7
--- /dev/null
@@ -0,0 +1,53 @@
+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;
diff --git a/queue-4.9/tpm_tis-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch b/queue-4.9/tpm_tis-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
new file mode 100644 (file)
index 0000000..5eb4111
--- /dev/null
@@ -0,0 +1,51 @@
+From 6bb320ca4a4a7b5b3db8c8d7250cc40002046878 Mon Sep 17 00:00:00 2001
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Date: Thu, 8 Feb 2018 12:32:06 -0800
+Subject: tpm_tis: fix potential buffer overruns caused by bit glitches on the bus
+
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+
+commit 6bb320ca4a4a7b5b3db8c8d7250cc40002046878 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>
+Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.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_tis_core.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -208,7 +208,8 @@ static int tpm_tis_recv(struct tpm_chip
+ {
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       int size = 0;
+-      int expected, status;
++      int status;
++      u32 expected;
+       if (count < TPM_HEADER_SIZE) {
+               size = -EIO;
+@@ -223,7 +224,7 @@ static int tpm_tis_recv(struct tpm_chip
+       }
+       expected = be32_to_cpu(*(__be32 *) (buf + 2));
+-      if (expected > count) {
++      if (expected > count || expected < TPM_HEADER_SIZE) {
+               size = -EIO;
+               goto out;
+       }
diff --git a/queue-4.9/tpm_tis_spi-use-dma-safe-memory-for-spi-transfers.patch b/queue-4.9/tpm_tis_spi-use-dma-safe-memory-for-spi-transfers.patch
new file mode 100644 (file)
index 0000000..2cd7bca
--- /dev/null
@@ -0,0 +1,129 @@
+From 6b3a13173f23e798e1ba213dd4a2c065a3b8d751 Mon Sep 17 00:00:00 2001
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+Date: Mon, 11 Sep 2017 12:26:52 +0200
+Subject: tpm_tis_spi: Use DMA-safe memory for SPI transfers
+
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+
+commit 6b3a13173f23e798e1ba213dd4a2c065a3b8d751 upstream.
+
+The buffers used as tx_buf/rx_buf in a SPI transfer need to be DMA-safe.
+This cannot be guaranteed for the buffers passed to tpm_tis_spi_read_bytes
+and tpm_tis_spi_write_bytes. Therefore, we need to use our own DMA-safe
+buffer and copy the data to/from it.
+
+The buffer needs to be allocated separately, to ensure that it is
+cacheline-aligned and not shared with other data, so that DMA can work
+correctly.
+
+Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy")
+Cc: stable@vger.kernel.org
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_tis_spi.c |   45 ++++++++++++++++++++++++-----------------
+ 1 file changed, 27 insertions(+), 18 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_spi.c
++++ b/drivers/char/tpm/tpm_tis_spi.c
+@@ -47,9 +47,7 @@
+ struct tpm_tis_spi_phy {
+       struct tpm_tis_data priv;
+       struct spi_device *spi_device;
+-
+-      u8 tx_buf[4];
+-      u8 rx_buf[4];
++      u8 *iobuf;
+ };
+ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
+@@ -72,14 +70,14 @@ static int tpm_tis_spi_transfer(struct t
+       while (len) {
+               transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+-              phy->tx_buf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+-              phy->tx_buf[1] = 0xd4;
+-              phy->tx_buf[2] = addr >> 8;
+-              phy->tx_buf[3] = addr;
++              phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
++              phy->iobuf[1] = 0xd4;
++              phy->iobuf[2] = addr >> 8;
++              phy->iobuf[3] = addr;
+               memset(&spi_xfer, 0, sizeof(spi_xfer));
+-              spi_xfer.tx_buf = phy->tx_buf;
+-              spi_xfer.rx_buf = phy->rx_buf;
++              spi_xfer.tx_buf = phy->iobuf;
++              spi_xfer.rx_buf = phy->iobuf;
+               spi_xfer.len = 4;
+               spi_xfer.cs_change = 1;
+@@ -89,9 +87,9 @@ static int tpm_tis_spi_transfer(struct t
+               if (ret < 0)
+                       goto exit;
+-              if ((phy->rx_buf[3] & 0x01) == 0) {
++              if ((phy->iobuf[3] & 0x01) == 0) {
+                       // handle SPI wait states
+-                      phy->tx_buf[0] = 0;
++                      phy->iobuf[0] = 0;
+                       for (i = 0; i < TPM_RETRY; i++) {
+                               spi_xfer.len = 1;
+@@ -100,7 +98,7 @@ static int tpm_tis_spi_transfer(struct t
+                               ret = spi_sync_locked(phy->spi_device, &m);
+                               if (ret < 0)
+                                       goto exit;
+-                              if (phy->rx_buf[0] & 0x01)
++                              if (phy->iobuf[0] & 0x01)
+                                       break;
+                       }
+@@ -113,8 +111,14 @@ static int tpm_tis_spi_transfer(struct t
+               spi_xfer.cs_change = 0;
+               spi_xfer.len = transfer_len;
+               spi_xfer.delay_usecs = 5;
+-              spi_xfer.tx_buf = out;
+-              spi_xfer.rx_buf = in;
++
++              if (in) {
++                      spi_xfer.tx_buf = NULL;
++              } else if (out) {
++                      spi_xfer.rx_buf = NULL;
++                      memcpy(phy->iobuf, out, transfer_len);
++                      out += transfer_len;
++              }
+               spi_message_init(&m);
+               spi_message_add_tail(&spi_xfer, &m);
+@@ -122,11 +126,12 @@ static int tpm_tis_spi_transfer(struct t
+               if (ret < 0)
+                       goto exit;
+-              len -= transfer_len;
+-              if (in)
++              if (in) {
++                      memcpy(in, phy->iobuf, transfer_len);
+                       in += transfer_len;
+-              if (out)
+-                      out += transfer_len;
++              }
++
++              len -= transfer_len;
+       }
+ exit:
+@@ -192,6 +197,10 @@ static int tpm_tis_spi_probe(struct spi_
+       phy->spi_device = dev;
++      phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
++      if (!phy->iobuf)
++              return -ENOMEM;
++
+       return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops,
+                                NULL);
+ }