All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "James Hilliard" <james.hilliard1@gmail.com>,
	"Miquel Raynal" <miquel.raynal@bootlin.com>,
	"Richard Weinberger" <richard@nod.at>,
	"Vignesh Raghavendra" <vigneshr@ti.com>,
	"Sebastian Andrzej Siewior" <bigeasy@linutronix.de>,
	"Clark Williams" <clrkwllms@kernel.org>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Rob Herring" <robh@kernel.org>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>
Cc: "Chen-Yu Tsai" <wens@kernel.org>,
	"Jernej Skrabec" <jernej.skrabec@gmail.com>,
	"Samuel Holland" <samuel@sholland.org>,
	"Maxime Ripard" <mripard@kernel.org>,
	"Richard Genoud" <richard.genoud@bootlin.com>,
	"Boris Brezillon" <bbrezillon@kernel.org>,
	"Masahiro Yamada" <yamada.masahiro@socionext.com>,
	"Brian Norris" <computersforpeace@gmail.com>,
	linux-mtd@lists.infradead.org, linux-sunxi@lists.linux.dev,
	linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v8 17/17] mtd: rawnand: sunxi: support the Allwinner randomized OOB format
Date: Fri, 16 Oct 2026 04:02:32 +0000	[thread overview]
Message-ID: <sashiko-outbox-173724@kernel.org> (raw)
In-Reply-To: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-17-8ba4881fbee8@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] mtd: rawnand: sunxi: Missing bounds check on ecc->steps against max_ecc_steps
--

commit a2ae1cf95bb52a1850e6dc239c873b74d175805e
Author: James Hilliard <james.hilliard1@gmail.com>

    mtd: rawnand: sunxi: support the Allwinner randomized OOB format
    
    Normal hardware-ECC reads also decode protected OOB, including the
    bad-block marker and metadata used in bad-block-table scans. Allwinner
    firmware leaves the marker in the randomizer stream, but the existing
    driver compensates it to keep a plain physical marker. On H6/H616,
    firmware also packs protected user data before the first parity region
    rather than maximizing its allocation across the page. Those mismatches
    prevent normal ECC reads from interpreting firmware-formatted pages and
    their markers.

> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 56594bb411933..0e2ff1c59120f 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c

[ ... ]

