[RFC v2 15/15] cxl/mem: Fix NULL pointer deference in memory device paths

From: mhonap

Date: Tue Dec 09 2025 - 11:54:42 EST


From: Manish Honap <mhonap@xxxxxxxxxx>

Add NULL pointer validation in CXL memory device code paths that can
be triggered during error scenarios and device cleanup operations.

Two crash scenarios have been identified during VFIO-CXL testing:

1. __cxlmd_free() can be called with a NULL cxlmd pointer during
error handling paths in device probe/remove sequences. This leads
to a NULL pointer dereference when accessing cxlmd->cxlds.

2. cxl_memdev_has_poison_cmd() can receive a cxlmd where the
conversion to cxl_memdev_state via to_cxl_memdev_state() returns
NULL. This occurs when the device state hasn't been fully
initialized yet, causing a crash when test_bit() attempts to
access mds->poison.enabled_cmds.

Fix by adding defensive NULL checks:
- In __cxlmd_free(), return early if cxlmd is NULL to avoid
dereferencing an invalid pointer
- In cxl_memdev_has_poison_cmd(), validate mds before accessing
the poison.enabled_cmds bitmap

Signed-off-by: Manish Honap <mhonap@xxxxxxxxxx>
---
drivers/cxl/core/memdev.c | 2 +-
drivers/cxl/mem.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index d281843fb2f4..eb694203a259 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -207,7 +207,7 @@ bool cxl_memdev_has_poison_cmd(struct cxl_memdev *cxlmd,
{
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);

- return test_bit(cmd, mds->poison.enabled_cmds);
+ return (mds) ? test_bit(cmd, mds->poison.enabled_cmds) : false;
}

static int cxl_get_poison_by_memdev(struct cxl_memdev *cxlmd)
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index d91d08d25bc4..d5a942ba97b2 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -188,6 +188,9 @@ static int cxl_mem_probe(struct device *dev)

static void __cxlmd_free(struct cxl_memdev *cxlmd)
{
+ if (!cxlmd)
+ return;
+
cxlmd->cxlds->cxlmd = NULL;
put_device(&cxlmd->dev);
kfree(cxlmd);
--
2.25.1