[PATCH] cxl/hdm: Robustify decoder target list reads

Davidlohr Bueso <[email protected]> Tue, 28 Jul 2026 16:02:29 -0700
Newsgroups org.kernel.vger.linux-cxl
Message-ID <[email protected]>
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]>
---
 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