]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
patches for 4.9
authorSasha Levin (Microsoft) <sashal@kernel.org>
Wed, 17 Apr 2019 17:16:23 +0000 (13:16 -0400)
committerSasha Levin (Microsoft) <sashal@kernel.org>
Wed, 17 Apr 2019 17:16:23 +0000 (13:16 -0400)
Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org>
queue-4.9/series
queue-4.9/tpm-tpm_crb-avoid-unaligned-reads-in-crb_recv.patch [new file with mode: 0644]

index ed54a653076d82f1e11def7f8e10b44a11d2221e..a9c733da4dfbf1b6e669dbd32057da069e3c587e 100644 (file)
@@ -45,3 +45,4 @@ arm-8839-1-kprobe-make-patch_lock-a-raw_spinlock_t.patch
 appletalk-fix-use-after-free-in-atalk_proc_exit.patch
 lib-div64.c-off-by-one-in-shift.patch
 include-linux-swap.h-use-offsetof-instead-of-custom-.patch
+tpm-tpm_crb-avoid-unaligned-reads-in-crb_recv.patch
diff --git a/queue-4.9/tpm-tpm_crb-avoid-unaligned-reads-in-crb_recv.patch b/queue-4.9/tpm-tpm_crb-avoid-unaligned-reads-in-crb_recv.patch
new file mode 100644 (file)
index 0000000..141acca
--- /dev/null
@@ -0,0 +1,77 @@
+From 7dd49a1da166df1e0620aef1f17050de166a7d07 Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Date: Wed, 17 Apr 2019 17:59:15 +0300
+Subject: tpm/tpm_crb: Avoid unaligned reads in crb_recv()
+
+commit 3d7a850fdc1a2e4d2adbc95cc0fc962974725e88 upstream
+
+The current approach to read first 6 bytes from the response and then tail
+of the response, can cause the 2nd memcpy_fromio() to do an unaligned read
+(e.g. read 32-bit word from address aligned to a 16-bits), depending on how
+memcpy_fromio() is implemented. If this happens, the read will fail and the
+memory controller will fill the read with 1's.
+
+This was triggered by 170d13ca3a2f, which should be probably refined to
+check and react to the address alignment. Before that commit, on x86
+memcpy_fromio() turned out to be memcpy(). By a luck GCC has done the right
+thing (from tpm_crb's perspective) for us so far, but we should not rely on
+that. Thus, it makes sense to fix this also in tpm_crb, not least because
+the fix can be then backported to stable kernels and make them more robust
+when compiled in differing environments.
+
+Cc: stable@vger.kernel.org
+Cc: James Morris <jmorris@namei.org>
+Cc: Tomas Winkler <tomas.winkler@intel.com>
+Cc: Jerry Snitselaar <jsnitsel@redhat.com>
+Fixes: 30fc8d138e91 ("tpm: TPM 2.0 CRB Interface")
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Acked-by: Tomas Winkler <tomas.winkler@intel.com>
+Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm_crb.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
+index fa0f66809503..d29f78441cdb 100644
+--- a/drivers/char/tpm/tpm_crb.c
++++ b/drivers/char/tpm/tpm_crb.c
+@@ -102,19 +102,29 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+       struct crb_priv *priv = dev_get_drvdata(&chip->dev);
+       unsigned int expected;
+-      /* sanity check */
+-      if (count < 6)
++      /* A sanity check that the upper layer wants to get at least the header
++       * as that is the minimum size for any TPM response.
++       */
++      if (count < TPM_HEADER_SIZE)
+               return -EIO;
++      /* If this bit is set, according to the spec, the TPM is in
++       * unrecoverable condition.
++       */
+       if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR)
+               return -EIO;
+-      memcpy_fromio(buf, priv->rsp, 6);
+-      expected = be32_to_cpup((__be32 *) &buf[2]);
+-      if (expected > count || expected < 6)
++      /* Read the first 8 bytes in order to get the length of the response.
++       * We read exactly a quad word in order to make sure that the remaining
++       * reads will be aligned.
++       */
++      memcpy_fromio(buf, priv->rsp, 8);
++
++      expected = be32_to_cpup((__be32 *)&buf[2]);
++      if (expected > count || expected < TPM_HEADER_SIZE)
+               return -EIO;
+-      memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6);
++      memcpy_fromio(&buf[8], &priv->rsp[8], expected - 8);
+       return expected;
+ }
+-- 
+2.19.1
+