All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Stefan Ghetu" <stefan.ghetu@nxp.com>,
	han.xu@nxp.com, miquel.raynal@bootlin.com
Cc: richard@nod.at, vigneshr@ti.com, s.hauer@pengutronix.de,
	imx@lists.linux.dev, daniel.baluta@nxp.com,
	linux-mtd@lists.infradead.org, Frank.Li@kernel.org
Subject: Re: [PATCH] mtd: rawnand: gpmi: Fix possible NULL pointer dereference in gpmi_nfc_exec_op()
Date: Thu, 05 Nov 2026 10:39:47 +0000	[thread overview]
Message-ID: <sashiko-outbox-198870@kernel.org> (raw)
In-Reply-To: <20261105103410.4424-1-stefan.ghetu@nxp.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] mtd: rawnand: gpmi: lost error and OOB access in gpmi_nfc_exec_op()
--

commit 17db1082d69f752c7e093324fef48f49184391f5
Author: Han Xu <han.xu@nxp.com>

mtd: rawnand: gpmi: Fix possible NULL pointer dereference in gpmi_nfc_exec_op()

This commit moves the NULL check on the DMA descriptor pointer in
gpmi_nfc_exec_op() from inside the instruction loop to after the loop
completes.

> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index 527165ccc839d..333ba468ecaf6 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -2616,11 +2616,11 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
>  						   &direct);
>  			break;
>  		}
> +	}
>  
> -		if (!desc) {
> -			ret = -ENXIO;
> -			goto unmap;
> -		}
> +	if (!desc) {
> +		ret = -ENXIO;
> +		goto unmap;
>  	}

[Severity: Critical]
Does moving the !desc check outside the instruction loop mask failures on
intermediate instructions and allow out-of-bounds accesses on
this->transfers[]?

In gpmi_nfc_exec_op(), each iteration of the for (i = 0; i < op->ninstrs; i++)
loop overwrites desc with the descriptor returned by gpmi_chain_wait_ready(),
gpmi_chain_command(), gpmi_chain_data_write(), or gpmi_chain_data_read().

If an intermediate instruction fails to prepare a DMA descriptor and sets desc
to NULL, the loop no longer aborts. When mxs_dma_prep_slave_sg() in
drivers/dma/mxs-dma.c fails on an intermediate instruction, it sets
mxs_chan->status = DMA_ERROR and returns NULL:

drivers/dma/mxs-dma.c:mxs_dma_prep_slave_sg() {
	...
	if (mxs_chan->status == DMA_IN_PROGRESS)
		idx = mxs_chan->desc_count;

	if (sg_len + idx > NUM_CCW) {
		dev_err(mxs_dma->dma_device.dev,
				"maximum number of sg exceeded: %d > %d\n",
				sg_len, NUM_CCW);
		goto err_out;
	}

	mxs_chan->status = DMA_IN_PROGRESS;
	...
err_out:
	mxs_chan->status = DMA_ERROR;
	return NULL;
}

On the next instruction in the loop, mxs_dma_prep_slave_sg() sees
mxs_chan->status != DMA_IN_PROGRESS, resets idx to 0, overwrites
mxs_chan->ccw[0], and returns a non-NULL descriptor. The post-loop !desc check
then passes and submits a truncated DMA chain to hardware.

In addition, get_next_transfer() checks for array exhaustion using exact
equality after incrementing this->ntransfers:

drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c:get_next_transfer() {
	struct gpmi_transfer *transfer = &this->transfers[this->ntransfers];

	this->ntransfers++;

	if (this->ntransfers == GPMI_MAX_TRANSFERS)
		return NULL;

	return transfer;
}

Previously, returning NULL immediately aborted the loop via goto unmap. If the
loop continues after this->ntransfers reaches GPMI_MAX_TRANSFERS, a subsequent
call to get_next_transfer() indexes past the end of this->transfers[],
increments this->ntransfers past GPMI_MAX_TRANSFERS, and returns the
out-of-bounds pointer, which also causes the unmap cleanup loop to iterate
out of bounds:

	for (i = 0; i < this->ntransfers; i++) {
		struct gpmi_transfer *transfer = &this->transfers[i];

		if (transfer->direction != DMA_NONE)
			dma_unmap_sg(this->dev, &transfer->sgl, 1,
				     transfer->direction);
	}

Also, the continue in the NAND_OP_CMD_INSTR case is guarded by:

	if (i + 1 != op->ninstrs &&
	    op->instrs[i + 1].type == NAND_OP_ADDR_INSTR)
		continue;

so the next iteration is guaranteed to execute the NAND_OP_ADDR_INSTR case and
check desc. Should the !desc check inside the loop be kept (or present in both
places to also handle a zero-length NAND_OP_DATA_IN_INSTR)?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261105103410.4424-1-stefan.ghetu@nxp.com?part=1

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

WARNING: multiple messages have this Message-ID (diff)
From: sashiko-bot@kernel.org
To: "Stefan Ghetu" <stefan.ghetu@nxp.com>,
	han.xu@nxp.com, miquel.raynal@bootlin.com
Cc: richard@nod.at, vigneshr@ti.com, s.hauer@pengutronix.de,
	imx@lists.linux.dev, daniel.baluta@nxp.com,
	linux-mtd@lists.infradead.org, Frank.Li@kernel.org
