| From e5e415262330bd70f983e091d8919d9dcd99e475 Mon Sep 17 00:00:00 2001 |
| From: Pengpeng Hou <pengpeng@iscas.ac.cn> |
| Date: Mon, 20 Jul 2026 19:57:25 +0800 |
| Subject: mtd: rawnand: validate ONFI extended parameter page sections |
| |
| From: Pengpeng Hou <pengpeng@iscas.ac.cn> |
| |
| commit e5e415262330bd70f983e091d8919d9dcd99e475 upstream. |
| |
| nand_flash_detect_ext_param_page() allocates the length declared by the |
| ONFI parameter page, then treats the data as a fixed header followed by |
| variable-length sections. It reads that header and advances over sections |
| without first proving that the fixed page and each current section fit in |
| the allocation. |
| |
| Reject pages shorter than the fixed header, track the remaining variable |
| area while walking sections, and require the ECC section to contain every |
| field read from struct onfi_ext_ecc_info. Use device-scoped diagnostics |
| that identify the malformed ONFI section. |
| |
| Fixes: 6dcbe0cdd83f ("mtd: get the ECC info from the Extended Parameter Page") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn> |
| Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/mtd/nand/raw/nand_onfi.c | 27 +++++++++++++++++++++++++-- |
| 1 file changed, 25 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/mtd/nand/raw/nand_onfi.c |
| +++ b/drivers/mtd/nand/raw/nand_onfi.c |
| @@ -35,16 +35,21 @@ static int nand_flash_detect_ext_param_p |
| struct nand_onfi_params *p) |
| { |
| struct nand_device *base = &chip->base; |
| + struct mtd_info *mtd = nand_to_mtd(chip); |
| struct nand_ecc_props requirements; |
| struct onfi_ext_param_page *ep; |
| struct onfi_ext_section *s; |
| struct onfi_ext_ecc_info *ecc; |
| + size_t remaining, section_len; |
| uint8_t *cursor; |
| int ret; |
| int len; |
| int i; |
| |
| len = le16_to_cpu(p->ext_param_page_length) * 16; |
| + if (len < sizeof(*ep)) |
| + return -EINVAL; |
| + |
| ep = kmalloc(len, GFP_KERNEL); |
| if (!ep) |
| return -ENOMEM; |
| @@ -77,11 +82,29 @@ static int nand_flash_detect_ext_param_p |
| |
| /* find the ECC section. */ |
| cursor = (uint8_t *)(ep + 1); |
| + remaining = len - sizeof(*ep); |
| for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) { |
| s = ep->sections + i; |
| - if (s->type == ONFI_SECTION_TYPE_2) |
| + section_len = s->length * 16; |
| + if (section_len > remaining) { |
| + dev_dbg(&mtd->dev, |
| + "ONFI extended parameter section %d exceeds page\n", |
| + i); |
| + goto ext_out; |
| + } |
| + |
| + if (s->type == ONFI_SECTION_TYPE_2) { |
| + if (section_len < sizeof(*ecc)) { |
| + dev_dbg(&mtd->dev, |
| + "ONFI extended parameter ECC section %d is too short\n", |
| + i); |
| + goto ext_out; |
| + } |
| break; |
| - cursor += s->length * 16; |
| + } |
| + |
| + cursor += section_len; |
| + remaining -= section_len; |
| } |
| if (i == ONFI_EXT_SECTION_MAX) { |
| pr_debug("We can not find the ECC section.\n"); |