]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.4/tpm-tpm_crb-avoid-unaligned-reads-in-crb_recv.patch
Fixes for 5.4
[thirdparty/kernel/stable-queue.git] / queue-4.4 / tpm-tpm_crb-avoid-unaligned-reads-in-crb_recv.patch
1 From 2380f1b1ebc63576a05e07325e64f7e7c3b9d9ef Mon Sep 17 00:00:00 2001
2 From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
3 Date: Wed, 10 Apr 2019 16:54:32 +0300
4 Subject: tpm/tpm_crb: Avoid unaligned reads in crb_recv()
5
6 commit 3d7a850fdc1a2e4d2adbc95cc0fc962974725e88 upstream
7
8 The current approach to read first 6 bytes from the response and then tail
9 of the response, can cause the 2nd memcpy_fromio() to do an unaligned read
10 (e.g. read 32-bit word from address aligned to a 16-bits), depending on how
11 memcpy_fromio() is implemented. If this happens, the read will fail and the
12 memory controller will fill the read with 1's.
13
14 This was triggered by 170d13ca3a2f, which should be probably refined to
15 check and react to the address alignment. Before that commit, on x86
16 memcpy_fromio() turned out to be memcpy(). By a luck GCC has done the right
17 thing (from tpm_crb's perspective) for us so far, but we should not rely on
18 that. Thus, it makes sense to fix this also in tpm_crb, not least because
19 the fix can be then backported to stable kernels and make them more robust
20 when compiled in differing environments.
21
22 Cc: stable@vger.kernel.org
23 Cc: James Morris <jmorris@namei.org>
24 Cc: Tomas Winkler <tomas.winkler@intel.com>
25 Cc: Jerry Snitselaar <jsnitsel@redhat.com>
26 Fixes: 30fc8d138e91 ("tpm: TPM 2.0 CRB Interface")
27 Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
28 Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
29 Acked-by: Tomas Winkler <tomas.winkler@intel.com>
30 Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org>
31 ---
32 drivers/char/tpm/tpm_crb.c | 22 ++++++++++++++++------
33 1 file changed, 16 insertions(+), 6 deletions(-)
34
35 diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
36 index 35308dfff754..8226e3b6dc1f 100644
37 --- a/drivers/char/tpm/tpm_crb.c
38 +++ b/drivers/char/tpm/tpm_crb.c
39 @@ -109,19 +109,29 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
40 struct crb_priv *priv = chip->vendor.priv;
41 unsigned int expected;
42
43 - /* sanity check */
44 - if (count < 6)
45 + /* A sanity check that the upper layer wants to get at least the header
46 + * as that is the minimum size for any TPM response.
47 + */
48 + if (count < TPM_HEADER_SIZE)
49 return -EIO;
50
51 + /* If this bit is set, according to the spec, the TPM is in
52 + * unrecoverable condition.
53 + */
54 if (le32_to_cpu(ioread32(&priv->cca->sts)) & CRB_CA_STS_ERROR)
55 return -EIO;
56
57 - memcpy_fromio(buf, priv->rsp, 6);
58 - expected = be32_to_cpup((__be32 *) &buf[2]);
59 - if (expected > count || expected < 6)
60 + /* Read the first 8 bytes in order to get the length of the response.
61 + * We read exactly a quad word in order to make sure that the remaining
62 + * reads will be aligned.
63 + */
64 + memcpy_fromio(buf, priv->rsp, 8);
65 +
66 + expected = be32_to_cpup((__be32 *)&buf[2]);
67 + if (expected > count || expected < TPM_HEADER_SIZE)
68 return -EIO;
69
70 - memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6);
71 + memcpy_fromio(&buf[8], &priv->rsp[8], expected - 8);
72
73 return expected;
74 }
75 --
76 2.19.1
77