The ST33ZP24 driver parses TPM command and response headers from byte
transport buffers. st33zp24_recv() reads the response size from bytes
2..5 of the TPM header, and st33zp24_send() reads the command ordinal
from bytes 6..9 when IRQ mode waits for command completion.

Those fields are 32-bit big-endian protocol fields, but their TPM
header offsets are not 32-bit aligned: the header starts with a 2-byte
tag, so both offsets 2 and 6 are 2 modulo 4. Even if the caller buffer
is 4-byte aligned, casting buf + 2 or buf + 6 to __be32 * still creates
a misaligned typed access.

Use get_unaligned_be32() for both TPM header fields.

This issue was detected by our static analysis tool and confirmed by
manual audit. A focused UBSAN alignment validation of the same typed
load shape reported a misaligned __be32 access in st33zp24_recv().

Fixes: bf38b8710892 ("tpm/tpm_i2c_stm_st33: Split tpm_i2c_tpm_st33 in 2 layers 
(core + phy)")
Cc: [email protected]
Signed-off-by: Runyu Xiao <[email protected]>
---
 drivers/char/tpm/st33zp24/st33zp24.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/char/tpm/st33zp24/st33zp24.c 
b/drivers/char/tpm/st33zp24/st33zp24.c
index e2b7451ea7cc..2d74f30c2fc0 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -18,6 +18,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/unaligned.h>
 
 #include "../tpm.h"
 #include "st33zp24.h"
@@ -364,7 +365,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned 
char *buf,
                goto out_err;
 
        if (chip->flags & TPM_CHIP_FLAG_IRQ) {
-               ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+               ordinal = get_unaligned_be32(buf + 6);
 
                ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
                                tpm_calc_ordinal_duration(chip, ordinal),
@@ -400,7 +401,7 @@ static int st33zp24_recv(struct tpm_chip *chip, unsigned 
char *buf,
                goto out;
        }
 
-       expected = be32_to_cpu(*(__be32 *)(buf + 2));
+       expected = get_unaligned_be32(buf + 2);
        if (expected > count || expected < TPM_HEADER_SIZE) {
                size = -EIO;
                goto out;
-- 
2.34.1


Reply via email to