All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 6.6.y] cxl/mem: Fix no cxl_nvd during pmem region auto-assembling
@ 2026-09-29  3:07 Artem Dinaburg
  2026-09-29  3:16 ` sashiko-bot
  2026-09-29 18:50 ` Sasha Levin
  0 siblings, 2 replies; 3+ messages in thread
From: Artem Dinaburg @ 2026-09-29  3:07 UTC (permalink / raw)
  To: stable
  Cc: Artem Dinaburg, Greg Kroah-Hartman, Sasha Levin, Li Ming,
	Dan Williams, Alison Schofield, Jonathan Cameron, Dave Jiang,
	Davidlohr Bueso, Vishal Verma, Ira Weiny, linux-cxl, linux-kernel,
	dan.j.williams, ira.weiny, jonathan.cameron, Li Ming,
	Jonathan Cameron

From: Li Ming <ming4.li@intel.com>

[ Upstream commit 84ec985944ef34a34a1605b93ce401aa8737af96 ]

When CXL subsystem is auto-assembling a pmem region during cxl
endpoint port probing, always hit below calltrace.

 BUG: kernel NULL pointer dereference, address: 0000000000000078
 #PF: supervisor read access in kernel mode
 #PF: error_code(0x0000) - not-present page
 RIP: 0010:cxl_pmem_region_probe+0x22e/0x360 [cxl_pmem]
 Call Trace:
  <TASK>
  ? __die+0x24/0x70
  ? page_fault_oops+0x82/0x160
  ? do_user_addr_fault+0x65/0x6b0
  ? exc_page_fault+0x7d/0x170
  ? asm_exc_page_fault+0x26/0x30
  ? cxl_pmem_region_probe+0x22e/0x360 [cxl_pmem]
  ? cxl_pmem_region_probe+0x1ac/0x360 [cxl_pmem]
  cxl_bus_probe+0x1b/0x60 [cxl_core]
  really_probe+0x173/0x410
  ? __pfx___device_attach_driver+0x10/0x10
  __driver_probe_device+0x80/0x170
  driver_probe_device+0x1e/0x90
  __device_attach_driver+0x90/0x120
  bus_for_each_drv+0x84/0xe0
  __device_attach+0xbc/0x1f0
  bus_probe_device+0x90/0xa0
  device_add+0x51c/0x710
  devm_cxl_add_pmem_region+0x1b5/0x380 [cxl_core]
  cxl_bus_probe+0x1b/0x60 [cxl_core]

The cxl_nvd of the memdev needs to be available during the pmem region
probe. Currently the cxl_nvd is registered after the endpoint port probe.
The endpoint probe, in the case of autoassembly of regions, can cause a
pmem region probe requiring the not yet available cxl_nvd. Adjust the
sequence so this dependency is met.

This requires adding a port parameter to cxl_find_nvdimm_bridge() that
can be used to query the ancestor root port. The endpoint port is not
yet available, but will share a common ancestor with its parent, so
start the query from there instead.

