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
>