Linux CXL
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 6.18] cxl/region: Validate partition index before array access
       [not found] <20260831133314.4125787-1-sashal@kernel.org>
@ 2026-08-31 13:25 ` Sasha Levin
  2026-08-31 15:38   ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Sasha Levin @ 2026-08-31 13:25 UTC (permalink / raw)
  To: patches, stable
  Cc: Koba Ko, Alison Schofield, Dave Jiang, Sasha Levin, dave, jic23,
	vishal.l.verma, djbw, linux-cxl, linux-kernel

From: Koba Ko <kobak@nvidia.com>

[ Upstream commit 16329b510f76e5b824e05bf8add8b29850f1f16f ]

construct_region() reads cxled->part and uses it to index
cxlds->part[] without checking for a negative value. If the
partition was never resolved, part remains at its initial value
of -1, causing an out-of-bounds array access.

Add a guard to return -EBUSY when part is negative.

The check was dropped during a merge.

Signed-off-by: Koba Ko <kobak@nvidia.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Link: https://patch.msgid.link/20260414024527.3399590-1-kobak@nvidia.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit Message Forensics

### Step 1.1: Subject Line
**Record:** `[cxl/region] [validate] [partition index before array
access in construct_region()]`

### Step 1.2: Tags
**Record:**
- **Fixes:** — not present (expected for manual review)
- **Reported-by:** — none
- **Tested-by:** — none
- **Reviewed-by:** Alison Schofield `<alison.schofield@intel.com>` (CXL
  maintainer/contributor)
- **Acked-by:** — none
- **Link:**
  https://patch.msgid.link/20260414024527.3399590-1-kobak@nvidia.com
- **Cc: stable@vger.kernel.org:** — absent (not a negative signal)
- **Signed-off-by:** Koba Ko `<kobak@nvidia.com>`, Dave Jiang
  `<dave.jiang@intel.com>` (ignore pipeline-added SOBs)

Notable: maintainer Reviewed-by, no syzbot/user reports.

### Step 1.3: Body Analysis
**Record:**
- **Bug:** `construct_region()` reads `cxled->part` and indexes
  `cxlds->part[part]` without validating `part` is non-negative.
  Unresolved partition leaves `part == -1` (initial value).
- **Symptom:** Out-of-bounds array access on `cxlds->part[-1]`.
- **Root cause:** Guard `if (part < 0) return ERR_PTR(-EBUSY)` was
  accidentally dropped during a merge.
- **Version info:** None explicit in message.

### Step 1.4: Hidden Bug Fix Detection
**Record:** Not disguised — explicit OOB/array-bounds bug fix, though
described as restoring a lost merge guard.

---

## Phase 2: Diff Analysis

### Step 2.1: Inventory
**Record:**
- **Files:** `drivers/cxl/core/region.c` (+3 lines)
- **Function:** `construct_region()`
- **Scope:** Single-file, surgical fix

### Step 2.2: Code Flow Change
**Record:**
- **Before:** `part = READ_ONCE(cxled->part)` then immediately
  `cxlds->part[part].mode` — with `part == -1`, indexes before
  `part[0]`.
- **After:** Early `if (part < 0) return ERR_PTR(-EBUSY)` before array
  access.
- **Path:** Region autodiscovery during endpoint port probe
  (`cxl_add_to_region()` → `construct_region()`).

### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Buffer overflow / out-of-bounds access (negative array
  index).
- **Mechanism:** `cxled->part` initialized to `-1` in
  `drivers/cxl/core/port.c`; if DPA does not map to any partition,
  `hdm.c` warns but continues with `part == -1`. `construct_region()`
  then reads `cxlds->part[-1].mode` from a 2-element array
  (`CXL_NR_PARTITIONS_MAX`).

### Step 2.4: Fix Quality
**Record:**
- Obviously correct — restores guard from `be5cbd0840275`.
- Minimal (3 lines).
- Low regression risk: matches existing pattern in
  `cxl_region_attach()`; `-EBUSY` propagates through opportunistic
  `discover_region()` which already tolerates failures via `dev_dbg()`.

---

## Phase 3: Git History Investigation

### Step 3.1: Blame
**Record:**
- `construct_region()` introduced in `5ec67596e368cd` (2025-02-21, "Drop
  goto pattern of construct_region()").
- Partition indexing `cxlds->part[part].mode` added in `be5cbd0840275`
  (2025-02-03, "Kill enum cxl_decoder_mode") **with** the `part < 0`
  guard.
- Guard lost in merge `b6faa9c613787b` (2025-03-14, merge of
  `for-6.15/guard_cleanups` into `cxl-for-next2`).
- Bug present since that merge; confirmed in this tree at v6.18.44.

### Step 3.2: Fixes: Tag
**Record:** N/A — no Fixes: tag. Root regression is merge
`b6faa9c613787b` dropping guard from `be5cbd0840275`. Both are ancestors
of v6.18.44.

### Step 3.3: Related File History
**Record:**
- Recent `region.c` changes in 6.18: poison injection, SPA/DPA
  translation, lock refactors — unrelated to this guard.
- Standalone fix; not part of a multi-patch series.

### Step 3.4: Author Context
**Record:** Koba Ko has limited CXL history in this tree (2 unrelated
commits). Reviewer Alison Schofield is an active CXL contributor
(region, port, trace fixes).

### Step 3.5: Dependencies
**Record:** No prerequisites. Fix is self-contained. Note: upstream diff
shows `struct cxl_region_context *ctx` signature; this tree uses `struct
cxl_endpoint_decoder *cxled` directly — trivial adaptation, same guard
placement.

---

## Phase 4: Mailing List and External Research

### Step 4.1–4.5
**Record:**
- **b4 dig:** Cannot run `-c <commit>` — commit not present in this
  checkout.
- **Lore/patch.msgid.link:** Blocked by Anubis bot protection; could not
  read thread.
- **UNVERIFIED:** Reviewer stable nomination, NAKs, series revisions.

---

## Phase 5: Code Semantic Analysis

### Step 5.1: Key Functions
**Record:** `construct_region()`, called from `cxl_add_to_region()`.

### Step 5.2: Callers
**Record:**
- `cxl_add_to_region()` ← `discover_region()` in `drivers/cxl/port.c`
- `discover_region()` ← `cxl_endpoint_port_probe()` via
  `device_for_each_child()`
- Runs during CXL endpoint port probe after decoder enumeration

### Step 5.3: Callees
**Record:** `__create_region()`, `__construct_region()`,
`READ_ONCE(cxled->part)`, `cxlds->part[part].mode`.

### Step 5.4: Reachability
**Record:**
- Triggered on CXL hardware probe with `CONFIG_CXL_REGION=y`.
- Reachable when endpoint decoder has HPA range but `part` unresolved
  (`-1`).
- `hdm.c` explicitly allows this: warns `"does not map any partition"`
  and returns success.
- Not a syscall path, but standard driver probe on real hardware.

### Step 5.5: Similar Patterns
**Record:** Existing guards elsewhere in same file:
- `cxl_region_attach()`: `if (cxled->part < 0) return -ENODEV` (line
  1946)
- Poison context: `if (ctx->part < 0) return 0` (line 2758)

The missing guard in `construct_region()` is inconsistent — attach path
is protected, construction path is not.

---

## Phase 6: Cross-Reference Against Local Tree

### Step 6.1: Buggy Code Exists?
**Record:** **YES.** Local tree is **v6.18.44** (`make kernelversion` =
6.18.44). `construct_region()` at lines 3515–3543 lacks `part < 0` check
and uses `cxlds->part[part].mode` with `part` potentially `-1`.

### Step 6.2: Backport Complications
**Record:** Clean apply expected — 3 lines after `part =
READ_ONCE(cxled->part)`. Function signature differs slightly from
upstream patch (uses `cxled` not `ctx`), but guard is identical.

### Step 6.3: Related Fixes Already Present?
**Record:** `cxl_region_attach()` already has `part < 0` check (from
`be5cbd0840275`). The `construct_region()` guard specifically is
**missing** — this fix is still needed.

---

## Phase 7: Subsystem Context

### Step 7.1: Subsystem Criticality
**Record:** `drivers/cxl/` — CXL memory subsystem. **IMPORTANT** for CXL
hardware users; not universal core kernel, but memory-related.

### Step 7.2: Activity
**Record:** Actively developed in 6.18 (poison, region management, lock
refactors).

---

## Phase 8: Impact and Risk Assessment

### Step 8.1: Who Is Affected
**Record:** Users with CXL memory devices and region autodiscovery
enabled (`CONFIG_CXL_REGION`). Systems where endpoint decoder DPA does
not map to a partition.

### Step 8.2: Trigger Conditions
**Record:**
- Endpoint decoder enumerated with `part == -1` (initial value or post-
  invalidate)
- Decoder has valid HPA range and `CXL_DECODER_STATE_AUTO`
- No existing region for that HPA range → `construct_region()` called
- Moderately plausible on misconfigured or partially mapped CXL devices

### Step 8.3: Failure Mode Severity
**Record:** OOB read of `cxlds->part[-1]` — **HIGH** severity (kernel
oops/KASAN report, possible crash; undefined behavior reading memory
before array). Not data corruption in common case, but real crash risk
on probe.

### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** Prevents OOB access on CXL probe path; restores
  intentionally added safety check.
- **Risk:** Very low — 3-line guard, reviewed, matches existing code
  patterns.
- **Ratio:** Strong benefit, minimal risk.

---

## Phase 9: Final Synthesis

### Step 9.1: Evidence Summary

**FOR backport:**
- Real OOB bug with concrete trigger path (unresolved partition index)
- Small, surgical, obviously correct fix
- Restores guard accidentally dropped in merge `b6faa9c613787b`
- Reviewed by CXL maintainer (Alison Schofield)
- Buggy code confirmed present in v6.18.44
- Consistent with existing `part < 0` guards in same file

**AGAINST backport:**
- CXL region is hardware/config-specific (not all users)
- No user/syzbot report in commit message
- Mailing list discussion unverified

**UNRESOLVED:**
- Lore thread content and any explicit stable nomination

### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — restores known-good guard;
   maintainer reviewed
2. Fixes real bug affecting users? **PASS** — OOB on CXL probe with
   unmapped partition
3. Important issue? **PASS** — OOB/crash on driver probe (HIGH)
4. Small and contained? **PASS** — 3 lines, one function
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** — buggy code present; trivial
   adaptation

### Step 9.3: Exception Categories
**Record:** None (standard bug fix, not device ID/quirk/build fix).

### Step 9.4: Decision Rationale

This commit fixes a genuine out-of-bounds array access in
`construct_region()` when an endpoint decoder's partition index remains
at its initial value of `-1`. That state is explicitly allowed by
`hdm.c` (warning only, probe continues). The guard was added in
`be5cbd0840275` and accidentally dropped during merge `b6faa9c613787b`;
the fix simply restores it. For the locally checked-out **6.18.44**
tree, the vulnerable code is present and the patch applies cleanly with
at most a trivial signature adaptation.

---

## Verification

- [Phase 1] Parsed commit message: subject, Reviewed-by, Link tag; no
  Fixes/Reported-by
- [Phase 2] Diff: 3-line guard before `cxlds->part[part]` access in
  `construct_region()`
- [Phase 3] `git describe HEAD`: v6.18.44; `make kernelversion`: 6.18.44
- [Phase 3] `git blame -L 3515,3530`: `construct_region()` from
  `5ec67596e368cd`, partition indexing from `b6faa9c613787b` lineage
- [Phase 3] `git show be5cbd0840275`: added both
  `cxlds->part[part].mode` and `if (part < 0) return ERR_PTR(-EBUSY)`
- [Phase 3] `git show b6faa9c613787b:drivers/cxl/core/region.c`:
  confirmed guard absent after merge
- [Phase 3] `git merge-base --is-ancestor b6faa9c613787b v6.18.44`:
  merge is in this tree
- [Phase 3] `git log -S "if (part < 0)"`: only addition in
  `be5cbd0840275`; no later removal commit (lost in merge conflict
  resolution)
- [Phase 4] `b4 dig -c`: failed — commit not in checkout
- [Phase 4] WebFetch lore/patch.msgid.link: blocked by Anubis —
  **UNVERIFIED** mailing list discussion
- [Phase 5] `grep cxl_add_to_region`: caller chain port.c → region.c
  confirmed
- [Phase 5] `grep cxled->part`: init `-1` in port.c:2076; set `-1` on
  invalidate region.c:2133; unresolved path hdm.c:405-407
- [Phase 5] `CXL_NR_PARTITIONS_MAX = 2` in cxlmem.h — `part[-1]` is OOB
- [Phase 5] Existing guards at region.c:1946 and 2758 confirmed
- [Phase 6] Current `construct_region()` at 3515-3543: no `part < 0`
  check — bug present
- [Phase 6] `cxl_region_attach()` guard present — partial protection
  only, OOB occurs before attach
- [Phase 8] Failure mode: OOB read on probe — HIGH severity for affected
  CXL configs

**YES**

 drivers/cxl/core/region.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 41b64d871c5a1..e09ba89889397 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -3521,6 +3521,9 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
 	int rc, part = READ_ONCE(cxled->part);
 	struct cxl_region *cxlr;
 
+	if (part < 0)
+		return ERR_PTR(-EBUSY);
+
 	do {
 		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
 				       atomic_read(&cxlrd->region_id));
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH AUTOSEL 6.18] cxl/region: Validate partition index before array access
  2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] cxl/region: Validate partition index before array access Sasha Levin
@ 2026-08-31 15:38   ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-08-31 15:38 UTC (permalink / raw)
  To: Sasha Levin; +Cc: linux-cxl

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] Malformed loop condition in `__cxl_dpa_reserve()` causes an infinite loop and out-of-bounds read if a resource does not match any partition.
- [High] `poison_by_decoder()` misses partition index validation, causing an out-of-bounds read if `cxled->part` is -1.
--

commit 31fe17e0b5eabcb1df81ee069bc89ecabb1a8d36
Author: Koba Ko <kobak@nvidia.com>

cxl/region: Validate partition index before array access

construct_region() reads cxled->part and uses it to index
cxlds->part[] without checking for a negative value. If the
partition was never resolved, part remains at its initial value
of -1, causing an out-of-bounds array access.

Link: https://patch.msgid.link/20260414024527.3399590-1-kobak@nvidia.com

> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index 41b64d871c5a1..e09ba89889397 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -3521,6 +3521,9 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
>  	int rc, part = READ_ONCE(cxled->part);
>  	struct cxl_region *cxlr;
>  
> +	if (part < 0)
> +		return ERR_PTR(-EBUSY);
> +
>  	do {
>  		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
>  				       atomic_read(&cxlrd->region_id));

[Severity: High]
This is a pre-existing issue, but does poison_by_decoder() in this same file
also miss this partition index validation? 

If cxled->part is -1, it appears we skip index validation and jump directly
to reading cxlds->part[-1].mode:

drivers/cxl/core/region.c:poison_by_decoder() {
    ...
    mode = cxlds->part[cxled->part].mode;
    ...
}

Could this cause a similar out-of-bounds read during CXL endpoint poison
iteration?

[Severity: High]
This is a pre-existing issue, but does the loop condition in
__cxl_dpa_reserve() evaluate as constantly true?

drivers/cxl/core/hdm.c:__cxl_dpa_reserve() {
    ...
    for (int i = 0; cxlds->nr_partitions; i++)
    ...
}

If a resource does not match any partition, i increments infinitely because
cxlds->nr_partitions is evaluated as a constant boolean rather than an index
bound. Could this cause an infinite loop and out-of-bounds read on cxlds->part
until a page fault halts execution?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831133314.4125787-312-sashal@kernel.org?part=1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-31 15:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] cxl/region: Validate partition index before array access Sasha Levin
2026-08-31 15:38   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox