Re: [PATCH] cxl/hdm: Robustify decoder target list reads
Alison Schofield <[email protected]> Tue, 28 Jul 2026 16:45:37 -0700
| Newsgroups | org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Jul 28, 2026 at 04:02:29PM -0700, Davidlohr Bueso wrote: > Since the target_list union is fixed at 8 entries, if a CXL switch > device has an IW value larger than 8 (such as 12 or 16 way), things > can go bad: > > BUG: KASAN: stack-out-of-bounds in devm_cxl_enumerate_decoders+0xefd/0x1b00 > Read of size 1 at addr ffff8881003bf180 by task kworker/u16:0/12 > kasan_report+0xe0/0x110 > devm_cxl_enumerate_decoders+0xefd/0x1b00 > cxl_port_add_dport+0x9c/0x200 > devm_cxl_enumerate_ports+0xa36/0x1190 > cxl_mem_probe+0x26f/0x710 > > The buggy address belongs to stack of task kworker/u16:0/12 > and is located at offset 40 in frame: > devm_cxl_enumerate_decoders+0x0/0x1b00 > This frame has 1 object: > [32, 40) 'target_list' > > While this is out of spec (see Table 123), we can robustify and > just reject such a decoder - noting that cxl_port_setup_targets() > already refuses to program more than 8 ways. > > Reported-by: Sashiko <[email protected]> > Fixes: d17d0540a0db ("cxl/core/hdm: Add CXL standard decoder enumeration to the core") > Signed-off-by: Davidlohr Bueso <[email protected]> Hi Davidlohr, I think this issue, and its spawn (the endianness issue), are addressed in this in flight patchset. Please take a look: https://lore.kernel.org/linux-cxl/[email protected]/ -- Alison > --- > drivers/cxl/core/hdm.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c > index 0c80b76a5f9b..87bdadeccb5f 100644 > --- a/drivers/cxl/core/hdm.c > +++ b/drivers/cxl/core/hdm.c > @@ -1084,6 +1084,13 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, > cxld->interleave_ways, cxld->interleave_granularity); > > if (!cxled) { > + if (cxld->interleave_ways > ARRAY_SIZE(target_list.target_id)) { > + dev_warn(&port->dev, > + "decoder%d.%d: Invalid target list (iw: %d)\n", > + port->id, cxld->id, cxld->interleave_ways); > + return -EINVAL; > + } > + > lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which)); > hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which)); > target_list.value = (hi << 32) + lo; > -- > 2.39.5 >