[PATCH 2/2] mtd: spi-nor: sfdp: check the length of the SCCR map

HyeongJun An <[email protected]>
Newsgroups org.infradead.lists.linux-mtd,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
spi_nor_parse_sccr() sizes its bounce buffer from the length the flash
reports in the SFDP parameter header, then reads DWORD22 out of it:

    len = sccr_header->length * sizeof(*dwords);
    dwords = kmalloc(len, GFP_KERNEL);
    ...
    if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE,
                  dwords[SFDP_DWORD(22)]))

Nothing checks that the table actually has 22 DWORDs.  The length is a
u8 the flash supplies, so a device advertising the SCCR map with a
shorter length makes the read run past the allocation: with a length of
one the buffer is four bytes and dwords[SFDP_DWORD(22)] reads
eighty-four bytes beyond it.  A length of zero is worse, as kmalloc()
then returns ZERO_SIZE_PTR rather than an error and the read of
dwords[SFDP_DWORD(1)] dereferences it.

Reject a table shorter than the highest DWORD the parser reads, the way
spi_nor_parse_4bait() already does with SFDP_4BAIT_DWORD_MAX.  Failing
an optional parameter table is not fatal: spi_nor_parse_sfdp() warns and
carries on with the data gathered so far.

spi_nor_parse_sccr_mc() does not need the same check.  It derives the
number of dice from the length it allocated with, so its highest index
stays inside the buffer, and a length below two leaves its loop empty.

Fixes: 7ab8b810757a ("mtd: spi-nor: sfdp: Add support for SCCR map for multi-chip device")
Cc: [email protected]
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: HyeongJun An <[email protected]>
---
 drivers/mtd/spi-nor/sfdp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index d3d85b5d1b4a..6c9db103a29a 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -1266,6 +1266,7 @@ static int spi_nor_parse_profile1(struct spi_nor *nor,
 }
 
 #define SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE		BIT(31)
+#define SFDP_SCCR_DWORD_MAX				22
 
 /**
  * spi_nor_parse_sccr() - Parse the Status, Control and Configuration Register
@@ -1284,6 +1285,9 @@ static int spi_nor_parse_sccr(struct spi_nor *nor,
 	size_t len;
 	int ret;
 
+	if (sccr_header->length < SFDP_SCCR_DWORD_MAX)
+		return -EINVAL;
+
 	len = sccr_header->length * sizeof(*dwords);
 	dwords = kmalloc(len, GFP_KERNEL);
 	if (!dwords)
-- 
2.43.0


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.