summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuixin Liu <kanie@linux.alibaba.com>2026-09-14 20:18:43 +0800
committerDave Jiang <dave.jiang@intel.com>2026-09-17 20:05:17 -0700
commit0de71a1ab211694be7e88d56fc35c9bf72078ad1 (patch)
tree609825da2e71eb2bd627e12df16b4f6a88e33591
parent58b2b1ef28024093063de536c05aaea792226e24 (diff)
downloadlinux-next-0de71a1ab211694be7e88d56fc35c9bf72078ad1.tar.gz
linux-next-0de71a1ab211694be7e88d56fc35c9bf72078ad1.zip
cxl/core: Fix dport use-after-free via the einj_inject debugfs file
The per-dport einj_inject debugfs file retains a pointer to the 'struct cxl_dport', but its lifetime is not tied to the dport. Unbinding the dport host frees the dport and leaves einj_inject behind, so writing the file dereferences freed memory. The stale directory also prevents recreation on rebind. Remove the per-dport debugfs directory when the dport host is released. Found by code inspection, then reproduced on a QEMU CXL topology with KASAN (the einj_cxl_is_initialized() guard had to be forced open, as QEMU emits no EINJ table). Unpatched, writing the leftover file after unbind gives a KASAN slab-use-after-free report in cxl_einj_inject(), and rebind hits "already exists in 'cxl'". Patched, the directory goes away with the dport and rebind recreates a working einj_inject. Fixes: 8039804cfa73 ("cxl/core: Add CXL EINJ debugfs files") Signed-off-by: Guixin Liu <kanie@linux.alibaba.com> Reviewed-by: Richard Cheng <icheng@nvidia.com> Reviewed-by: Li Ming <ming.li@zohomail.com> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://patch.msgid.link/20260914121843.718493-1-kanie@linux.alibaba.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
-rw-r--r--drivers/cxl/core/port.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index fea43a92744c..8d715739995b 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -814,6 +814,11 @@ static int cxl_einj_inject(void *data, u64 type)
DEFINE_DEBUGFS_ATTRIBUTE(cxl_einj_inject_fops, NULL, cxl_einj_inject,
"0x%llx\n");
+static void remove_debugfs(void *dentry)
+{
+ debugfs_remove_recursive(dentry);
+}
+
static void cxl_debugfs_create_dport_dir(struct cxl_dport *dport)
{
struct cxl_port *parent = parent_port_of(dport->port);
@@ -832,6 +837,8 @@ static void cxl_debugfs_create_dport_dir(struct cxl_dport *dport)
dir = cxl_debugfs_create_dir(dev_name(dport->dport_dev));
+ devm_add_action_or_reset(dport_to_host(dport), remove_debugfs, dir);
+
debugfs_create_file("einj_inject", 0200, dir, dport,
&cxl_einj_inject_fops);
}