> @@ -2342,6 +2353,299 @@ static const struct sunxi_nfc_oob_ops sunxi_nfc_scrambled_plain_bbm_oob_ops = {
>  	.finish_read = sunxi_nfc_oob_finish_read,
>  };
>  
> +/* Allwinner randomized-OOB format, selected only by allwinner,randomized-oob. */
> +#define SUNXI_NFC_H6_ALLWINNER_OOB_MAX_USER_DATA_SZ 16
> +
> +static void sunxi_nfc_randomize_buf(u16 state, u8 *buf, unsigned int len)
> +{
> +	while (len--) {
> +		*buf++ ^= state;
> +		state = sunxi_nfc_randomizer_step(state, 8);
> +	}
> +}
> +
> +static void
> +sunxi_nfc_allwinner_oob_record_status(struct nand_chip *nand,
> +				      struct sunxi_nfc_allwinner_oob_status *result,
> +				      int logical_step, int hw_step,
> +				      struct sunxi_nfc_ecc_snapshot *snapshot)
> +{
> +	u32 count;
> +
> +	if ((snapshot->pattern_found & BIT(hw_step)) &&
> +	    !(snapshot->pattern_id & BIT(hw_step)))
> +		result->zero_steps |= BIT(logical_step);

[Severity: High]
Does this code invoke undefined behavior if logical_step exceeds the bit-width?

The number of ECC steps is derived directly from the NAND page size in
sunxi_nand_hw_ecc_ctrl_init():

	nsectors = mtd->writesize / ecc->size;
	ret = sunxi_nand->oob_ops->init_user_data(nand, nsectors);

It doesn't appear that nsectors is validated against the controller's
max_ecc_steps limit. If a NAND flash with a large page size is used,
ecc->steps (and thus logical_step) can exceed the hardware limit (e.g.,
16 or 32). On 32-bit platforms, this could cause the BIT(logical_step)
shift to overflow.

Additionally, this could lead to out-of-bounds MMIO reads in
sunxi_nfc_hw_ecc_get_prot_oob_bytes() when iterating over ecc->steps,
as reg_index might exceed the supported hardware registers for user data.

[ ... ]

> +static int sunxi_nfc_allwinner_oob_finish_read(struct nand_chip *nand,
> +					       struct sunxi_nfc_ecc_read *read,
> +					       int *cur_off)
> +{
> +	struct sunxi_nfc_allwinner_oob_status *result = &read->allwinner_oob;
> +	u8 *buf = read->buf;
> +	bool oob_required = read->oob_required;
> +	bool dma = read->dma;
> +	int page = read->page;
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	struct nand_ecc_ctrl *ecc = &nand->ecc;
> +	int ret;
> +
> +	/*
> +	 * Allwinner firmware treats an all-zero physical page as bad, even without
> +	 * ECC errors. This takes precedence over the spare-byte heuristic.
> +	 */
> +	if (result->zero_steps == GENMASK(ecc->steps - 1, 0)) {

[Severity: High]
Can GENMASK() invoke undefined behavior here if ecc->steps exceeds the
architecture's bit-width?

Similar to the BIT() shift above, since ecc->steps isn't bounded by
max_ecc_steps, a large page size could cause this range to exceed 32 bits,
leading to an overflow.

> +		memset(buf, 0, mtd->writesize);
> +		memset(nand->oob_poi, 0, mtd->oobsize);
> +		mtd->ecc_stats.failed += ecc->steps;
> +		return 0;
> +	}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com?part=17

WARNING: multiple messages have this Message-ID (diff)
From: sashiko-bot@kernel.org
To: "James Hilliard" <james.hilliard1@gmail.com>,
	"Miquel Raynal" <miquel.raynal@bootlin.com>,
	"Richard Weinberger" <richard@nod.at>,
	"Vignesh Raghavendra" <vigneshr@ti.com>,
	"Sebastian Andrzej Siewior" <bigeasy@linutronix.de>,
	"Clark Williams" <clrkwllms@kernel.org>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Rob Herring" <robh@kernel.org>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>
Cc: "Chen-Yu Tsai" <wens@kernel.org>,
	"Jernej Skrabec" <jernej.skrabec@gmail.com>,
	"Samuel Holland" <samuel@sholland.org>,
	"Maxime Ripard" <mripard@kernel.org>,
	"Richard Genoud" <richard.genoud@bootlin.com>,
	"Boris Brezillon" <bbrezillon@kernel.org>,
	"Masahiro Yamada" <yamada.masahiro@socionext.com>,
	"Brian Norris" <computersforpeace@gmail.com>,
	linux-mtd@lists.infradead.org, linux-sunxi@lists.linux.dev,
	linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v8 17/17] mtd: rawnand: sunxi: support the Allwinner randomized OOB format
Date: Fri, 16 Oct 2026 04:02:32 +0000	[thread overview]
Message-ID: <sashiko-outbox-173724@kernel.org> (raw)
In-Reply-To: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-17-8ba4881fbee8@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] mtd: rawnand: sunxi: Missing bounds check on ecc->steps against max_ecc_steps
--

commit a2ae1cf95bb52a1850e6dc239c873b74d175805e
Author: James Hilliard <james.hilliard1@gmail.com>

    mtd: rawnand: sunxi: support the Allwinner randomized OOB format
    
    Normal hardware-ECC reads also decode protected OOB, including the
    bad-block marker and metadata used in bad-block-table scans. Allwinner
    firmware leaves the marker in the randomizer stream, but the existing
    driver compensates it to keep a plain physical marker. On H6/H616,
    firmware also packs protected user data before the first parity region
    rather than maximizing its allocation across the page. Those mismatches
    prevent normal ECC reads from interpreting firmware-formatted pages and
    their markers.

> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 56594bb411933..0e2ff1c59120f 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c

[ ... ]

