All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guixin Liu <kanie@linux.alibaba.com>
To: Davidlohr Bueso <dave@stgolabs.net>,
	Jonathan Cameron <jic23@kernel.org>,
	Dave Jiang <dave.jiang@intel.com>,
	Alison Schofield <alison.schofield@intel.com>,
	Vishal Verma <vishal.l.verma@intel.com>,
	Dan Williams <djbw@kernel.org>, Ira Weiny <iweiny@kernel.org>,
	Li Ming <ming.li@zohomail.com>
Cc: linux-cxl@vger.kernel.org
Subject: [PATCH v2] cxl/hdm: Fix out of bounds read of the decoder target list
Date: Wed, 12 Aug 2026 14:10:17 +0800	[thread overview]
Message-ID: <20260812061017.56916-1-kanie@linux.alibaba.com> (raw)

init_hdm_decoder() reads the HDM Decoder Target List register of a switch
or host bridge decoder into an 8 byte on-stack image and copies
cxld->interleave_ways bytes of it into cxld->target_map, with nothing
bounding the count against the 8 target port IDs the register can hold.
cxl_port_setup_targets(), which programs the same field from the region
side, refuses the configuration up front with 'iw > 8 || iw > nr_targets';
the enumeration path has no equivalent gate.

Values above 8 are legal hardware encodings, not corruption.
interleave_ways comes from the 4-bit Interleave Ways field of the decoder
control register through eiw_to_ways(), which returns 16 for eiw 4 and 12
for eiw 10, and the driver accepts whatever firmware left programmed there
before it enumerated the decoder.

The copy loop therefore reads up to 8 bytes past the union, and the stack
residue is stored into target_map as target port IDs. Those IDs are matched
against the port's dports by find_dport() when the decoder's targets are
populated, so a byte that happens to match an unrelated dport's port_id
installs that dport into cxlsd->target[].

Reject the decoder, which is how the eiw_to_ways() and eig_to_granularity()
failures in the same function are already handled. A decoder whose target
list register cannot describe its own interleave is not a configuration a
region can be attached to.

Fixes: d17d0540a0db ("cxl/core/hdm: Add CXL standard decoder enumeration to the core")
Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
---
This was patch 5/8 of the "cxl: Assorted fixes" series [1]. Per review
feedback that series is not being reworked as a whole; the fixes are resent
individually instead. Patches 1, 2 and 7 of the series are dropped, as those
issues are already fixed in cxl/next.

v1->v2:
- rebase onto cxl/next
- rewrite the commit message to describe the behaviour rather than narrate
  the code change (Alison Schofield)

[1] https://lore.kernel.org/linux-cxl/20260811113608.2815625-1-kanie@linux.alibaba.com/

 drivers/cxl/core/hdm.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 0c80b76a5f9b..9d49b48a4456 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -1084,6 +1084,18 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 		cxld->interleave_ways, cxld->interleave_granularity);
 
 	if (!cxled) {
+		/*
+		 * The Target List register only holds
+		 * ARRAY_SIZE(target_list.target_id) entries, so a switch
+		 * decoder cannot interleave across more ports than that.
+		 */
+		if (cxld->interleave_ways > ARRAY_SIZE(target_list.target_id)) {
+			dev_warn(&port->dev,
+				 "decoder%d.%d: Interleave ways: %d exceeds target list size\n",
+				 port->id, cxld->id, cxld->interleave_ways);
+			return -ENXIO;
+		}
+
 		lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
 		hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
 		target_list.value = (hi << 32) + lo;

base-commit: 7098e9cd98a05c0c5de2fae0c2465f9d966fdd07
-- 
2.43.7


             reply	other threads:[~2026-08-12  6:10 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-12  6:10 Guixin Liu [this message]
2026-08-12  6:26 ` [PATCH v2] cxl/hdm: Fix out of bounds read of the decoder target list sashiko-bot
2026-08-12  7:51   ` Guixin Liu
2026-08-12 11:31 ` Li Ming

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260812061017.56916-1-kanie@linux.alibaba.com \
    --to=kanie@linux.alibaba.com \
    --cc=alison.schofield@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=dave@stgolabs.net \
    --cc=djbw@kernel.org \
    --cc=iweiny@kernel.org \
    --cc=jic23@kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=ming.li@zohomail.com \
    --cc=vishal.l.verma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.