[ Backport to 6.6.y: mapped find_cxl_root() and reference handling to the
  older struct cxl_port and put_device() APIs. The new early error return
  explicitly drops parent_port because 6.6.y lacks the scoped cleanup later
  added by upstream commit dd2617ebd2a6 ("cxl/port: Use __free() to drop
  put_device() for cxl_port"). ]

Fixes: f17b558d6663 ("cxl/pmem: Refactor nvdimm device registration, delete the workqueue")
Co-developed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Li Ming <ming4.li@intel.com>
Tested-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Link: https://patch.msgid.link/20240612064423.2567625-1-ming4.li@intel.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Assisted-by: LLM
Signed-off-by: Artem Dinaburg <artem@trailofbits.com>
---
Hi Greg, Sasha, and cxl maintainers,

I am working through the small CVE backports still missing from 6.6.y.
This one addresses CVE-2024-41085. It registers the nvdimm bridge before
endpoint probing can auto-assemble a pmem region.

The fix is already present in 6.12.y, 6.18.y, and 7.2.y, but not in 6.6.y.
The target-specific adjustment is recorded in the bracketed note above.
The added error-path put_device() matches the cleanup that current mainline
performs automatically through its scoped cxl_port reference.

Could you please queue it for 6.6.y?

CVE: CVE-2024-41085
Upstream: 84ec985944ef34a34a1605b93ce401aa8737af96

AI assistance: An LLM helped identify, adapt, and validate this backport; I
reviewed the resulting code and validation evidence.

Thanks,
Artem Dinaburg

 drivers/cxl/core/pmem.c   | 21 ++++++++++++++-------
 drivers/cxl/core/region.c |  2 +-
 drivers/cxl/cxl.h         |  4 ++--
 drivers/cxl/mem.c         | 18 ++++++++++--------
 4 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
index 317b2fbbef668f..1f87ce9191a74d 100644
--- a/drivers/cxl/core/pmem.c
+++ b/drivers/cxl/core/pmem.c
@@ -62,16 +62,21 @@ static int match_nvdimm_bridge(struct device *dev, void *data)
 	return is_cxl_nvdimm_bridge(dev);
 }
 
-struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd)
+/**
+ * cxl_find_nvdimm_bridge() - find a bridge device relative to a port
+ * @port: any descendant port of an nvdimm-bridge associated
+ *        root-cxl-port
+ */
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_port *port)
 {
-	struct cxl_port *port = find_cxl_root(cxlmd->endpoint);
+	struct cxl_port *root = find_cxl_root(port);
 	struct device *dev;
 
-	if (!port)
+	if (!root)
 		return NULL;
 
-	dev = device_find_child(&port->dev, NULL, match_nvdimm_bridge);
-	put_device(&port->dev);
+	dev = device_find_child(&root->dev, NULL, match_nvdimm_bridge);
+	put_device(&root->dev);
 
 	if (!dev)
 		return NULL;
@@ -244,18 +249,20 @@ static void cxlmd_release_nvdimm(void *_cxlmd)
 
 /**
  * devm_cxl_add_nvdimm() - add a bridge between a cxl_memdev and an nvdimm
+ * @parent_port: parent port for the (to be added) @cxlmd endpoint port
  * @cxlmd: cxl_memdev instance that will perform LIBNVDIMM operations
  *
  * Return: 0 on success negative error code on failure.
  */
-int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd)
+int devm_cxl_add_nvdimm(struct cxl_port *parent_port,
+			struct cxl_memdev *cxlmd)
 {
 	struct cxl_nvdimm_bridge *cxl_nvb;
 	struct cxl_nvdimm *cxl_nvd;
 	struct device *dev;
 	int rc;
 
-	cxl_nvb = cxl_find_nvdimm_bridge(cxlmd);
+	cxl_nvb = cxl_find_nvdimm_bridge(parent_port);
 	if (!cxl_nvb)
 		return -ENODEV;
 
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index af4f8bbe63c448..97e4a4755ab2f8 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2682,7 +2682,7 @@ static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr)
 		 * bridge for one device is the same for all.
 		 */
 		if (i == 0) {
-			cxl_nvb = cxl_find_nvdimm_bridge(cxlmd);
+			cxl_nvb = cxl_find_nvdimm_bridge(cxlmd->endpoint);
 			if (!cxl_nvb) {
 				kfree(cxlr_pmem);
 				cxlr_pmem = ERR_PTR(-ENODEV);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index a7a1b71626de43..59e963e39d31b1 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -795,8 +795,8 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
 struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
 bool is_cxl_nvdimm(struct device *dev);
 bool is_cxl_nvdimm_bridge(struct device *dev);
-int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd);
-struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd);
+int devm_cxl_add_nvdimm(struct cxl_port *parent_port, struct cxl_memdev *cxlmd);
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_port *port);
 
 #ifdef CONFIG_CXL_REGION
 bool is_cxl_pmem_region(struct device *dev);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 317c7548e4e9b4..3400d2f2a5ff92 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -153,6 +153,16 @@ static int cxl_mem_probe(struct device *dev)
 		return -ENXIO;
 	}
 
+	if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) {
+		rc = devm_cxl_add_nvdimm(parent_port, cxlmd);
+		if (rc) {
+			if (rc == -ENODEV)
+				dev_info(dev, "PMEM disabled by platform\n");
+			put_device(&parent_port->dev);
+			return rc;
+		}
+	}
+
 	if (dport->rch)
 		endpoint_parent = parent_port->uport_dev;
 	else
@@ -173,14 +183,6 @@ static int cxl_mem_probe(struct device *dev)
 	if (rc)
 		return rc;
 
