Skip to content

Commit 4d5c42a

Browse files
committed
cxl/hdm: Fix DPA reservation vs cxl_endpoint_decoder lifetime
After adding support for emulating platform firmware established DPA reservations, the cxl-topology.sh [1] unit test started crashing with the following signature: general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6bc3: 0000 [Rust-for-Linux#1] PREEMPT SMP [..] RIP: 0010:to_cxl_port+0x8/0x60 [cxl_core] [..] Call Trace: <TASK> __cxl_dpa_release+0x1b/0xd0 [cxl_core] cxl_dpa_release+0x1d/0x30 [cxl_core] release_nodes+0x63/0x90 devres_release_all+0x88/0xc0 ...i.e. a use after free of a 'struct cxl_endpoint_decoder' object. This results from the ordering of init_hdm_decoder() before add_hdm_decoder() where, at release time, the decoder is unregistered and released before the DPA reservation. Fix this by extending the life of the object until all DPA reservations have been released which also preserves platform decoder settings being settled by the time the decoder is published in sysfs (KOBJ_ADD time). Note that the @len == 0 case in __cxl_dpa_reserve() is avoided in practice as this function is only called for committed decoders and new non-zero DPA allocations. Link: https://github.com/pmem/ndctl/blob/pending/test/cxl-topology.sh [1] Fixes: 9c57cde ("cxl/hdm: Enumerate allocated DPA") Cc: Jonathan Cameron <[email protected]> Reviewed-by: Vishal Verma <[email protected]> Link: https://lore.kernel.org/r/165896020625.3546860.12390103413706292760.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent e774830 commit 4d5c42a

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

drivers/cxl/core/hdm.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled)
178178
__release_region(&cxlds->dpa_res, skip_start, cxled->skip);
179179
cxled->skip = 0;
180180
cxled->dpa_res = NULL;
181+
put_device(&cxled->cxld.dev);
181182
port->hdm_end--;
182183
}
183184

@@ -214,7 +215,7 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
214215
lockdep_assert_held_write(&cxl_dpa_rwsem);
215216

216217
if (!len)
217-
return 0;
218+
goto success;
218219

219220
if (cxled->dpa_res) {
220221
dev_dbg(dev, "decoder%d.%d: existing allocation %pr assigned\n",
@@ -266,8 +267,10 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
266267
cxled->cxld.id, cxled->dpa_res);
267268
cxled->mode = CXL_DECODER_MIXED;
268269
}
269-
port->hdm_end++;
270270

271+
success:
272+
port->hdm_end++;
273+
get_device(&cxled->cxld.dev);
271274
return 0;
272275
}
273276

0 commit comments

Comments
 (0)