Subject: Re: [PATCH] mtd: rawnand: gpmi: Fix possible NULL pointer dereference in gpmi_nfc_exec_op()
Date: Thu, 05 Nov 2026 10:39:47 +0000	[thread overview]
Message-ID: <sashiko-outbox-198870@kernel.org> (raw)
In-Reply-To: <20261105103410.4424-1-stefan.ghetu@nxp.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] mtd: rawnand: gpmi: lost error and OOB access in gpmi_nfc_exec_op()
--

commit 17db1082d69f752c7e093324fef48f49184391f5
Author: Han Xu <han.xu@nxp.com>

mtd: rawnand: gpmi: Fix possible NULL pointer dereference in gpmi_nfc_exec_op()

This commit moves the NULL check on the DMA descriptor pointer in
gpmi_nfc_exec_op() from inside the instruction loop to after the loop
completes.

> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index 527165ccc839d..333ba468ecaf6 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -2616,11 +2616,11 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
>  						   &direct);
>  			break;
>  		}
> +	}
>  
> -		if (!desc) {
> -			ret = -ENXIO;
> -			goto unmap;
> -		}
> +	if (!desc) {
> +		ret = -ENXIO;
> +		goto unmap;
>  	}

[Severity: Critical]
Does moving the !desc check outside the instruction loop mask failures on
intermediate instructions and allow out-of-bounds accesses on
this->transfers[]?

In gpmi_nfc_exec_op(), each iteration of the for (i = 0; i < op->ninstrs; i++)
loop overwrites desc with the descriptor returned by gpmi_chain_wait_ready(),
gpmi_chain_command(), gpmi_chain_data_write(), or gpmi_chain_data_read().

If an intermediate instruction fails to prepare a DMA descriptor and sets desc
to NULL, the loop no longer aborts. When mxs_dma_prep_slave_sg() in
drivers/dma/mxs-dma.c fails on an intermediate instruction, it sets
mxs_chan->status = DMA_ERROR and returns NULL:

drivers/dma/mxs-dma.c:mxs_dma_prep_slave_sg() {
	...
	if (mxs_chan->status == DMA_IN_PROGRESS)
		idx = mxs_chan->desc_count;

	if (sg_len + idx > NUM_CCW) {
		dev_err(mxs_dma->dma_device.dev,
				"maximum number of sg exceeded: %d > %d\n",
				sg_len, NUM_CCW);
		goto err_out;
	}

	mxs_chan->status = DMA_IN_PROGRESS;
	...
err_out:
	mxs_chan->status = DMA_ERROR;
	return NULL;
}

On the next instruction in the loop, mxs_dma_prep_slave_sg() sees
mxs_chan->status != DMA_IN_PROGRESS, resets idx to 0, overwrites
mxs_chan->ccw[0], and returns a non-NULL descriptor. The post-loop !desc check
then passes and submits a truncated DMA chain to hardware.

In addition, get_next_transfer() checks for array exhaustion using exact
equality after incrementing this->ntransfers:

drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c:get_next_transfer() {
	struct gpmi_transfer *transfer = &this->transfers[this->ntransfers];

	this->ntransfers++;

	if (this->ntransfers == GPMI_MAX_TRANSFERS)
		return NULL;

	return transfer;
}

Previously, returning NULL immediately aborted the loop via goto unmap. If the
loop continues after this->ntransfers reaches GPMI_MAX_TRANSFERS, a subsequent
call to get_next_transfer() indexes past the end of this->transfers[],
increments this->ntransfers past GPMI_MAX_TRANSFERS, and returns the
out-of-bounds pointer, which also causes the unmap cleanup loop to iterate
out of bounds:

	for (i = 0; i < this->ntransfers; i++) {
		struct gpmi_transfer *transfer = &this->transfers[i];

		if (transfer->direction != DMA_NONE)
			dma_unmap_sg(this->dev, &transfer->sgl, 1,
				     transfer->direction);
	}

Also, the continue in the NAND_OP_CMD_INSTR case is guarded by:

	if (i + 1 != op->ninstrs &&
	    op->instrs[i + 1].type == NAND_OP_ADDR_INSTR)
		continue;

so the next iteration is guaranteed to execute the NAND_OP_ADDR_INSTR case and
check desc. Should the !desc check inside the loop be kept (or present in both
places to also handle a zero-length NAND_OP_DATA_IN_INSTR)?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261105103410.4424-1-stefan.ghetu@nxp.com?part=1

  reply	other threads:[~2026-11-05 10:39 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05 10:34 [PATCH] mtd: rawnand: gpmi: Fix possible NULL pointer dereference in gpmi_nfc_exec_op() Stefan Ghetu
2026-11-05 10:34 ` Stefan Ghetu
2026-11-05 10:39 ` sashiko-bot [this message]
2026-11-05 10:39   ` 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-198870@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=daniel.baluta@nxp.com \
    --cc=han.xu@nxp.com \
    --cc=imx@lists.linux.dev \
    --cc=linux-mtd@lists.infradead.org \
    --cc=miquel.raynal@bootlin.com \
    --cc=richard@nod.at \
    --cc=s.hauer@pengutronix.de \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=stefan.ghetu@nxp.com \
    --cc=vigneshr@ti.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.