> @@ -2342,6 +2353,299 @@ static const struct sunxi_nfc_oob_ops sunxi_nfc_scrambled_plain_bbm_oob_ops = {
>  	.finish_read = sunxi_nfc_oob_finish_read,
>  };
>  
> +/* Allwinner randomized-OOB format, selected only by allwinner,randomized-oob. */
> +#define SUNXI_NFC_H6_ALLWINNER_OOB_MAX_USER_DATA_SZ 16
> +
> +static void sunxi_nfc_randomize_buf(u16 state, u8 *buf, unsigned int len)
> +{
> +	while (len--) {
> +		*buf++ ^= state;
> +		state = sunxi_nfc_randomizer_step(state, 8);
> +	}
> +}
> +
> +static void
> +sunxi_nfc_allwinner_oob_record_status(struct nand_chip *nand,
> +				      struct sunxi_nfc_allwinner_oob_status *result,
> +				      int logical_step, int hw_step,
> +				      struct sunxi_nfc_ecc_snapshot *snapshot)
> +{
> +	u32 count;
> +
> +	if ((snapshot->pattern_found & BIT(hw_step)) &&
> +	    !(snapshot->pattern_id & BIT(hw_step)))
> +		result->zero_steps |= BIT(logical_step);

[Severity: High]
Does this code invoke undefined behavior if logical_step exceeds the bit-width?

The number of ECC steps is derived directly from the NAND page size in
sunxi_nand_hw_ecc_ctrl_init():

	nsectors = mtd->writesize / ecc->size;
	ret = sunxi_nand->oob_ops->init_user_data(nand, nsectors);

It doesn't appear that nsectors is validated against the controller's
max_ecc_steps limit. If a NAND flash with a large page size is used,
ecc->steps (and thus logical_step) can exceed the hardware limit (e.g.,
16 or 32). On 32-bit platforms, this could cause the BIT(logical_step)
shift to overflow.

Additionally, this could lead to out-of-bounds MMIO reads in
sunxi_nfc_hw_ecc_get_prot_oob_bytes() when iterating over ecc->steps,
as reg_index might exceed the supported hardware registers for user data.

[ ... ]

> +static int sunxi_nfc_allwinner_oob_finish_read(struct nand_chip *nand,
> +					       struct sunxi_nfc_ecc_read *read,
> +					       int *cur_off)
> +{
> +	struct sunxi_nfc_allwinner_oob_status *result = &read->allwinner_oob;
> +	u8 *buf = read->buf;
> +	bool oob_required = read->oob_required;
> +	bool dma = read->dma;
> +	int page = read->page;
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	struct nand_ecc_ctrl *ecc = &nand->ecc;
> +	int ret;
> +
> +	/*
> +	 * Allwinner firmware treats an all-zero physical page as bad, even without
> +	 * ECC errors. This takes precedence over the spare-byte heuristic.
> +	 */
> +	if (result->zero_steps == GENMASK(ecc->steps - 1, 0)) {

[Severity: High]
Can GENMASK() invoke undefined behavior here if ecc->steps exceeds the
architecture's bit-width?

Similar to the BIT() shift above, since ecc->steps isn't bounded by
max_ecc_steps, a large page size could cause this range to exceed 32 bits,
leading to an overflow.

> +		memset(buf, 0, mtd->writesize);
> +		memset(nand->oob_poi, 0, mtd->oobsize);
> +		mtd->ecc_stats.failed += ecc->steps;
> +		return 0;
> +	}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com?part=17

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

  reply	other threads:[~2026-10-16  4:02 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-16  3:45 [PATCH v8 00/17] mtd: rawnand: sunxi: fix transfers and support randomized OOB James Hilliard
2026-10-16  3:45 ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 01/17] mtd: rawnand: sunxi: centralize OOB handling James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 02/17] mtd: rawnand: sunxi: use the logical step's OOB length in PIO James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 03/17] mtd: rawnand: sunxi: propagate page-setup and erased-check errors James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 04/17] mtd: rawnand: sunxi: drain interrupts before reusing the completion James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 05/17] mtd: rawnand: sunxi: stop failed program operations and disable ECC James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 06/17] mtd: rawnand: sunxi: select the pattern ID for the current ECC step James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 07/17] mtd: rawnand: sunxi: preserve synthesized zero-pattern data and OOB James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 08/17] mtd: rawnand: sunxi: propagate buffer and column transfer errors James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 09/17] mtd: rawnand: sunxi: avoid a second program confirm for OOB writes James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 10/17] mtd: rawnand: sunxi: use page reads to reposition small-page NAND James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 11/17] mtd: rawnand: sunxi: bound DMA batches by the user-data register bank James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 12/17] mtd: rawnand: sunxi: reuse ECC status within each transfer James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 13/17] mtd: rawnand: sunxi: avoid redundant column changes for extra OOB James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 14/17] mtd: rawnand: sunxi: avoid duplicate chip setup before page commands James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 15/17] mtd: rawnand: sunxi: reduce user-data length register accesses James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 16/17] dt-bindings: mtd: sunxi: Add randomized OOB flag James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  3:45 ` [PATCH v8 17/17] mtd: rawnand: sunxi: support the Allwinner randomized OOB format James Hilliard
2026-10-16  3:45   ` James Hilliard
2026-10-16  4:02   ` sashiko-bot [this message]
2026-10-16  4:02     ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-173724@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bbrezillon@kernel.org \
    --cc=bigeasy@linutronix.de \
    --cc=clrkwllms@kernel.org \
    --cc=computersforpeace@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=james.hilliard1@gmail.com \
    --cc=jernej.skrabec@gmail.com \
    --cc=krzk+dt@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux-rt-devel@lists.linux.dev \
    --cc=linux-sunxi@lists.linux.dev \
    --cc=miquel.raynal@bootlin.com \
    --cc=mripard@kernel.org \
    --cc=richard.genoud@bootlin.com \
    --cc=richard@nod.at \
    --cc=robh@kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=samuel@sholland.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vigneshr@ti.com \
    --cc=wens@kernel.org \
    --cc=yamada.masahiro@socionext.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.