diff options
| author | Guixin Liu <kanie@linux.alibaba.com> | 2026-09-14 20:18:43 +0800 |
|---|---|---|
| committer | Dave Jiang <dave.jiang@intel.com> | 2026-09-17 20:05:17 -0700 |
| commit | 0de71a1ab211694be7e88d56fc35c9bf72078ad1 (patch) | |
| tree | 609825da2e71eb2bd627e12df16b4f6a88e33591 | |
| parent | 58b2b1ef28024093063de536c05aaea792226e24 (diff) | |
| download | linux-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.c | 7 |
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); } |
