Skip to contentSkip to conversation

FAILED: patch "[PATCH] mtd: spinand: fix NULL pointer dereference with no ECC engine" failed to apply to 6.12-stable tree

PATCH New [email protected] 2 participants 2 messages Oct 5 – Oct 6

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x b890e6163761ddb580cc74f43e15f8bbde15647e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026100520-luminance-trough-b11b@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From b890e6163761ddb580cc74f43e15f8bbde15647e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nuno=20S=C3=A1?= <[email protected]>
Date: Mon, 31 Aug 2026 16:07:17 +0100
Subject: [PATCH] mtd: spinand: fix NULL pointer dereference with no ECC engine
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When "nand-no-ecc-engine" is set in DT, nanddev_get_ecc_engine() takes the NAND_ECC_ENGINE_TYPE_NONE path and returns success while leaving nand->ecc.engine NULL. The SPI-NAND code nevertheless dereferences it unconditionally to test for a pipelined engine, so probing such a device oopses immediately.

Rather than open-coding the test three times, add a nand_ecc_is_pipelined() helper to the NAND core that folds the NULL check into the integration comparison, and use it everywhere. Future callers then cannot reintroduce the problem.

Fixes f9d7c7265bcf ("mtd: spinand: Create direct mapping descriptors for ECC operations")
drivers/mtd/nand/ecc.c +7 -0
index 6ccdff3fc913..1d809cbd47e6 100644
@@ -159,6 +159,13 @@ int nand_ecc_finish_io_req(struct nand_device *nand,
 }
 EXPORT_SYMBOL(nand_ecc_finish_io_req);
 
+bool nand_ecc_is_pipelined(const struct nand_device *nand)
+{
+	return nand->ecc.engine &&
+	       nand->ecc.engine->integration == NAND_ECC_ENGINE_INTEGRATION_PIPELINED;
+}
+EXPORT_SYMBOL(nand_ecc_is_pipelined);
+
 /* Define default OOB placement schemes for large and small page devices */
 static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
drivers/mtd/nand/spi/core.c +3 -5
index bea352dd82d7..4fb769581595 100644
@@ -526,8 +526,7 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
 	else
 		rdesc->info.op_tmpl = &rdesc->info.primary_op_tmpl;
 
-	if (nand->ecc.engine->integration == NAND_ECC_ENGINE_INTEGRATION_PIPELINED &&
-	    req->mode != MTD_OPS_RAW)
+	if (nand_ecc_is_pipelined(nand) && req->mode != MTD_OPS_RAW)
 		rdesc->info.op_tmpl->data.ecc = true;
 	else
 		rdesc->info.op_tmpl->data.ecc = false;
@@ -621,8 +620,7 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
 
 	wdesc = spinand->dirmaps[req->pos.plane].wdesc;
 
-	if (nand->ecc.engine->integration == NAND_ECC_ENGINE_INTEGRATION_PIPELINED &&
-	    req->mode != MTD_OPS_RAW)
+	if (nand_ecc_is_pipelined(nand) && req->mode != MTD_OPS_RAW)
 		wdesc->info.op_tmpl->data.ecc = true;
 	else
 		wdesc->info.op_tmpl->data.ecc = false;
@@ -1279,7 +1277,7 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
 	struct spi_mem_dirmap_desc *desc;
 	bool enable_ecc = false, secondary_op = false;
 
-	if (nand->ecc.engine->integration == NAND_ECC_ENGINE_INTEGRATION_PIPELINED)
+	if (nand_ecc_is_pipelined(nand))
 		enable_ecc = true;
 
 	if (spinand->cont_read_possible && spinand->op_templates->cont_read_cache)
include/linux/mtd/nand.h +2 -0
index 09c8c93e4dba..6936180b6ea5 100644
@@ -305,6 +305,8 @@ int nand_ecc_prepare_io_req(struct nand_device *nand,
 			    struct nand_page_io_req *req);
 int nand_ecc_finish_io_req(struct nand_device *nand,
 			   struct nand_page_io_req *req);
+bool nand_ecc_is_pipelined(const struct nand_device *nand);
+
 bool nand_ecc_is_strong_enough(struct nand_device *nand);
 
 #if IS_REACHABLE(CONFIG_MTD_NAND_CORE)
maintainer
#1 lore raw

PATCH 1/1 mtd: spinand: fix NULL pointer dereference with no ECC engine

From: Nuno Sá <[email protected]>

[ Upstream commit b890e6163761ddb580cc74f43e15f8bbde15647e ]

When "nand-no-ecc-engine" is set in DT, nanddev_get_ecc_engine() takes the NAND_ECC_ENGINE_TYPE_NONE path and returns success while leaving nand->ecc.engine NULL. The SPI-NAND code nevertheless dereferences it unconditionally to test for a pipelined engine, so probing such a device oopses immediately.

Rather than open-coding the test three times, add a nand_ecc_is_pipelined() helper to the NAND core that folds the NULL check into the integration comparison, and use it everywhere. Future callers then cannot reintroduce the problem.

Fixes f9d7c7265bcf ("mtd: spinand: Create direct mapping descriptors for ECC operations")
[ sashal: Replaced the nand_ecc_is_pipelined() helper with an inline NULL guard in spinand_create_dirmap(). ]
---
 drivers/mtd/nand/spi/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/mtd/nand/spi/core.c +2 -1
index a41f2fd47379c..cb10cc573d9ae 100644
@@ -1108,7 +1108,8 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
 
 	spinand->dirmaps[plane].rdesc = desc;
 
-	if (nand->ecc.engine->integration != NAND_ECC_ENGINE_INTEGRATION_PIPELINED) {
+	if (!nand->ecc.engine ||
+	    nand->ecc.engine->integration != NAND_ECC_ENGINE_INTEGRATION_PIPELINED) {
 		spinand->dirmaps[plane].wdesc_ecc = spinand->dirmaps[plane].wdesc;
 		spinand->dirmaps[plane].rdesc_ecc = spinand->dirmaps[plane].rdesc;
 
Signature · 1 line
2.53.0