-	if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) {
-		rc = devm_cxl_add_nvdimm(cxlmd);
-		if (rc == -ENODEV)
-			dev_info(dev, "PMEM disabled by platform\n");
-		else
-			return rc;
-	}
-
 	/*
 	 * The kernel may be operating out of CXL memory on this device,
 	 * there is no spec defined way to determine whether this device
-- 
2.39.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 6.6.y] cxl/mem: Fix no cxl_nvd during pmem region auto-assembling
  2026-09-29  3:07 [PATCH 6.6.y] cxl/mem: Fix no cxl_nvd during pmem region auto-assembling Artem Dinaburg
@ 2026-09-29  3:16 ` sashiko-bot
  2026-09-29 18:50 ` Sasha Levin
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-09-29  3:16 UTC (permalink / raw)
  To: Artem Dinaburg; +Cc: linux-cxl

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] cxl: fatal probe failure when PMEM is disabled by platform
--

commit 3836a307f91efffcbe3c18ffddeb397cd4ef78b8
Author: Li Ming <ming4.li@intel.com>

cxl/mem: Fix no cxl_nvd during pmem region auto-assembling

When the CXL subsystem is auto-assembling a pmem region during cxl endpoint
port probing, it can hit a null pointer dereference. The cxl_nvd of the
memdev needs to be available during the pmem region probe, so this patch
adjusts the sequence to register the nvdimm bridge earlier.

Link: https://patch.msgid.link/20240612064423.2567625-1-ming4.li@intel.com

> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> index 317c7548e4e9b..3400d2f2a5ff9 100644
> --- a/drivers/cxl/mem.c
> +++ b/drivers/cxl/mem.c
> @@ -153,6 +153,16 @@ static int cxl_mem_probe(struct device *dev)
>  		return -ENXIO;
>  	}
>  
> +	if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) {
> +		rc = devm_cxl_add_nvdimm(parent_port, cxlmd);
> +		if (rc) {
> +			if (rc == -ENODEV)
> +				dev_info(dev, "PMEM disabled by platform\n");
> +			put_device(&parent_port->dev);
> +			return rc;

[Severity: High]
Can returning an error here inadvertently cause a fatal probe failure when
the platform disables PMEM?

If a CXL memory expander has a PMEM region but the platform lacks an NVDIMM
bridge, devm_cxl_add_nvdimm() correctly returns -ENODEV.

The new code catches this and logs "PMEM disabled by platform", but then
it unconditionally returns rc. Returning an error here fails the entire
cxl_mem driver probe, meaning the device is rejected and its endpoint is
never registered.

This renders the device completely unusable, blocking access to both its
persistent and volatile memory. The old code correctly swallowed the -ENODEV
error to allow continued probing.

> +		}
> +	}
> +
>  	if (dport->rch)
>  		endpoint_parent = parent_port->uport_dev;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260929030716.86736-1-artem@trailofbits.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 6.6.y] cxl/mem: Fix no cxl_nvd during pmem region auto-assembling
  2026-09-29  3:07 [PATCH 6.6.y] cxl/mem: Fix no cxl_nvd during pmem region auto-assembling Artem Dinaburg
  2026-09-29  3:16 ` sashiko-bot
@ 2026-09-29 18:50 ` Sasha Levin
  1 sibling, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-09-29 18:50 UTC (permalink / raw)
  To: stable
  Cc: Sasha Levin, Artem Dinaburg, Greg Kroah-Hartman, Li Ming,
	Dan Williams, Alison Schofield, Jonathan Cameron, Dave Jiang,
	Davidlohr Bueso, Vishal Verma, Ira Weiny, linux-cxl, linux-kernel,
	dan.j.williams, ira.weiny, jonathan.cameron, Li Ming,
	Jonathan Cameron

> This one addresses CVE-2024-41085. It registers the nvdimm bridge before
> endpoint probing can auto-assemble a pmem region.

Queued for 6.6, thanks.

-- 
Thanks,
Sasha

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-29 18:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-29  3:07 [PATCH 6.6.y] cxl/mem: Fix no cxl_nvd during pmem region auto-assembling Artem Dinaburg
2026-09-29  3:16 ` sashiko-bot
2026-09-29 18:50 ` Sasha Levin

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.