* [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup()
@ 2026-10-19 13:44 Sasha Levin
2026-10-19 13:44 ` Sasha Levin
` (516 more replies)
0 siblings, 517 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Daniel Golle, Jakub Kicinski, Sasha Levin, chester.a.unal, andrew,
olteanv, davem, edumazet, pabeni, matthias.bgg,
angelogioacchino.delregno, netdev, linux-kernel, linux-arm-kernel,
linux-mediatek
From: Daniel Golle <daniel@makrotopia.org>
[ Upstream commit 1ae63b018d3d70e96d420b59a1334860cf232bc6 ]
mt7531_setup() reads CORE_PLL_GROUP4 through the MT7531 indirect c45
PHY access, modifies it and writes it back to enable the PHY core
PLL, but checks neither the read nor the write. Now that the indirect
access functions propagate command-write failures, a failed read
returns a negative errno that would be bit-modified and written back
into the PLL register, and a failed write-back would go unnoticed.
Check both and bail out. The adjacent EEE advertisement writes push a
constant value and cannot corrupt state, so they are left as is.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Link: https://patch.msgid.link/a7dfe3b66ea6ac1ae7915034de0527060e6ddcd4.1785811140.git.daniel@makrotopia.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a real, small error-path fix for this 6.12 tree: an unchecked
CORE_PLL_GROUP4 RMW can write a negative errno into the MT7531 PHY PLL.
The buggy code is present here, and a related callee change already
landed.
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
Record: `[net: dsa: mt7530]` `[check]` Check CORE_PLL_GROUP4 read/write
results in `mt7531_setup()`. “check” is used as a missing-return-value
fix, not a feature add.
**Step 1.2 — Tags (from the candidate message)**
Record:
- `Signed-off-by: Daniel Golle <daniel@makrotopia.org>` (author)
- `Link: https://patch.msgid.link/a7dfe3b66ea6ac1ae7915034de0527060e6ddc
d4.1785811140.git.daniel@makrotopia.org`
- `Signed-off-by: Jakub Kicinski <kuba@kernel.org>` (netdev maintainer
applied it)
Ignored per instructions: any pipeline “already selected” markers.
Original mailing-list version (openwall/lkml, same msgid) also had:
- `Fixes: c288575f7810 ("net: dsa: mt7530: Add the support of MT7531
switch")`
- No `Cc: stable`, no `Reported-by`, no `Reviewed-by` on this patch
itself
Cover letter for the series: Andrew Lunn’s `Reviewed-by` was collected
on patches 1–3 and 6, not on this one (it was new in v2).
**Step 1.3 — Body**
Record:
- Bug: `mt7531_setup()` RMW of `CORE_PLL_GROUP4` via
`mt7531_ind_c45_phy_read/write` does not check either result.
- Failure mode: a failed read returns a negative errno that is bit-
modified and written into the PHY core PLL; a failed write is ignored.
- Author’s framing: this became acute once the indirect helpers
propagate command-write failures.
- Adjacent EEE advertisement writes are constant `0`, so they cannot
corrupt RMW state and are left alone.
**Step 1.4 — Hidden bug fix?**
Record: Not hidden. It is an explicit missing-error-check fix. The “now
that …” wording is series context (patch 3/6), not a cleanup-only
change.
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
Record:
- File: `drivers/net/dsa/mt7530.c` only
- Function: `mt7531_setup()`
- ~10 insertions, ~4 deletions (candidate hunk); net +6 lines of checks
- Scope: single-file surgical caller fix
**Step 2.2 — Flow**
Record: Before, `u32 val = mt7531_ind_c45_phy_read(...)` then OR/AND
bits and write back, ignoring errors. After, store the `int` in `ret`,
return if `ret < 0`, copy into `val` only on success, check the write,
return on write failure. Probe/`sw_setup` fails instead of programming
PLL from an errno.
**Step 2.3 — Bug mechanism**
Record: **Logic / error-path correctness**, specifically “treat errno as
register data.”
- `mt7531_ind_c45_phy_read()` returns `int` (PHY data or negative
errno).
- Assigned to `u32 val`, then modified (`MT7531_RG_SYSPLL_DMY2 |
MT7531_PHY_PLL_BYPASS_MODE`, clear `MT7531_PHY_PLL_OFF`).
- Written through `mt7531_ind_c45_phy_write(..., u16 data)`, so a value
such as `(u32)-ETIMEDOUT` (`0xFFFFFF92`) truncates to
`0xFF92`/`0xFFD2` and is programmed into the PHY PLL.
- Write errors (already returned on poll timeout in this tree) are
ignored.
**Step 2.4 — Fix quality**
Record: Obviously correct. `ret` is already declared in
`mt7531_setup()`. No API/locking/data-structure change. Regression risk
is that a failing MDIO access now fails switch setup instead of
continuing with a bogus PLL; that is the intended behavior. Risk of the
fix itself is very low.
## Phase 3: Git history
**Step 3.1 — Blame**
Record:
- Unchecked RMW originates in `c288575f7810` (Landen Chao, 2020-09-14):
“Add the support of MT7531 switch”.
- Helper names/`MT753X_CTRL_PHY_ADDR` from later Arınç ÜNAL refactors
(`868ff5f4944aa9`, `06dfcd4098cfdc`, 2024).
- Poll path in this tree already uses `regmap_read_poll_timeout()` from
`96e0f5184af69` (Daniel Golle, applied 2026-08-09): “error out on
failed reads in MT7531 PHY polling”.
**Step 3.2 — Fixes: target**
Record: `c288575f7810` **is** an ancestor of this tree. The original
MT7531 support (and this RMW) has been here since well before 6.12.
**Step 3.3 — Related file history**
Record:
- `96e0f5184af69` — already in this tree. Makes poll/read failures
return negative errno instead of continuing with garbage “success”
data.
- `93d46870c5440` — already in this tree. Same class: do not treat
`bus->read()` errno as register data.
- This candidate is the missing **caller** check for the one in-driver
RMW of `mt7531_ind_c45_phy_read()`.
**Step 3.4 — Author**
Record: Daniel Golle is a regular MT7530 contributor (PLL/PHY access,
MT7988, MT7531BE). Same author as the already-backported poll-error fix.
**Step 3.5 — Prerequisites**
Record: This is patch **4/6** of “fix remaining swallowed MDIO access
errors”. Patch 3 (`error out on failed PHY_IAC command writes`, upstream
`1c95dcb7e923`) is **not** in this tree. It is not required to compile
or to apply this hunk: the helpers already return `int`, and
`mt7531_ind_c45_phy_read/write` already return negative errno on
`regmap_read_poll_timeout()` failure. Patch 3 only adds extra error
returns from discarded `mt7530_mii_write()` of `MT7531_PHY_IAC`.
Standalone apply: **yes**.
## Phase 4: Mailing list / external
**Step 4.1 — Original discussion**
Record:
- `b4 dig` on the msgid failed (`Cannot find a commit matching …`).
- lore.kernel.org fetches returned 403.
- Fallback: openwall + lkml + cover letter.
- Lore/openwall URL: msgid `a7dfe3b66ea6ac1ae7915034de0527060e6ddcd4.178
5811140.git.daniel@makrotopia.org` (Tue 4 Aug 2026).
- Cover: https://lists.openwall.net/netdev/2026/08/04/90
- This patch was **new in v2**, flagged by Sashiko AI review of v1 as
another swallowed MDIO error.
- Cover letter: “the call site exposed once patch 3 makes the MT7531
indirect c45 access propagate command-write failures.”
- Applied by Jakub Kicinski; patchwork bot lists upstream as
`1ae63b018d3d`.
- No NAK found in the material that could be retrieved.
**Step 4.2 — Recipients**
Record: To/Cc included Andrew Lunn, Vladimir Oltean, netdev maintainers,
MediaTek/DSA people, `netdev@`, `linux-mediatek@`. Appropriate audience.
Andrew reviewed 1–3 and 6; this patch 4 had no `Reviewed-by` in the
submission.
**Step 4.3 — Bug report**
Record: No syzbot/bugzilla. Found by AI review of the MDIO-error series,
not a user crash report.
**Step 4.4 — Series**
Record: v2 6-patch series. Patches 1, 2, 3, 5, 6 are **not** in this
tree. This patch is self-contained at the `mt7531_setup()` call site.
**Step 4.5 — Stable list**
Record: No stable-specific discussion found (lore.kernel.org/stable
search did not return this subject). UNVERIFIED: whether anyone later
nominated it on stable@.
## Phase 5: Code semantic analysis
**Step 5.1 — Functions**
Record: `mt7531_setup()` only. Helpers `mt7531_ind_c45_phy_read/write`
are not modified.
**Step 5.2 — Callers**
Record:
- `mt7531_setup` is `.sw_setup` for `ID_MT7531` only (`mt753x_table`).
- `mt753x_setup()` calls `priv->info->sw_setup(ds)` and aborts on error.
- `mt753x_setup` is `.setup` in `mt7530_switch_ops` → DSA switch setup /
probe.
- MT7988/EN7581 use `mt7988_setup()` → `mt7531_setup_common()`; they do
**not** run this PLL RMW.
**Step 5.3 — Callees**
Record: `mt7531_ind_c45_phy_read/write` lock the MDIO mutex, write
`MT7531_PHY_IAC`, poll `MT7531_PHY_ACS_ST`. On poll/read failure they
`goto out` and return negative `ret`. `mt7530_mii_write()` already
returns `regmap_write` errors, but those returns are still discarded in
this tree (patch 3).
**Step 5.4 — Reachability**
Record: Probe-time only, when an MT7531 DSA switch is instantiated
(`CONFIG_NET_DSA_MT7530`). Not a syscall hot path. Userspace cannot
trigger it except by causing device probe. Trigger is MDIO/regmap
failure or IAC poll timeout during setup.
**Step 5.5 — Similar patterns**
Record: The only in-driver `mt7531_ind_c45_phy_read()` call site is this
PLL RMW. Other `mt7531_ind_c45_phy_write()` uses in the same function
are constant EEE-adv `0`. Phylib also uses these as `.phy_read_c45` /
`.phy_write_c45`.
## Phase 6: Local tree (6.12.111 / `pending-6.12`)
**Step 6.1 — Buggy code present?**
Record: **Yes.** `drivers/net/dsa/mt7530.c` `mt7531_setup()` still does:
```2665:2672:drivers/net/dsa/mt7530.c
val = mt7531_ind_c45_phy_read(priv,
MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MDIO_MMD_VEND2, CORE_PLL_GROUP4);
val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE;
val &= ~MT7531_PHY_PLL_OFF;
mt7531_ind_c45_phy_write(priv,
MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MDIO_MMD_VEND2, CORE_PLL_GROUP4, val);
```
Bug introduced with MT7531 support (`c288575f7810`, v5.10-era). Present
in 6.12.
**Step 6.2 — Backport difficulty**
Record: **Clean apply** aside from line-number offset (2665 here vs 2764
in the candidate diff). Surrounding comments and EEE loop match. `ret`
is already in scope.
**Step 6.3 — Related fixes already here**
Record: `96e0f5184af69` already backported. That change makes failed IAC
polls/reads return errno into this unchecked caller, so this tree
already has the callee half of the fix without the caller half. No
equivalent caller check exists yet.
## Phase 7: Subsystem context
**Step 7.1**
Record: `drivers/net/dsa/mt7530.c` — MediaTek MT7530/MT7531 DSA.
**IMPORTANT** for MediaTek routers/SBCs (MT7621/MT7622/MT7531), not core
mm/vfs. `CONFIG_NET_DSA_MT7530`.
**Step 7.2**
Record: File is actively maintained; recent 6.12 backports already
include two MDIO-error fixes from the same author.
## Phase 8: Impact and risk
**Step 8.1 — Who is affected**
Record: Driver-specific: MT7531 switch users (common on MediaTek ARM
routers). Not MT7988/EN7581 setup (`mt7988_setup`).
**Step 8.2 — Trigger**
Record: MDIO/regmap failure or PHY_IAC poll timeout during `dsa_switch`
setup. Uncommon on healthy hardware. Not an unprivileged syscall
trigger. After `96e0f5184af69`, a failed bus read during poll is a
**negative errno**, not silent garbage success — so this caller bug is
easier to hit than before that backport.
**Step 8.3 — Failure mode**
Record: Hardware misconfiguration: PHY core PLL programmed from a
truncated errno instead of a real `CORE_PLL_GROUP4` value, then setup
continues. Switch can probe “successfully” with PHYs/PLL in a bad state.
Not a KASAN crash. Severity: **HIGH** for that hardware (silent wrong
PLL), not a generic kernel panic. Failing probe is the correct outcome.
**Step 8.4 — Risk/benefit**
Record:
- Benefit: medium-high for MT7531 — closes a hole opened/worsened by the
already-applied poll-error backport; avoids writing errno into PLL.
- Risk: very low (6 lines of `if (ret < 0) return ret`).
- Ratio: favorable.
## Phase 9: Synthesis
**Evidence FOR**
- Real bug: negative errno used as PLL register data, then written back.
- Buggy RMW is in this 6.12 tree; `Fixes:` target `c288575f7810` is
here.
- Companion to `96e0f5184af69`, already in this tree: that commit made
failed reads return errno; this caller still treats the result as PHY
data.
- Small, obviously correct, no new API, applies cleanly.
- Same class as other swallowed-MDIO fixes already accepted here
(`93d46870c5440`, `96e0f5184af69`).
- Author intended it as a bug fix (`Fixes: c288575f7810` on the list).
- Applied to mainline by Jakub Kicinski (`1ae63b018d3d`).
**Evidence AGAINST**
- Error path only; no syzbot/user crash report.
- Driver-specific, probe-time, not a UAF/panic/CVE.
- Series patch 4/6; Andrew Lunn did not `Reviewed-by` this specific
patch.
- Patch 3 (PHY_IAC command-write checks) is not in this tree; the
author’s “now that writes propagate” story is only fully true after
patch 3.
**Unresolved / UNVERIFIED**
- Full lore thread (403); no individual review replies beyond cover
letter and patchwork apply notice.
- Whether patch 3 will be evaluated separately for this tree (not
required for this hunk).
**Stable rules**
1. Obviously correct and tested? **PASS** — trivial return-value checks;
merged to net by Kicinski.
2. Real bug affecting users? **PASS** — MT7531 setup can program PHY PLL
from errno on MDIO/poll failure.
3. Important? **PASS** — hardware PLL corruption and silent “success”
after a failed access; worsened by an already-backported callee fix.
Not a generic oops, but it is serious for this switch.
4. Small and contained? **PASS** — one function, ~6 net lines.
5. No new features/APIs? **PASS**.
6. Can apply to this tree? **PASS**.
**Exception category:** none (not a device ID/quirk/DT/build/docs
exception). It qualifies on ordinary bug-fix rules.
The missing patch 3 does not make this a NO: poll timeout and failed
`regmap_read_poll_timeout()` already return errno here, and those values
are what get written into `CORE_PLL_GROUP4` today.
### What it solves for this tree
On MT7531 probe, a failed indirect C45 read of `CORE_PLL_GROUP4` is
currently folded into the PLL enable RMW and written back. This tree
already backported the helper change that returns those failures as
errno. Without this caller check, 6.12 can program the PHY core PLL from
that errno and keep going. The fix fails setup instead. It is small,
matches local code, and does not need the rest of the series.
Verification:
- [Phase 1] Parsed subject/tags/body; list version has `Fixes:
c288575f7810`; candidate message has Link + Golle/Kicinski SOBs
- [Phase 2] Diff: `mt7531_setup()` only; check read and write; `ret`
already declared
- [Phase 3] `git blame` on 2660–2686: RMW from `c288575f7810`; helpers
renamed later; poll uses `96e0f5184af69`
- [Phase 3] `git merge-base --is-ancestor c288575f7810 HEAD` → yes
- [Phase 3] `git merge-base --is-ancestor 96e0f5184af69 HEAD` → yes
(callee error propagation already here)
- [Phase 3] `git log --grep="PHY_IAC command writes"` → patch 3 **not**
in this tree
- [Phase 3] `git show 96e0f5184af69` confirms
`regmap_read_poll_timeout()` returns negative on failed reads
- [Phase 4] `b4 dig` on msgid failed; lore 403; used openwall/lkml/cover
letter; upstream SHA `1ae63b018d3d`; v2 new patch; Andrew reviewed 1–3
and 6 only
- [Phase 4] UNVERIFIED: full review-reply text; stable@ thread
- [Phase 5] grep: only in-driver `mt7531_ind_c45_phy_read` call is this
RMW; `.sw_setup = mt7531_setup` for `ID_MT7531`; `mt753x_setup()`
returns that error
- [Phase 6] `git describe HEAD` → `p-6.12-4-gbf6fcdf761abd`; `make
kernelversion` → 6.12.111; buggy code at mt7530.c:2665–2672
- [Phase 6] Pre-image matches the candidate hunk; clean apply expected
- [Phase 8] Failure mode: PHY PLL programmed from truncated errno on
probe MDIO failure; severity HIGH for MT7531, trigger uncommon but
real after `96e0f5184af69`
**YES**
drivers/net/dsa/mt7530.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index d2dcc2f1522f4..4f391ef797ea3 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2758,14 +2758,20 @@ mt7531_setup(struct dsa_switch *ds)
* phy_[read,write]_mmd_indirect is called, we provide our own
* mt7531_ind_mmd_phy_[read,write] to complete this function.
*/
- val = mt7531_ind_c45_phy_read(priv,
+ ret = mt7531_ind_c45_phy_read(priv,
MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MDIO_MMD_VEND2, CORE_PLL_GROUP4);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE;
val &= ~MT7531_PHY_PLL_OFF;
- mt7531_ind_c45_phy_write(priv,
- MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
- MDIO_MMD_VEND2, CORE_PLL_GROUP4, val);
+ ret = mt7531_ind_c45_phy_write(priv,
+ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
+ MDIO_MMD_VEND2, CORE_PLL_GROUP4, val);
+ if (ret < 0)
+ return ret;
/* Disable EEE advertisement on the switch PHYs. */
for (i = MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] iommu/rockchip: Clear stale page faults before enabling stall
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
@ 2026-10-19 13:44 ` Sasha Levin
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18] docs: update the unmount propagation rule Sasha Levin
` (515 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Jiaxing Hu, Will Deacon, Sasha Levin, joro, heiko, iommu,
linux-arm-kernel, linux-rockchip, linux-kernel
From: Jiaxing Hu <gahing@gahingwoo.com>
[ Upstream commit b10d5920cafa292ee3cab9c20f813da4fe4f00b8 ]
Boot firmware can leave an IOMMU bank in PAGE_FAULT_ACTIVE before the
driver has configured paging:
PAGE_FAULT_ACTIVE=1 STALL_ACTIVE=0 IDLE=1
Such a bank ignores CMD_ENABLE_STALL and never reaches STALL_ACTIVE, so
rk_iommu_enable_stall()'s readx_poll_timeout() spins until it times out
(seen on the RK3576 NPU, whose MMUs share this poll across banks).
Rather than special-casing these banks in the stall path, acknowledge the
stale fault with CMD_PAGE_FAULT_DONE before enabling stall, so every bank
starts from a clean state and the normal stall sequence applies to all of
them. Banks without a pending fault are untouched.
Signed-off-by: Jiaxing Hu <gahing@gahingwoo.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is mainline **7.3-rc4**. The stall-timeout path is in
this tree, and the 13-line firmware leftover workaround is a real IOMMU
enable failure, not a new API.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[iommu/rockchip] [Clear] [acknowledge leftover
PAGE_FAULT_ACTIVE so stall enable does not poll-timeout]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Jiaxing Hu \<gahing@gahingwoo.com\> (author)
- Signed-off-by: Will Deacon \<will@kernel.org\> (IOMMU maintainer;
applied the patch)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
or Cc: stable (absence of Fixes/Cc:stable is expected for this review)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Boot firmware can leave an IOMMU bank in
`PAGE_FAULT_ACTIVE=1`, `STALL_ACTIVE=0`, `IDLE=1` before the driver
configures paging.
- **Symptom:** That bank ignores `CMD_ENABLE_STALL` and never reaches
`STALL_ACTIVE`. `rk_iommu_enable_stall()`’s `readx_poll_timeout()`
fails. Observed on the RK3576 NPU, whose MMUs share the stall poll
across banks (`rk_iommu_is_stall_active()` ANDs every bank).
- **Root cause:** Stale firmware page-fault state blocks the stall
command.
- **Fix:** Issue `CMD_PAGE_FAULT_DONE` on any bank that still has
`PAGE_FAULT_ACTIVE`, then use the normal stall sequence. Banks without
a pending fault are untouched.
- **Version info in message:** none beyond RK3576 NPU.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. This is an explicit hardware/firmware leftover
workaround that prevents a stall-enable timeout.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/iommu/rockchip-iommu.c` — **+13 / -0**
- Function: `rk_iommu_enable_stall()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** If stall is not already active and paging is enabled,
broadcast `CMD_ENABLE_STALL` and poll until every bank reports
`STALL_ACTIVE` (1 ms timeout, `RK_MMU_POLL_TIMEOUT_US=1000`). One
stuck bank fails the whole poll.
- **After:** Same path, but first walk each bank; if
`RK_MMU_STATUS_PAGE_FAULT_ACTIVE` is set, write
`RK_MMU_CMD_PAGE_FAULT_DONE` to that bank’s command register, then
enable stall as before.
- Path: initialization / attach / resume (`rk_iommu_enable` →
`rk_iommu_enable_stall`), and also disable/suspend (return value
ignored there).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Hardware workaround / logic correctness]** Firmware leaves
`PAGE_FAULT_ACTIVE`. Hardware ignores `CMD_ENABLE_STALL` in that state.
`rk_iommu_enable()` treats stall timeout as fatal (`if (ret) goto
out_disable_clocks`), so the IOMMU never reaches
`rk_iommu_force_reset()` / paging setup and **device attach fails**. The
fix acks the leftover fault with the same command the IRQ handler
already uses (`RK_MMU_CMD_PAGE_FAULT_DONE`).
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Minimal and readable. Gated on `PAGE_FAULT_ACTIVE`, so idle
banks are unchanged. Uses the existing command encoding. Regression risk
is low; the only flagged concern is not also writing `RK_MMU_INT_CLEAR`
(see Phase 4), which is incomplete-ack, not a new deadlock or API
change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- `rk_iommu_enable_stall()` introduced in **c68a292152d32**
(`iommu/rockchip: rk3288 iommu driver`, 2014) — contained in
**v3.19-rc1**.
- Multi-bank `num_mmu` loop: **cd6438c5f8446**, contained in
**v4.6-rc1**.
- `readx_poll_timeout`: **0416bf6479acef**, contained in **v4.17-rc1**.
- The 13-line ack loop is this commit (**b10d5920cafa2**).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Not applicable. Buggy interaction is firmware
leftover vs stall path that has existed for years.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Immediate parent on the file: **841363ebb5082** `iommu/rockchip: Take
all DT clocks` — same author, same RFC series (patch 4/8). Different
problem (extra clocks so DTE_ADDR writes land). **Not a code
dependency** of the stall ack.
- No later commits on this file after b10d5920cafa2 in this tree.
- Standalone IOMMU change; Will applied 4/8 and 5/8 without the rest of
the NPU series.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Jiaxing Hu is not the IOMMU maintainer. In this tree, two
rockchip-iommu commits (clocks + this). Will Deacon applied both.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Diff only needs `rk_iommu_enable_stall`, `num_mmu`,
`RK_MMU_STATUS_PAGE_FAULT_ACTIVE`, `RK_MMU_CMD_PAGE_FAULT_DONE` — all
present long before 7.3. **Can apply standalone.**
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore (via b4):
https://patch.msgid.link/20260718031146.3368811-6-gahing@gahingwoo.com
- Series: **[RFC PATCH v2 0/8] accel/rocket: RK3576 NPU (RKNN)
enablement**
- This patch is **v2 5/8**. v1 had two “skip orphaned-fault banks”
patches; v2 replaced them with this fault-ack after Chaoyi Chen asked
whether clearing the fault avoids skipping banks.
- Will Deacon (2026-07-26): “Applied driver changes to iommu (rockchip)”
for 4/8 and 5/8. No NAK on this patch.
- Cover letter: NPU bring-up is still incomplete (“full inference is not
correct yet”). This IOMMU fix was still taken on its own.
- v3 of the wider series was not out when Will applied this; applied
version is the latest for this hunk.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Recipients included Will Deacon, Joerg Roedel, Robin Murphy,
Heiko Stuebner, iommu@lists.linux.dev, linux-rockchip. No human
Reviewed-by on 5/8 in the thread. Will applied it. Sashiko bot
(automated) commented.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. Author hit it on a Radxa ROCK 4D while
bringing up the RK3576 NPU IOMMUs. Cover letter lists “clearing a stale
firmware page fault” as required for those IOMMUs to come up.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: RFC 8-patch NPU enablement. Only the two IOMMU driver patches
were merged. NPU DT/driver patches are **not** in this tree (no NPU
IOMMU nodes in `rk3576.dtsi`). This stall patch does not depend on them.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned HTTP 403. **UNVERIFIED**
whether stable@ discussed this. No in-tree grep hit except this commit.
Sashiko bot concern (verified from mbox): `CMD_PAGE_FAULT_DONE` without
`RK_MMU_INT_CLEAR` might leave a raw IRQ pending. On `rockchip,disable-
mmu-reset` instances (in-tree: px30, rk3288, rk3368, rk3399, rk356x,
rk3576 vdec), `rk_iommu_force_reset()` is skipped, then
`RK_MMU_INT_MASK` is programmed in `rk_iommu_enable()`. A leftover raw
bit could fire a page-fault IRQ. The existing IRQ handler already logs,
optionally `report_iommu_fault()`, zaps cache, issues `PAGE_FAULT_DONE`,
and clears INT_STATUS. That is a possible spurious IRQ/log, not a
verified panic. No follow-up commit addressed it; Will still applied the
patch.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `rk_iommu_enable_stall()` (modified). Helpers used:
`rk_iommu_read`, `rk_iommu_is_stall_active`,
`rk_iommu_is_paging_enabled`, `rk_iommu_command`.
**Step 5.2: TRACE CALLERS**
Record:
- `rk_iommu_disable()` line 928 — detach / runtime suspend. Return
ignored.
- `rk_iommu_enable()` line 950 — attach / runtime resume. **Failure
aborts enable.**
- `rk_iommu_enable()` called from `rk_iommu_attach_device()` (line 1064)
and `rk_iommu_resume()` (line 1349).
**Step 5.3: TRACE CALLEES**
Record: MMIO status/command. No allocation, no new locks.
`writel(RK_MMU_CMD_PAGE_FAULT_DONE, base + RK_MMU_COMMAND)` matches
`rk_iommu_base_command()`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace/DMA attach or runtime PM resume →
`rk_iommu_attach_device` / `rk_iommu_resume` → `rk_iommu_enable` →
`rk_iommu_enable_stall`. Reachable on Rockchip SoCs with
`CONFIG_ROCKCHIP_IOMMU`. Trigger is firmware leftover + paging already
enabled. Not a syscall fuzz path; it is device bring-up.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: IRQ path already does `RK_MMU_CMD_PAGE_FAULT_DONE` (line 642)
plus `RK_MMU_INT_CLEAR`. No other stall-path fault ack. In-tree RK3576
`vdec_mmu` is two-bank (`reg` two regions), so the AND-poll issue is not
NPU-only in principle.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Local tree: `git describe HEAD` =
**v7.3-rc4-27-gf0100363d8c37**, `make kernelversion` = **7.3.0-rc4**.
`rk_iommu_enable_stall()` is present; this commit is already an ancestor
of HEAD (`git merge-base --is-ancestor b10d5920cafa2 HEAD` succeeded).
Landed via `iommu-updates-v7.3` (not in v7.2). Stall path itself dates
to v3.19.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Hunk is a contiguous insert after the paging-enabled check.
Expected apply: **clean** on trees that have the 2016 multi-bank
`num_mmu` loop (v4.6+). No conflicting later edits on this function in
this checkout.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This is the only “stale page fault” commit. No alternate fix.
Sibling clocks change is independent.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **drivers/iommu/rockchip-iommu.c** — Rockchip IOMMU.
Criticality: **IMPORTANT** (platform IOMMU for multimedia/NPU DMA; not
core mm/VFS, but attach failure takes down the consumer device).
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature driver (2014), still receiving Rockchip bring-up fixes.
Joerg’s v7.3 pull: “Rework Rockchip state handling and fix clock, probe
and stale-fault handling.”
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **driver-specific / platform-specific** —
`CONFIG_ROCKCHIP_IOMMU` on Rockchip. Practical trigger reported on
RK3576 NPU MMUs (those DT nodes are **not** in this tree). Any multi-
bank instance whose firmware leaves `PAGE_FAULT_ACTIVE` can hit the same
poll (e.g. in-tree RK3576 `vdec_mmu` has two banks).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Boot firmware leftover fault, then first stall enable while
paging is still enabled. Timing: probe/attach or resume, not a hot path.
Unprivileged users do not trigger it directly; it is firmware × driver
init. No public reproducer beyond the author’s ROCK 4D bring-up.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **IOMMU enable fails after a 1 ms poll**
(`RK_MMU_POLL_TIMEOUT_US=1000`). Attach returns error; the DMA device
does not get a working IOMMU. **Not** a panic, hang, UAF, or corruption.
Severity: **HIGH** for the affected device (non-functional), **MEDIUM**
system-wide (1 ms timeout + error, rest of the machine continues).
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Hardware/firmware workaround so stall enable succeeds;
IOMMU attach can proceed. High for RK3576 NPU users; modest for other
Rockchip boards unless firmware leaves the same bit.
- **Risk:** 13 lines, status-gated. Theoretical spurious IRQ if
INT_STATUS is not cleared on `disable-mmu-reset` devices. No new
locks/APIs.
- **Ratio:** Benefit outweighs risk. Same class as other hardware
leftover/quirk fixes.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real, explained failure: stall poll times out, `rk_iommu_enable()`
aborts, device attach fails.
- Small (+13), contained, status-gated.
- Same command the IRQ handler already uses.
- Will Deacon applied it independently of the unfinished NPU RFC.
- v7.3 IOMMU pull listed stale-fault handling as a fix.
- Driver and stall path exist in this tree since v3.19 / v4.6.
- Hardware/firmware workaround (stable exception category).
- No new APIs or features.
AGAINST:
- Originated in an RFC series to enable RK3576 NPU; NPU IOMMU DT is
still not in this tree.
- Observed on that NPU, not reported on long-shipped VOP/VDEC.
- Not crash/security/corruption; 1 ms timeout then enable failure.
- Sashiko noted missing `INT_CLEAR`; unaddressed.
- No Fixes:/Cc:stable (not a negative by itself).
UNRESOLVED:
- lore.kernel.org/stable search HTTP 403.
- Whether in-tree vdec/vop firmware also leaves `PAGE_FAULT_ACTIVE`
(author only cited NPU).
- Whether a leftover INT_STATUS after `PAGE_FAULT_DONE` actually fires
on `disable-mmu-reset` hardware.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — logic matches the described
hardware state; author tested on ROCK 4D; IOMMU maintainer applied
it.
2. Fixes a real bug that affects users? **PASS** — stall timeout
prevents IOMMU enable/attach.
3. Important issue? **PASS** — device IOMMU never comes up (not a panic,
but hardware non-functional). Severity HIGH for that device.
4. Small and contained? **PASS** — 13 lines, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — stall path and symbols are
here; hunk is a clean insert.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk/workaround** — firmware leftover
`PAGE_FAULT_ACTIVE` so stall commands work. Not a new driver, not a new
userspace API.
**Step 9.4: MAKE YOUR DECISION**
This tree is 7.3-rc4; the stall path is old and the bug is a firmware
leftover vs that path, not a 7.3-only feature. The patch is a small,
maintainer-acked workaround that stops IOMMU attach from failing. Origin
in an unfinished NPU RFC does not make it a new API; Will merged it as a
standalone IOMMU fix. Missing `INT_CLEAR` is a residual IRQ-ack concern,
not a reason to drop a stall-timeout fix that already uses the
documented fault-done command.
Verification:
- [Phase 1] Parsed tags: only author SOB + Will Deacon SOB; no
Fixes/Reported-by/Cc:stable
- [Phase 1] Body: PAGE_FAULT_ACTIVE leftover → ENABLE_STALL ignored →
poll timeout on RK3576 NPU multi-bank poll
- [Phase 2] Diff: +13 in `rk_iommu_enable_stall()`; loop acks
`PAGE_FAULT_ACTIVE` with `CMD_PAGE_FAULT_DONE`
- [Phase 2] `rk_iommu_enable()` returns on stall timeout before
`force_reset` (line 950-952) — attach fails
- [Phase 3] git blame: function from c68a292152d32 (v3.19); poll from
0416bf6479acef (v4.17); multi-mmu cd6438c5f8446 (v4.6)
- [Phase 3] git merge-base --is-ancestor b10d5920cafa2 HEAD: yes; not in
v7.2; in v7.3-rc1
- [Phase 3] Sibling 841363ebb5082 is clocks-only; not required for this
hunk
- [Phase 4] b4 dig -c b10d5920cafa2:
https://patch.msgid.link/20260718031146.3368811-6-gahing@gahingwoo.com
- [Phase 4] b4 dig -a: RFC v1 (skip banks) → v2 (this ack); Will applied
v2 4/8 and 5/8
- [Phase 4] b4 dig -w: iommu maintainers + rockchip list on CC
- [Phase 4] mbox: Will “Applied driver changes to iommu (rockchip)”;
Sashiko INT_CLEAR warning; no human NAK
- [Phase 4] lore.kernel.org WebFetch/curl: HTTP 403 — stable-list
discussion UNVERIFIED
- [Phase 5] Callers: disable (unchecked) and enable (fatal); enable from
attach_device and resume
- [Phase 5] IRQ handler already issues PAGE_FAULT_DONE at line 642
- [Phase 6] git describe HEAD: v7.3-rc4-27-gf0100363d8c37; Makefile
7.3.0-rc4; file present
- [Phase 6] No NPU IOMMU nodes in
arch/arm64/boot/dts/rockchip/rk3576.dtsi; vdec_mmu is two-bank +
disable-mmu-reset
- [Phase 7] iommu-updates-v7.3 merge text: “fix clock, probe and stale-
fault handling”
- [Phase 8] Failure: 1 ms poll then IOMMU enable/attach failure; not
oops/UAF
- UNVERIFIED: whether firmware leaves this bit on in-tree vdec/vop;
whether INT_STATUS spurious IRQ reproduces; stable@ thread
The fix is small, surgical, and meets the stable criteria as a hardware
leftover workaround in a long-lived driver.
**YES**
drivers/iommu/rockchip-iommu.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 309ba78e27d4f..982ea9cafee1b 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -422,6 +422,19 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
if (!rk_iommu_is_paging_enabled(iommu))
return 0;
+ /*
+ * Boot firmware can leave a bank in PAGE_FAULT_ACTIVE with no handler
+ * (PAGE_FAULT_ACTIVE & !STALL_ACTIVE & IDLE). Such a bank ignores
+ * CMD_ENABLE_STALL and never reaches STALL_ACTIVE, timing out the poll
+ * below. Acknowledge any stale fault first so every bank starts clean.
+ */
+ for (i = 0; i < iommu->num_mmu; i++) {
+ if (rk_iommu_read(iommu->bases[i], RK_MMU_STATUS) &
+ RK_MMU_STATUS_PAGE_FAULT_ACTIVE)
+ writel(RK_MMU_CMD_PAGE_FAULT_DONE,
+ iommu->bases[i] + RK_MMU_COMMAND);
+ }
+
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] iommu/rockchip: Clear stale page faults before enabling stall
@ 2026-10-19 13:44 ` Sasha Levin
0 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Jiaxing Hu, Will Deacon, Sasha Levin, joro, heiko, iommu,
linux-arm-kernel, linux-rockchip, linux-kernel
From: Jiaxing Hu <gahing@gahingwoo.com>
[ Upstream commit b10d5920cafa292ee3cab9c20f813da4fe4f00b8 ]
Boot firmware can leave an IOMMU bank in PAGE_FAULT_ACTIVE before the
driver has configured paging:
PAGE_FAULT_ACTIVE=1 STALL_ACTIVE=0 IDLE=1
Such a bank ignores CMD_ENABLE_STALL and never reaches STALL_ACTIVE, so
rk_iommu_enable_stall()'s readx_poll_timeout() spins until it times out
(seen on the RK3576 NPU, whose MMUs share this poll across banks).
Rather than special-casing these banks in the stall path, acknowledge the
stale fault with CMD_PAGE_FAULT_DONE before enabling stall, so every bank
starts from a clean state and the normal stall sequence applies to all of
them. Banks without a pending fault are untouched.
Signed-off-by: Jiaxing Hu <gahing@gahingwoo.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is mainline **7.3-rc4**. The stall-timeout path is in
this tree, and the 13-line firmware leftover workaround is a real IOMMU
enable failure, not a new API.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[iommu/rockchip] [Clear] [acknowledge leftover
PAGE_FAULT_ACTIVE so stall enable does not poll-timeout]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Jiaxing Hu \<gahing@gahingwoo.com\> (author)
- Signed-off-by: Will Deacon \<will@kernel.org\> (IOMMU maintainer;
applied the patch)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
or Cc: stable (absence of Fixes/Cc:stable is expected for this review)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Boot firmware can leave an IOMMU bank in
`PAGE_FAULT_ACTIVE=1`, `STALL_ACTIVE=0`, `IDLE=1` before the driver
configures paging.
- **Symptom:** That bank ignores `CMD_ENABLE_STALL` and never reaches
`STALL_ACTIVE`. `rk_iommu_enable_stall()`’s `readx_poll_timeout()`
fails. Observed on the RK3576 NPU, whose MMUs share the stall poll
across banks (`rk_iommu_is_stall_active()` ANDs every bank).
- **Root cause:** Stale firmware page-fault state blocks the stall
command.
- **Fix:** Issue `CMD_PAGE_FAULT_DONE` on any bank that still has
`PAGE_FAULT_ACTIVE`, then use the normal stall sequence. Banks without
a pending fault are untouched.
- **Version info in message:** none beyond RK3576 NPU.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. This is an explicit hardware/firmware leftover
workaround that prevents a stall-enable timeout.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/iommu/rockchip-iommu.c` — **+13 / -0**
- Function: `rk_iommu_enable_stall()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** If stall is not already active and paging is enabled,
broadcast `CMD_ENABLE_STALL` and poll until every bank reports
`STALL_ACTIVE` (1 ms timeout, `RK_MMU_POLL_TIMEOUT_US=1000`). One
stuck bank fails the whole poll.
- **After:** Same path, but first walk each bank; if
`RK_MMU_STATUS_PAGE_FAULT_ACTIVE` is set, write
`RK_MMU_CMD_PAGE_FAULT_DONE` to that bank’s command register, then
enable stall as before.
- Path: initialization / attach / resume (`rk_iommu_enable` →
`rk_iommu_enable_stall`), and also disable/suspend (return value
ignored there).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Hardware workaround / logic correctness]** Firmware leaves
`PAGE_FAULT_ACTIVE`. Hardware ignores `CMD_ENABLE_STALL` in that state.
`rk_iommu_enable()` treats stall timeout as fatal (`if (ret) goto
out_disable_clocks`), so the IOMMU never reaches
`rk_iommu_force_reset()` / paging setup and **device attach fails**. The
fix acks the leftover fault with the same command the IRQ handler
already uses (`RK_MMU_CMD_PAGE_FAULT_DONE`).
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Minimal and readable. Gated on `PAGE_FAULT_ACTIVE`, so idle
banks are unchanged. Uses the existing command encoding. Regression risk
is low; the only flagged concern is not also writing `RK_MMU_INT_CLEAR`
(see Phase 4), which is incomplete-ack, not a new deadlock or API
change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- `rk_iommu_enable_stall()` introduced in **c68a292152d32**
(`iommu/rockchip: rk3288 iommu driver`, 2014) — contained in
**v3.19-rc1**.
- Multi-bank `num_mmu` loop: **cd6438c5f8446**, contained in
**v4.6-rc1**.
- `readx_poll_timeout`: **0416bf6479acef**, contained in **v4.17-rc1**.
- The 13-line ack loop is this commit (**b10d5920cafa2**).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Not applicable. Buggy interaction is firmware
leftover vs stall path that has existed for years.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Immediate parent on the file: **841363ebb5082** `iommu/rockchip: Take
all DT clocks` — same author, same RFC series (patch 4/8). Different
problem (extra clocks so DTE_ADDR writes land). **Not a code
dependency** of the stall ack.
- No later commits on this file after b10d5920cafa2 in this tree.
- Standalone IOMMU change; Will applied 4/8 and 5/8 without the rest of
the NPU series.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Jiaxing Hu is not the IOMMU maintainer. In this tree, two
rockchip-iommu commits (clocks + this). Will Deacon applied both.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Diff only needs `rk_iommu_enable_stall`, `num_mmu`,
`RK_MMU_STATUS_PAGE_FAULT_ACTIVE`, `RK_MMU_CMD_PAGE_FAULT_DONE` — all
present long before 7.3. **Can apply standalone.**
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore (via b4):
https://patch.msgid.link/20260718031146.3368811-6-gahing@gahingwoo.com
- Series: **[RFC PATCH v2 0/8] accel/rocket: RK3576 NPU (RKNN)
enablement**
- This patch is **v2 5/8**. v1 had two “skip orphaned-fault banks”
patches; v2 replaced them with this fault-ack after Chaoyi Chen asked
whether clearing the fault avoids skipping banks.
- Will Deacon (2026-07-26): “Applied driver changes to iommu (rockchip)”
for 4/8 and 5/8. No NAK on this patch.
- Cover letter: NPU bring-up is still incomplete (“full inference is not
correct yet”). This IOMMU fix was still taken on its own.
- v3 of the wider series was not out when Will applied this; applied
version is the latest for this hunk.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Recipients included Will Deacon, Joerg Roedel, Robin Murphy,
Heiko Stuebner, iommu@lists.linux.dev, linux-rockchip. No human
Reviewed-by on 5/8 in the thread. Will applied it. Sashiko bot
(automated) commented.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. Author hit it on a Radxa ROCK 4D while
bringing up the RK3576 NPU IOMMUs. Cover letter lists “clearing a stale
firmware page fault” as required for those IOMMUs to come up.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: RFC 8-patch NPU enablement. Only the two IOMMU driver patches
were merged. NPU DT/driver patches are **not** in this tree (no NPU
IOMMU nodes in `rk3576.dtsi`). This stall patch does not depend on them.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned HTTP 403. **UNVERIFIED**
whether stable@ discussed this. No in-tree grep hit except this commit.
Sashiko bot concern (verified from mbox): `CMD_PAGE_FAULT_DONE` without
`RK_MMU_INT_CLEAR` might leave a raw IRQ pending. On `rockchip,disable-
mmu-reset` instances (in-tree: px30, rk3288, rk3368, rk3399, rk356x,
rk3576 vdec), `rk_iommu_force_reset()` is skipped, then
`RK_MMU_INT_MASK` is programmed in `rk_iommu_enable()`. A leftover raw
bit could fire a page-fault IRQ. The existing IRQ handler already logs,
optionally `report_iommu_fault()`, zaps cache, issues `PAGE_FAULT_DONE`,
and clears INT_STATUS. That is a possible spurious IRQ/log, not a
verified panic. No follow-up commit addressed it; Will still applied the
patch.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `rk_iommu_enable_stall()` (modified). Helpers used:
`rk_iommu_read`, `rk_iommu_is_stall_active`,
`rk_iommu_is_paging_enabled`, `rk_iommu_command`.
**Step 5.2: TRACE CALLERS**
Record:
- `rk_iommu_disable()` line 928 — detach / runtime suspend. Return
ignored.
- `rk_iommu_enable()` line 950 — attach / runtime resume. **Failure
aborts enable.**
- `rk_iommu_enable()` called from `rk_iommu_attach_device()` (line 1064)
and `rk_iommu_resume()` (line 1349).
**Step 5.3: TRACE CALLEES**
Record: MMIO status/command. No allocation, no new locks.
`writel(RK_MMU_CMD_PAGE_FAULT_DONE, base + RK_MMU_COMMAND)` matches
`rk_iommu_base_command()`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace/DMA attach or runtime PM resume →
`rk_iommu_attach_device` / `rk_iommu_resume` → `rk_iommu_enable` →
`rk_iommu_enable_stall`. Reachable on Rockchip SoCs with
`CONFIG_ROCKCHIP_IOMMU`. Trigger is firmware leftover + paging already
enabled. Not a syscall fuzz path; it is device bring-up.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: IRQ path already does `RK_MMU_CMD_PAGE_FAULT_DONE` (line 642)
plus `RK_MMU_INT_CLEAR`. No other stall-path fault ack. In-tree RK3576
`vdec_mmu` is two-bank (`reg` two regions), so the AND-poll issue is not
NPU-only in principle.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Local tree: `git describe HEAD` =
**v7.3-rc4-27-gf0100363d8c37**, `make kernelversion` = **7.3.0-rc4**.
`rk_iommu_enable_stall()` is present; this commit is already an ancestor
of HEAD (`git merge-base --is-ancestor b10d5920cafa2 HEAD` succeeded).
Landed via `iommu-updates-v7.3` (not in v7.2). Stall path itself dates
to v3.19.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Hunk is a contiguous insert after the paging-enabled check.
Expected apply: **clean** on trees that have the 2016 multi-bank
`num_mmu` loop (v4.6+). No conflicting later edits on this function in
this checkout.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This is the only “stale page fault” commit. No alternate fix.
Sibling clocks change is independent.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **drivers/iommu/rockchip-iommu.c** — Rockchip IOMMU.
Criticality: **IMPORTANT** (platform IOMMU for multimedia/NPU DMA; not
core mm/VFS, but attach failure takes down the consumer device).
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature driver (2014), still receiving Rockchip bring-up fixes.
Joerg’s v7.3 pull: “Rework Rockchip state handling and fix clock, probe
and stale-fault handling.”
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **driver-specific / platform-specific** —
`CONFIG_ROCKCHIP_IOMMU` on Rockchip. Practical trigger reported on
RK3576 NPU MMUs (those DT nodes are **not** in this tree). Any multi-
bank instance whose firmware leaves `PAGE_FAULT_ACTIVE` can hit the same
poll (e.g. in-tree RK3576 `vdec_mmu` has two banks).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Boot firmware leftover fault, then first stall enable while
paging is still enabled. Timing: probe/attach or resume, not a hot path.
Unprivileged users do not trigger it directly; it is firmware × driver
init. No public reproducer beyond the author’s ROCK 4D bring-up.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **IOMMU enable fails after a 1 ms poll**
(`RK_MMU_POLL_TIMEOUT_US=1000`). Attach returns error; the DMA device
does not get a working IOMMU. **Not** a panic, hang, UAF, or corruption.
Severity: **HIGH** for the affected device (non-functional), **MEDIUM**
system-wide (1 ms timeout + error, rest of the machine continues).
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Hardware/firmware workaround so stall enable succeeds;
IOMMU attach can proceed. High for RK3576 NPU users; modest for other
Rockchip boards unless firmware leaves the same bit.
- **Risk:** 13 lines, status-gated. Theoretical spurious IRQ if
INT_STATUS is not cleared on `disable-mmu-reset` devices. No new
locks/APIs.
- **Ratio:** Benefit outweighs risk. Same class as other hardware
leftover/quirk fixes.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real, explained failure: stall poll times out, `rk_iommu_enable()`
aborts, device attach fails.
- Small (+13), contained, status-gated.
- Same command the IRQ handler already uses.
- Will Deacon applied it independently of the unfinished NPU RFC.
- v7.3 IOMMU pull listed stale-fault handling as a fix.
- Driver and stall path exist in this tree since v3.19 / v4.6.
- Hardware/firmware workaround (stable exception category).
- No new APIs or features.
AGAINST:
- Originated in an RFC series to enable RK3576 NPU; NPU IOMMU DT is
still not in this tree.
- Observed on that NPU, not reported on long-shipped VOP/VDEC.
- Not crash/security/corruption; 1 ms timeout then enable failure.
- Sashiko noted missing `INT_CLEAR`; unaddressed.
- No Fixes:/Cc:stable (not a negative by itself).
UNRESOLVED:
- lore.kernel.org/stable search HTTP 403.
- Whether in-tree vdec/vop firmware also leaves `PAGE_FAULT_ACTIVE`
(author only cited NPU).
- Whether a leftover INT_STATUS after `PAGE_FAULT_DONE` actually fires
on `disable-mmu-reset` hardware.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — logic matches the described
hardware state; author tested on ROCK 4D; IOMMU maintainer applied
it.
2. Fixes a real bug that affects users? **PASS** — stall timeout
prevents IOMMU enable/attach.
3. Important issue? **PASS** — device IOMMU never comes up (not a panic,
but hardware non-functional). Severity HIGH for that device.
4. Small and contained? **PASS** — 13 lines, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — stall path and symbols are
here; hunk is a clean insert.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk/workaround** — firmware leftover
`PAGE_FAULT_ACTIVE` so stall commands work. Not a new driver, not a new
userspace API.
**Step 9.4: MAKE YOUR DECISION**
This tree is 7.3-rc4; the stall path is old and the bug is a firmware
leftover vs that path, not a 7.3-only feature. The patch is a small,
maintainer-acked workaround that stops IOMMU attach from failing. Origin
in an unfinished NPU RFC does not make it a new API; Will merged it as a
standalone IOMMU fix. Missing `INT_CLEAR` is a residual IRQ-ack concern,
not a reason to drop a stall-timeout fix that already uses the
documented fault-done command.
Verification:
- [Phase 1] Parsed tags: only author SOB + Will Deacon SOB; no
Fixes/Reported-by/Cc:stable
- [Phase 1] Body: PAGE_FAULT_ACTIVE leftover → ENABLE_STALL ignored →
poll timeout on RK3576 NPU multi-bank poll
- [Phase 2] Diff: +13 in `rk_iommu_enable_stall()`; loop acks
`PAGE_FAULT_ACTIVE` with `CMD_PAGE_FAULT_DONE`
- [Phase 2] `rk_iommu_enable()` returns on stall timeout before
`force_reset` (line 950-952) — attach fails
- [Phase 3] git blame: function from c68a292152d32 (v3.19); poll from
0416bf6479acef (v4.17); multi-mmu cd6438c5f8446 (v4.6)
- [Phase 3] git merge-base --is-ancestor b10d5920cafa2 HEAD: yes; not in
v7.2; in v7.3-rc1
- [Phase 3] Sibling 841363ebb5082 is clocks-only; not required for this
hunk
- [Phase 4] b4 dig -c b10d5920cafa2:
https://patch.msgid.link/20260718031146.3368811-6-gahing@gahingwoo.com
- [Phase 4] b4 dig -a: RFC v1 (skip banks) → v2 (this ack); Will applied
v2 4/8 and 5/8
- [Phase 4] b4 dig -w: iommu maintainers + rockchip list on CC
- [Phase 4] mbox: Will “Applied driver changes to iommu (rockchip)”;
Sashiko INT_CLEAR warning; no human NAK
- [Phase 4] lore.kernel.org WebFetch/curl: HTTP 403 — stable-list
discussion UNVERIFIED
- [Phase 5] Callers: disable (unchecked) and enable (fatal); enable from
attach_device and resume
- [Phase 5] IRQ handler already issues PAGE_FAULT_DONE at line 642
- [Phase 6] git describe HEAD: v7.3-rc4-27-gf0100363d8c37; Makefile
7.3.0-rc4; file present
- [Phase 6] No NPU IOMMU nodes in
arch/arm64/boot/dts/rockchip/rk3576.dtsi; vdec_mmu is two-bank +
disable-mmu-reset
- [Phase 7] iommu-updates-v7.3 merge text: “fix clock, probe and stale-
fault handling”
- [Phase 8] Failure: 1 ms poll then IOMMU enable/attach failure; not
oops/UAF
- UNVERIFIED: whether firmware leaves this bit on in-tree vdec/vop;
whether INT_STATUS spurious IRQ reproduces; stable@ thread
The fix is small, surgical, and meets the stable criteria as a hardware
leftover workaround in a long-lived driver.
**YES**
drivers/iommu/rockchip-iommu.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 309ba78e27d4f..982ea9cafee1b 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -422,6 +422,19 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
if (!rk_iommu_is_paging_enabled(iommu))
return 0;
+ /*
+ * Boot firmware can leave a bank in PAGE_FAULT_ACTIVE with no handler
+ * (PAGE_FAULT_ACTIVE & !STALL_ACTIVE & IDLE). Such a bank ignores
+ * CMD_ENABLE_STALL and never reaches STALL_ACTIVE, timing out the poll
+ * below. Acknowledge any stale fault first so every bank starts clean.
+ */
+ for (i = 0; i < iommu->num_mmu; i++) {
+ if (rk_iommu_read(iommu->bases[i], RK_MMU_STATUS) &
+ RK_MMU_STATUS_PAGE_FAULT_ACTIVE)
+ writel(RK_MMU_CMD_PAGE_FAULT_DONE,
+ iommu->bases[i] + RK_MMU_COMMAND);
+ }
+
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
--
2.53.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] docs: update the unmount propagation rule
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
2026-10-19 13:44 ` Sasha Levin
@ 2026-10-19 13:44 ` Sasha Levin
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-5.10] mmc: cqhci: fix to missed endian conversions Sasha Levin
` (514 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Christian Brauner, Sasha Levin, corbet, linux-doc, linux-kernel
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit 3f5dc09141a7bfe286620a6869d1d70ffe32d6b8 ]
Section 5f still describes the rule propagate_umount() used before
commit f0d0ba19985d ("Rewrite of propagate_umount()"). It states that a
mount that receives the unmount by propagation is left alone as soon as
it has any submount. That's not true anymore.
A propagated unmount unmounts a mount with sub-mounts as long as every
sub-mount gets unmounted together with it. This is the case when the
sub-mounts are unmounted by the same propagation. Only a sub-mount that
cannot be unmounted keeps its parent mounted.
The section also only describes a single mount without sub-mounts. But
lazy unmounts take a tree and every mount of the tree propagates its
unmount from its parent mount.
Link: https://patch.msgid.link/20260923-work-mount-fixes-v1-8-f424cf8d3242@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a documentation-only correction of stale unmount-propagation
text. The local tree is **6.18.57** (`v6.18.57-155-gcdf239ca885b2`). The
rewrite it documents is already in that tree, so the question is whether
this docs update belongs here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[docs]** **[update]** Update the unmount propagation rule in
shared-subtree documentation.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Link: `https://patch.msgid.link/20260923-work-mount-
fixes-v1-8-f424cf8d3242@kernel.org`
- Signed-off-by: Christian Brauner (Amutable) \<brauner@kernel.org\>
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, or Cc:
stable on this patch itself
- Cover letter of the same series (`[PATCH 0/8] mount: a few gnarly
fixes`) did Cc stable; this 8/8 docs patch did not
- Ignore pipeline tags: `[Upstream commit 3f5dc09141a7…]`, `Signed-off-
by: Sasha Levin`
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** Section 5f of `sharedsubtree.rst` still describes pre-rewrite
`propagate_umount()`: a receiver with any sub-mount is left mounted.
- **Symptom:** Documentation disagrees with current kernel behavior. A
propagated unmount may take a mount that has children if those
children are also unmounted by the same propagation. Only a child that
cannot be unmounted keeps its parent.
- **Also missing:** Lazy `MNT_DETACH` unmounts a tree; every mount in
that tree propagates from its own parent.
- **Version info:** Behavior changed in `f0d0ba19985d` (“Rewrite of
propagate_umount()”).
- **Root cause:** Overview docs were not updated when
`propagate_umount()` was rewritten.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a hidden runtime fix. It is an explicit documentation
correction of obsolete unmount semantics. No code, locking, or error-
path change.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `Documentation/filesystems/sharedsubtree.rst` (+14 / −6)
- One section: “f) Unmount semantics”
- Scope: single-file documentation, surgical
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: receivers at dentry `b` are unmounted only if they have no
sub-mounts. Any child on C2/C3 blocks that receiver; C1 with sub-
mounts fails the whole umount.
- After: receivers are unmounted if every mount below them is also
unmounted. A child unmounted by the same propagation does not pin its
parent. Adds lazy-umount tree propagation and a pointer to
`Documentation/filesystems/propagate_umount.txt`.
- Path affected: documentation of umount/propagation semantics only.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: documentation correctness (obsolete comment/docs)
- Mechanism: overview text still described the old “any sub-mount blocks
the receiver” rule. Code after `f0d0ba19985d` unmounts a receiver when
remaining children are themselves candidates (`trim_one()` / non-
shifting set).
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct relative to this tree’s `propagate_umount()` and
`propagate_umount.txt`
- Minimal; no unrelated edits
- Regression risk: none (no executable code)
- Red flags: none
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Original unmount-semantics prose: `9cfcceea8f7e8f` (Ram Pai,
2005-11-07, `Documentation/sharedsubtree.txt`)
- ReST conversion/formatting: Bagas Sanjaya, 2025-08 (`a8886b42d57b8`,
`b293fd55a1b89`)
- Behavior change that made the text wrong: `f0d0ba19985d` (Al Viro,
2025-06-29, ~v6.17)
- That rewrite **is** an ancestor of this 6.18.y tree
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Expected. The related behavioral commit is
`f0d0ba19985d`, already in `v6.18.57`.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Recent `sharedsubtree.rst` work is formatting/ReST, not semantics
- Precise rules already live in
`Documentation/filesystems/propagate_umount.txt` (added by the
rewrite)
- Standalone: patch 8/8 of Brauner’s “mount: a few gnarly fixes”; this
hunk does not depend on patches 1–7
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record:
- Author is VFS maintainer (`FILESYSTEMS (VFS and infrastructure)` in
MAINTAINERS)
- Same series includes real umount/mount bugfixes (busy propagated
umount, unbindable copy, etc.)
- This patch is the docs companion, not one of those code fixes
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record:
- Depends only on the rewrite already present here, and on
`propagate_umount.txt`, which exists at `v6.18.57`
- Can apply standalone. No new helpers or struct changes.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 3f5dc09141a7…` matched patch-id `0b2df883901084c2…`
- Lore URL: https://patch.msgid.link/20260923-work-mount-
fixes-v1-8-f424cf8d3242@kernel.org
- Series: v1 only (`[PATCH 8/8] docs: update the unmount propagation
rule`), 2026-09-23
- Cover letter: `[PATCH 0/8] mount: a few gnarly fixes`
- Direct replies in the saved thread are about patch 5/8 (`fs: don't
silently unmount busy mounts`), not this docs patch
- No NAK, no reviewer concern, no stable nomination on 8/8 itself
- WebFetch of lore.kernel.org returned 403; thread recovered via `b4 dig
-m`
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`):
- Recipients: Christian Brauner, linux-fsdevel, Linus Torvalds,
Alexander Viro, Jan Kara
- Right maintainers/lists. No extra Reviewed-by on 8/8. Brauner is both
author and VFS maintainer.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No user/syzbot report for the docs. The body is the author’s
observation that section 5f lagged the rewrite. Severity is
documentation inaccuracy, not a crash.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record:
- Series of 8: unbindable copy, MOVE_MOUNT_SET_GROUP, busy propagated
umount, migrating-task ref, plus selftests, plus this docs update
- 8/8 does not implement those fixes; it only restates
`propagate_umount()` after the 2025 rewrite
- Self-contained
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record:
- Cover letter Cc’d `stable@vger.kernel.org`
- Patches 1/8 and 5/8 had explicit `Cc: stable` in the body; 8/8 did not
- Direct lore.kernel.org/stable search was blocked (bot challenge). No
additional stable-thread evidence beyond the series headers.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: None. Documentation only. Semcode tools are not available.
Step 5.2: TRACE CALLERS
Record: N/A for the diff. Documented behavior is implemented by
`propagate_umount()` in `fs/pnode.c`, called from `fs/namespace.c`
(`umount_tree` / `do_umount` path).
Step 5.3: TRACE CALLEES
Record: `propagate_umount()` gathers candidates, `trim_one()` /
`trim_ancestors()` enforce the non-shifting set, `handle_locked()`
enforces locked-mount (non-revealing) rules. That matches “unmount a
parent if every child is also unmounted; a child that cannot be
unmounted keeps the parent.”
Step 5.4: FOLLOW THE CALL CHAIN
Record: Reachable from `umount(2)` / `umount2(MNT_DETACH)` on
shared/slave mounts. Common container/namespace path. The **patch**
itself is not on that path; it only describes it.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Detailed rules already in
`Documentation/filesystems/propagate_umount.txt`. This change makes the
overview consistent with that file instead of contradicting it.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Local tree: VERSION 6.18.57 (`v6.18.57-155-gcdf239ca885b2`)
- Stale section 5f is present at
`v6.18.57:Documentation/filesystems/sharedsubtree.rst` (identical to
the candidate’s pre-image)
- Rewrite `f0d0ba19985d` **is** in `v6.18.57`
- So this tree’s kernel already uses the new rule, while the overview
still documents the old one
- Bug introduced (as a docs mismatch) when the rewrite landed (~v6.17),
i.e. before this 6.18 branch
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. `diff` of `v6.18.57` vs the candidate pre-image is
empty (both 994 lines). Context matches.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record:
- Precise notes (`propagate_umount.txt`) already here
- Related code fix `bf2c8dec26fb7` (“fs: don't silently unmount busy
mounts”) is already in `v6.18.57`; that does not replace this overview
correction
- No earlier equivalent rewrite of section 5f
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record:
- Subsystem: VFS / mount namespace documentation
(`Documentation/filesystems/`)
- Documents CORE mount/umount propagation used by containers
- The change itself is docs, not core code
- Criticality of the **text**: IMPORTANT for people who rely on shared-
subtree docs; runtime criticality: none
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mount/namespace code is actively maintained (Brauner/Viro).
`sharedsubtree.rst` itself is old and mostly formatting churn; the
semantics gap dates to the 2025 rewrite.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Anyone reading shared-subtree unmount docs (container/namespace
users and developers). No runtime user population is changed.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Not a runtime trigger. The mismatch is visible whenever someone
reads section 5f and compares it to `umount` on shared mounts with
nested children.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- Failure mode: incorrect documentation of `umount(2)` propagation
- Userspace that trusts the old “any child blocks the receiver” rule can
mis-predict which mounts disappear
- Accurate rules already exist in `propagate_umount.txt`
- Severity: **LOW** for runtime; **MEDIUM** as a docs bug about user-
visible mount semantics
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: overview matches this tree’s actual `propagate_umount()`;
avoids a documented lie about umount
- Risk: none (14 insertions / 6 deletions, docs only)
- Ratio: favorable — small, zero-risk correction of obsolete docs for
behavior that is already here
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Section 5f is factually wrong in this 6.18.y tree because
`f0d0ba19985d` is present
- Stable exception for documentation/comment fixes applies
- Small, contained, maintainer-authored
- Applies cleanly to `v6.18.57`
- Points at `propagate_umount.txt`, which already exists here
- Zero runtime regression risk
AGAINST:
- No crash, UAF, deadlock, corruption, or security fix
- This patch was not itself Cc’d to stable (1/8 and 5/8 were)
- Precise behavior is already documented in `propagate_umount.txt`
- No user report of the docs bug
UNRESOLVED:
- lore.kernel.org HTTP fetch returned 403; thread was recovered with `b4
dig`
- Could not search lore.kernel.org/stable beyond a bot wall
- No Reviewed-by on 8/8 (unverified whether silent acks existed off-
thread)
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — text matches
`propagate_umount()` / `propagate_umount.txt` in this tree
2. Fixes a real bug that affects users? **PASS** — obsolete description
of user-visible umount semantics (not a runtime bug)
3. Important issue (crash, security, corruption, deadlock)? **FAIL** as
a runtime issue; **PASS** under the documentation exception
4. Small and contained? **PASS** — +14/−6, one rst file
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — context at `v6.18.57` is
identical
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **Documentation fix** — correcting obsolete comments/docs. Zero
runtime risk.
Step 9.4: MAKE YOUR DECISION
The rewrite this documents is already in 6.18.y, the overview is still
wrong, and the patch is a tiny docs-only correction that applies
cleanly. That is exactly the documentation exception. It should be
backported to this tree.
Verification:
- [Phase 1] Parsed subject/tags: docs update; Link to patch 8/8 of work-
mount-fixes; no Fixes/Reported-by/Cc:stable on this patch
- [Phase 1] Cover letter Cc’d stable; patches 1/8 and 5/8 had `Cc:
stable` in the body; 8/8 did not
- [Phase 2] Diff: `Documentation/filesystems/sharedsubtree.rst` +14/−6;
section 5f only
- [Phase 3] `git describe HEAD` / Makefile: 6.18.57
- [Phase 3] `git merge-base --is-ancestor f0d0ba19985d v6.18.57`:
rewrite is in this tree
- [Phase 3] Blame: original text Ram Pai 2005; stale vs rewrite 2025-06
- [Phase 3] `git show
v6.18.57:Documentation/filesystems/sharedsubtree.rst`: old “any sub-
mounts” wording still present
- [Phase 4] `b4 dig -c 3f5dc09141a7`:
https://patch.msgid.link/20260923-work-mount-
fixes-v1-8-f424cf8d3242@kernel.org
- [Phase 4] `b4 dig -a`: v1 only, series of 8
- [Phase 4] `b4 dig -w`: vfs maintainers + linux-fsdevel
- [Phase 4] mbox: no NAK on 8/8; discussion was about 5/8
- [Phase 4] WebFetch lore: 403; UNVERIFIED beyond b4 mbox
- [Phase 5] Semcode unavailable; `propagate_umount()`/`trim_one()` in
`fs/pnode.c` match the new wording
- [Phase 6] File at v6.18.57 identical to candidate pre-image (994
lines, empty diff) — clean apply
- [Phase 6] `propagate_umount.txt` exists at v6.18.57
- [Phase 7] Author is VFS maintainer in MAINTAINERS
- [Phase 8] Failure mode: stale umount-propagation docs; severity LOW
runtime / docs exception
- UNVERIFIED: stable-list discussion beyond series headers
This is a small, obviously correct documentation fix for mount-namespace
behavior that this tree already implements. Risk is zero.
**YES**
Documentation/filesystems/sharedsubtree.rst | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/Documentation/filesystems/sharedsubtree.rst b/Documentation/filesystems/sharedsubtree.rst
index 8b7dc91590837..8bae6d9a7e047 100644
--- a/Documentation/filesystems/sharedsubtree.rst
+++ b/Documentation/filesystems/sharedsubtree.rst
@@ -564,8 +564,8 @@ f) Unmount semantics
where 'A' is a mount mounted on mount 'B' at dentry 'b'.
If mount 'B' is shared, then all most-recently-mounted mounts at dentry
- 'b' on mounts that receive propagation from mount 'B' and does not have
- sub-mounts within them are unmounted.
+ 'b' on mounts that receive propagation from mount 'B' are unmounted as
+ well, if every mount below them is also unmounted.
Example: Let's say 'B1', 'B2', 'B3' are shared mounts that propagate to
each other.
@@ -584,10 +584,18 @@ f) Unmount semantics
So all 'C1', 'C2' and 'C3' should be unmounted.
- If any of 'C2' or 'C3' has some child mounts, then that mount is not
- unmounted, but all other mounts are unmounted. However if 'C1' is told
- to be unmounted and 'C1' has some sub-mounts, the umount operation is
- failed entirely.
+ If any of 'C2' or 'C3' has a child mount that cannot be unmounted
+ then that mount is not unmounted. But all other mounts are unmounted.
+ A child mount that is itself unmounted by the same unmount
+ propagation does not keep its parent mounted. However if 'C1' is
+ supposed to be unmounted and 'C1' has some sub-mounts, the unmount
+ fails.
+
+ A lazy umount (MNT_DETACH) takes a whole tree. Every mount of the
+ tree then propagates its unmount from its own parent as described
+ above, so the mounts that receive propagation lose the corresponding
+ trees as well. Documentation/filesystems/propagate_umount.txt has the
+ precise rules, including the ones for locked mounts.
g) Clone Namespace
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] mmc: cqhci: fix to missed endian conversions
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
2026-10-19 13:44 ` Sasha Levin
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18] docs: update the unmount propagation rule Sasha Levin
@ 2026-10-19 13:44 ` Sasha Levin
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-6.6] ext4: use FGP_WRITEBEGIN for tail block zeroing Sasha Levin
` (513 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Ben Dooks, Adrian Hunter, Ulf Hansson, Sasha Levin, quic_asutoshd,
linux-mmc, linux-kernel
From: Ben Dooks <ben.dooks@codethink.co.uk>
[ Upstream commit 0aae2c73175821a71c0e20607f8e333be5b71940 ]
Fix two places where the wrong type or conversion of little-endian
types to fix the following sparse warnings:
drivers/mmc/host/cqhci-core.c:487:15: warning: incorrect type in assignment (different base types)
drivers/mmc/host/cqhci-core.c:487:15: expected restricted __le32 [usertype]
drivers/mmc/host/cqhci-core.c:487:15: got int
drivers/mmc/host/cqhci-core.c:566:19: warning: incorrect type in assignment (different base types)
drivers/mmc/host/cqhci-core.c:566:19: expected unsigned long long [usertype] *task_desc
drivers/mmc/host/cqhci-core.c:566:19: got restricted __le64 [usertype] *
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a real missed little-endian conversion in CQHCI DMA descriptors,
not a sparse-only cleanup. The local tree is mainline 7.3-rc4; the bug
has been in this file since v4.16.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[mmc / cqhci] [fix] missed little-endian conversions on CQHCI
descriptors**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected for this review pipeline)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** none
- **Acked-by:** Adrian Hunter \<adrian.hunter@intel.com\> (CQHCI/SDHCI
expert)
- **Link:** none in the commit; mailing-list thread recovered via `b4
dig`
- **Cc: stable:** none (not a negative signal here)
- **Signed-off-by:** Ben Dooks \<ben.dooks@codethink.co.uk\> (author);
Ulf Hansson \<ulfh@kernel.org\> (MMC maintainer). Ignore any Sasha
Levin SOB.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug described:** two assignments use the wrong type / omit
`cpu_to_le*` when writing `__le32` / `__le64` CQHCI descriptors.
- **Symptom in the message:** sparse type warnings only. No stack trace,
no reproducer, no user report.
- **Failure mode implied by the code (not stated in the message):** on a
big-endian CPU, transfer-descriptor attributes (including
`CQHCI_DAT_LENGTH`) and DCMD task descriptors are stored in CPU byte
order instead of the little-endian layout the CQHCI controller
expects.
- **Version info:** none in the message.
- **Root cause as given:** missed endian conversion / wrong pointer
type.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Yes, this is a hidden functional endian fix.** The subject
says “fix” but the body only cites sparse. The same file already
converts sibling descriptor fields with `cpu_to_le32`/`cpu_to_le64`.
Omitting that on `__le32 *attr` and `__le64 *task_desc` is a hardware-
descriptor bug on BE, not a warning-only cleanup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/mmc/host/cqhci-core.c` — 7 insertions, 7 deletions
(14 lines touched).
- **Functions:** `cqhci_set_tran_desc()`, `cqhci_prep_dcmd_desc()`.
- **Scope:** single-file surgical fix.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Hunk 1 (`cqhci_set_tran_desc`):** before, `*(__le32 *)attr` was
assigned a native `int` bitfield (`VALID|END|INT|ACT|DAT_LENGTH`).
Address words already used `cpu_to_le64`/`cpu_to_le32`. After, the
attribute word is wrapped in `cpu_to_le32()`. Path: every CQE data
transfer descriptor (normal I/O path).
- **Hunk 2 (`cqhci_prep_dcmd_desc`):** before, `task_desc` was `u64 *`
and `*task_desc |= data` mixed a CPU-endian `u64` into memory obtained
as `__le64`. After, `task_desc` is `__le64 *` and the OR uses
`cpu_to_le64(data)`. Path: CQE direct commands (DCMD), e.g. cache
flush / status when `MMC_CAP2_CQE_DCMD` is set.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Type / endianness]** CQHCI descriptors in memory are little-
endian. `CQHCI_DAT_LENGTH` lives in bits 16–31; DCMD
`CMD_INDEX`/`CMD_TIMING`/`RESP_TYPE` live in bits 16–24. Those fields do
not fit in byte 0, so a native store is wrong on BE. The controller
would see a swapped length and scrambled DCMD opcode/timing. The fix is
the same conversion already used in `cqhci_prep_task_desc()`
(`task_desc[0] = cpu_to_le64(desc0)`).
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct and minimal. On little-endian,
`cpu_to_le32`/`cpu_to_le64` are no-ops, so the common CQHCI population
does not change. Regression risk is very low. No API, locking, or
structure-layout change. `update_dcmd_desc` still mutates the CPU-endian
`u64 data` before conversion (Tegra’s callback is consistent with that).
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Buggy assignments come from **a4080225f51dce** (“mmc: cqhci:
support for command queue enabled host”, Venkat Gopalakrishnan,
2017-11-29), first in **v4.16-rc1**. Address-field conversions were
already present then; the attribute/DCMD stores were the miss. Code has
been in-tree for many years.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The introducing commit is a4080225f51dce
(v4.16). Intermediate related work: **ee49d0321f025** (Eric Biggers,
2021) converted `cqhci_prep_task_desc()` to `__le64 *` + `cpu_to_le64`
and did not fix DCMD / transfer-attr stores.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Recent `cqhci-core.c` work is halt/recovery/callback related,
not endian. Not a numbered series. Standalone.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Ben Dooks is a regular MMC endian/sparse contributor (`dw_mmc`
LE descriptor fixes, endian-agnostic IO). Not the MMC maintainer. Ulf
Hansson applied it; Adrian Hunter acked it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: No functional prerequisite. `cqhci_set_tran_desc` was exported
in **52bf134fca61f** (v6.11) for DWCMSHC; the body bug is independent of
that. File rename `cqhci.c` → `cqhci-core.c` (**0653300224a69**) is a
path tweak only for older trees. Can apply standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore URL from `b4 dig -c 0aae2c73175821`: https://patch.msgid.link/202
60622145036.513129-1-ben.dooks@codethink.co.uk
- **Series:** v1 only (`b4 dig -a`). Applied version is that v1.
- **Review:** Adrian Hunter Acked-by. Ulf Hansson: “Applied for next,
thanks!”
- **NAKs / stable nominations:** none in the thread.
- WebFetch of lore.kernel.org returned 403; thread was read from `b4 dig
-m` mbox instead.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc included Adrian Hunter, Asutosh Das, Ritesh
Harjani, Ulf Hansson, linux-mmc, linux-kernel. Right maintainers were on
the original mail.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by, bugzilla, or syzbot link. Trigger was sparse,
not a user crash report.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone single patch. Not 2/N.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** (lore.kernel.org/stable WebFetch 403). Original
thread did not mention stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `cqhci_set_tran_desc`, `cqhci_prep_dcmd_desc`. Callers also
involved: `cqhci_prep_tran_desc`, `cqhci_request`,
`dwcmshc_set_tran_desc`.
**Step 5.2: TRACE CALLERS**
Record:
- `cqhci_set_tran_desc`: `cqhci_prep_tran_desc` (default),
`dwcmshc_set_tran_desc` in `sdhci-of-dwcmshc.c` (Rockchip/DWC MSHC).
- `cqhci_prep_dcmd_desc`: `cqhci_request()` when `!mrq->data`.
- `cqhci_request` is `.cqe_request` — MMC command-queue I/O, not init-
only.
**Step 5.3: TRACE CALLEES**
Record: Bitfield macros, `get_desc()`, optional `update_dcmd_desc`
(Tegra only), `cpu_to_le32`/`cpu_to_le64`. No alloc/lock changes.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace block I/O on CQE eMMC → MMC core → `cqe_request` →
descriptor prep → doorbell. Reachable on any CQHCI host (Qualcomm, i.MX,
Tegra, MTK, Broadcom STB, Arasan, Intel GLK, TI AM654, Rockchip DWCMSHC,
etc.). BE vs LE is a kernel endian config, not a separate code path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: `cqhci_prep_task_desc` already converts correctly.
`setup_trans_desc()` still writes `VALID|ACT|END` through a `u8 *`;
those bits fit in byte 0, so a LE controller still sees the correct LSB
regardless of CPU endianness. The two sites this patch touches are the
ones that put multi-byte fields into `__le32`/`__le64` words.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: This checkout is **v7.3-rc4** (`7.3.0-rc4`, HEAD
`f0100363d8c37`, origin/master). Commit **0aae2c73175821 is already an
ancestor of HEAD** (merged in `mmc-v7.3`). Pre-fix code is in
`0aae2c73^`. The unconverted stores existed from v4.16 until this
commit. The bug is in this tree’s history and in any stable series that
still has the old assignments.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply on this tree (already applied). Older stables may
still name the file `cqhci.c` and may still have a static
`cqhci_set_tran_desc`; that is a trivial context/path adjustment, not a
semantic rework.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier equivalent DCMD/attr conversion. `ee49d0321f025` only
fixed `cqhci_prep_task_desc`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **MMC host / CQHCI** (`drivers/mmc/host/`). **IMPORTANT** — eMMC
command queue on widely used SoCs and some PCI hosts. Not core mm/VFS,
not staging.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained (halt, recovery, crypto, DWCMSHC callbacks).
CQHCI itself is mature (2017).
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: CQHCI users on **big-endian** kernels. In-tree `supports-cqe` DT
is ARM64 (Qualcomm, Rockchip, Tegra, …). ARM64 has
`CONFIG_CPU_BIG_ENDIAN`. No MIPS `supports-cqe` DT. Little-endian CQHCI
(the usual phone/board case) is unaffected.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Any CQE data transfer (`cqhci_set_tran_desc`) or DCMD
(`cqhci_prep_dcmd_desc`) on BE. Common path if CQE is enabled. Not a
race. Unprivileged I/O can exercise it if the device is
mounted/accessible.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Wrong LE descriptor in DMA memory → controller misreads length /
DCMD fields → **I/O failure and possible data corruption**. **Severity:
HIGH** on BE CQHCI; **none** on LE.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: **Benefit:** high for BE CQHCI (makes CQE descriptors spec-
correct); none for LE. **Risk:** very low (7 lines, LE no-op, no
locking/API). **Ratio:** favorable. This is the usual justification for
descriptor endian fixes in stable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
**FOR backporting:**
- Real missed `cpu_to_le*` on hardware DMA/task descriptors, present
since v4.16.
- Sibling `cqhci_prep_task_desc` and the address fields in the same
function already convert; these two stores were the hole.
- On BE, `DAT_LENGTH` and DCMD opcode/timing/response type would be
byte-swapped → CQE malfunction / corruption risk.
- 7-line, obviously correct, LE no-op.
- Acked by Adrian Hunter; applied by Ulf Hansson.
- Matches the endianness/type-bug class used in stable.
**AGAINST backporting:**
- Commit text only mentions sparse; no user report, no `Fixes:`, no `Cc:
stable`.
- Typical CQHCI hardware is ARM64/x86 LE, so most stable users see no
runtime change.
- Author did not describe a user-visible failure.
**UNRESOLVED:**
- Whether this was discussed on stable@ (lore 403).
- Whether any production BE CQHCI board is in the wild (in-tree CQE DT
is ARM64; ARM64 BE exists but is uncommon).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — mechanical `cpu_to_le*` to
match existing descriptor stores; maintainer ack.
2. Fixes a real bug that affects users? **PASS** — wrong CQHCI
descriptor endianness on BE is a real protocol/hardware bug, not
whitespace.
3. Important issue? **PASS** — wrong transfer length / DCMD fields can
break CQE I/O or corrupt data. Sparse is how it was found, not the
user-visible impact.
4. Small and contained? **PASS** — 7 lines, one file, two functions.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — already present on this
7.3-rc4 tree; the pre-fix pattern is the long-standing one.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/docs exception. Closest adjacent class
is **endianness correctness** (and incidentally a sparse warning). Not a
reason to reject.
**Step 9.4: MAKE YOUR DECISION**
The local tree is mainline **7.3.0-rc4**, which already contains the
fix. The evaluation is whether that fix should also be selected for
stable: the buggy stores have been in CQHCI since **v4.16**, the change
is self-contained, and it corrects hardware-visible descriptors. Sparse
was the detector; the bug is endian-incorrect DMA descriptors. Risk on
the LE majority is zero. That is appropriate for stable.
===============================================================
What the commit solves and why it matters
===============================================================
CQHCI transfer and DCMD descriptors are little-endian in memory. Two
writes used native CPU values: transfer attributes
(`VALID`/`END`/`ACT`/`DAT_LENGTH`) and the DCMD task word. On big-endian
that swaps the length and command fields the controller DMA-reads, so
command-queue I/O can fail or transfer the wrong size. Little-endian
kernels are unchanged. The patch is small, already reviewed by the CQHCI
expert, and needs no extra commits.
Risk vs benefit: very low risk, real correctness fix for BE CQHCI, no
behavior change for typical LE devices.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed commit 0aae2c73175821: Acked-by Adrian Hunter; SOB
Ben Dooks, Ulf Hansson; no Fixes/Reported-by/Cc: stable.
- [Phase 2] Diff: 7+/-7 in `cqhci_set_tran_desc` and
`cqhci_prep_dcmd_desc` only.
- [Phase 2] Confirmed `CQHCI_DAT_LENGTH` is bits 16–31 and DCMD fields
are bits 16+ in `cqhci.h`.
- [Phase 2] Pre-fix parent still assigned native ints/`u64` into `__le*`
memory; addresses already used `cpu_to_le*`.
- [Phase 3] `git blame`: buggy code from a4080225f51dce (v4.16-rc1).
- [Phase 3] `cqhci_prep_task_desc` conversion added in ee49d0321f025
(2021); DCMD/attr left unconverted.
- [Phase 3] Author history on `drivers/mmc/`: several real dw_mmc endian
fixes.
- [Phase 3] `git merge-base --is-ancestor 0aae2c73175821 HEAD` → commit
is in this tree.
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1-only thread; Hunter ack; Ulf
“Applied for next”; lists linux-mmc + Hunter/Hansson.
- [Phase 4] lore WebFetch 403; used local mbox. Stable@ search
UNVERIFIED (403).
- [Phase 5] Callers: `cqhci_request` → prep_tran_desc/prep_dcmd_desc;
`dwcmshc_set_tran_desc` calls `cqhci_set_tran_desc`.
- [Phase 5] No semcode MCP; used git grep.
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4.
- [Phase 6] Fix merged via f96718fc1f614 (`mmc-v7.3`).
- [Phase 6] In-tree `supports-cqe` is ARM64-only; no MIPS matches.
- [Phase 7] CQHCI selected by MSM, i.MX, Tegra, MTK, brcmstb, Arasan,
DWCMSHC, AM654, SDHCI PCI.
- [Phase 8] Failure mode: BE descriptor corruption → CQE I/O failure /
possible data corruption; LE no-op.
- UNVERIFIED: production BE CQHCI user reports; stable@ discussion.
The patch is small, obviously correct, and fixes a real hardware-
descriptor endian bug that has been in this tree’s CQHCI code since
v4.16.
**YES**
drivers/mmc/host/cqhci-core.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c
index 178277d90c31c..00614b500b2bc 100644
--- a/drivers/mmc/host/cqhci-core.c
+++ b/drivers/mmc/host/cqhci-core.c
@@ -484,11 +484,11 @@ void cqhci_set_tran_desc(u8 *desc, dma_addr_t addr, int len, bool end,
{
__le32 *attr = (__le32 __force *)desc;
- *attr = (CQHCI_VALID(1) |
- CQHCI_END(end ? 1 : 0) |
- CQHCI_INT(0) |
- CQHCI_ACT(0x4) |
- CQHCI_DAT_LENGTH(len));
+ *attr = cpu_to_le32((CQHCI_VALID(1) |
+ CQHCI_END(end ? 1 : 0) |
+ CQHCI_INT(0) |
+ CQHCI_ACT(0x4) |
+ CQHCI_DAT_LENGTH(len)));
if (dma64) {
__le64 *dataddr = (__le64 __force *)(desc + 4);
@@ -542,7 +542,7 @@ static int cqhci_prep_tran_desc(struct mmc_request *mrq,
static void cqhci_prep_dcmd_desc(struct mmc_host *mmc,
struct mmc_request *mrq)
{
- u64 *task_desc = NULL;
+ __le64 *task_desc = NULL;
u64 data = 0;
u8 resp_type;
u8 *desc;
@@ -574,7 +574,7 @@ static void cqhci_prep_dcmd_desc(struct mmc_host *mmc,
CQHCI_CMD_TIMING(timing) | CQHCI_RESP_TYPE(resp_type));
if (cq_host->ops->update_dcmd_desc)
cq_host->ops->update_dcmd_desc(mmc, mrq, &data);
- *task_desc |= data;
+ *task_desc |= cpu_to_le64(data);
desc = (u8 *)task_desc;
pr_debug("%s: cqhci: dcmd: cmd: %d timing: %d resp: %d\n",
mmc_hostname(mmc), mrq->cmd->opcode, timing, resp_type);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] ext4: use FGP_WRITEBEGIN for tail block zeroing
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (2 preceding siblings ...)
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-5.10] mmc: cqhci: fix to missed endian conversions Sasha Levin
@ 2026-10-19 13:44 ` Sasha Levin
2026-10-19 14:04 ` sashiko-bot
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18] RDMA/irdma: Suppress PF reset on HMC error Sasha Levin
` (512 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Zhang Yi, Jan Kara, Theodore Ts'o, Sasha Levin, linux-ext4,
linux-kernel
From: Zhang Yi <yi.zhang@huawei.com>
[ Upstream commit e1cf7b5f5c8ad1e00d00c50c61c3e8fdc79cd422 ]
ext4_load_tail_bh() returns a locked folio that callers immediately
mutate through folio_zero_range() and mark_buffer_dirty(). Use
FGP_WRITEBEGIN so that, on backing devices that require stable writes,
__filemap_get_folio() waits for writeback to finish before returning
the folio; on regular devices the wait is a no-op.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260714080044.4038124-2-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: this is a one-line stable-writes data-integrity
fix in a userspace-reachable ext4 tail-zeroing path, and the helper and
`FGP_WRITEBEGIN` both exist in this 7.3-rc4 tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[ext4] [use] use FGP_WRITEBEGIN for tail block zeroing**
Subsystem prefix `ext4:`. Verb is “use” (correctness change of folio-get
flags, not a feature). Claimed intent: get the tail folio with the
write-begin flag set so writeback finishes before the folio is mutated.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Verified from `git show e1cf7b5f5c8ad1e00d00c50c61c3e8fdc79cd422`:
- **Fixes:** none (expected for this review pipeline)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** Jan Kara \<jack@suse.cz\> (ext4 co-maintainer)
- **Acked-by:** none
- **Link:** https://patch.msgid.link/20260714080044.4038124-2-
yi.zhang@huaweicloud.com
- **Cc: stable:** none (expected; not a negative signal)
- **Signed-off-by:** Zhang Yi \<yi.zhang@huawei.com\> (author); Theodore
Ts'o \<tytso@mit.edu\> (ext4 maintainer)
No syzbot, no kernel-test-robot, no multiple reporters.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `ext4_load_tail_bh()` returns a locked folio that callers
immediately mutate with `folio_zero_range()` and
`mark_buffer_dirty()`, without waiting for in-flight writeback.
- **Symptom/failure mode:** On backing devices that require stable
writes, page-cache contents can change while DMA/writeback is in
progress, which can corrupt the in-flight write or break integrity
checksums. On ordinary devices the extra wait is a no-op.
- **Version information:** none in the message. History shows the helper
landed in v7.1-rc1 and this fix in v7.3-rc1.
- **Root cause:** folio obtained with `FGP_LOCK | FGP_ACCESSED |
FGP_CREAT` (no `FGP_STABLE` / `FGP_WRITE`).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Yes, this is a real bug fix**, not cleanup. The cover letter
for the series (v4) states it explicitly: “Add patch 1 to use
FGP_WRITEBEGIN in ext4_load_tail_bh(), fixing a pre-existing stable-
writes bug exposed by patch 4's reordering.”
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `fs/ext4/inode.c` — **1 insertion, 1 deletion**
- Function: `ext4_load_tail_bh()`
- Scope: **single-file surgical fix** (one flag expression)
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
**Before:** `__filemap_get_folio(..., FGP_LOCK | FGP_ACCESSED |
FGP_CREAT, ...)`. Locks/creates the folio and marks it accessed. Does
**not** wait for writeback.
**After:** `__filemap_get_folio(..., FGP_WRITEBEGIN | FGP_ACCESSED,
...)`.
`FGP_WRITEBEGIN` is defined in `include/linux/pagemap.h` as:
`FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE`
Net additions: `FGP_WRITE` and `FGP_STABLE`. `FGP_STABLE` calls
`folio_wait_stable()` after the folio is locked (`mm/filemap.c`). That
waits for writeback only if `mapping_stable_writes()` is set.
Path affected: every caller of `ext4_load_tail_bh()` immediately zeros
the folio (`ext4_block_do_zero_range()`,
`ext4_block_journalled_zero_range()`). This is a **normal mutator
path**, not an error-only path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** memory-safety / data integrity (stable-pages race with
writeback), plus a small GFP/idle-flag side effect from `FGP_WRITE`
- **Mechanism:** On `AS_STABLE_WRITES` mappings, in-flight writeback
DMA’s from page cache. Zeroing the folio without `folio_wait_stable()`
can mix old and new contents in the I/O. `FGP_WRITEBEGIN` is the
established write-begin flag set that waits first.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Quality:** obviously correct. Same flags every `->write_begin`
implementation uses. `folio_wait_stable()` is a no-op when
`mapping_stable_writes()` is false, so typical disks are unchanged.
- **Regression risk:** very low. Waiting while the folio is locked is
the documented write-begin pattern (`folio_wait_stable` comment: if
unlocked, writeback can restart). `FGP_ACCESSED | FGP_WRITEBEGIN`
still takes the `FGP_ACCESSED` branch in `__filemap_get_folio()`, so
idle-flag clearing does not change vs the old flags; `FGP_WRITE` only
adds `__GFP_WRITE` on allocation.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Current line is `e1cf7b5f5c8ad` (this commit).
- Same flags were already in `__ext4_block_zero_page_range()` before the
helper was factored out (`3b312a6f510ca`, v7.1-rc1, “ext4: factor out
journalled block zeroing range”).
- Folio conversion `9d3973de9a374` (“ext4: Convert
__ext4_block_zero_page_range() to use a folio”, v6.4 era) replaced
`find_or_create_page()` with `FGP_LOCK | FGP_ACCESSED | FGP_CREAT`.
`find_or_create_page()` also did **not** wait for stable writeback, so
the gap is older than the helper.
- Helper `ext4_load_tail_bh` first appeared in **v7.1-rc1**
(`3b312a6f510ca`).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Not applicable. The immediate pre-image is
the helper as introduced in `3b312a6f510ca`, which copied the old flags.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: This is **patch 1/9** of Zhang Yi’s series “ext4: fix unaligned
edge handling in FALLOC_FL_WRITE_ZEROES”, landed together around
2026-07-22:
1. `e1cf7b5f5c8ad` this commit
2. `2fff82f081401` skip tail zeroing for inline data
3. `705a3fd3bac16` check `ext4_get_block()` return
4. `b16e9d27a643a` move partial zeroing earlier in `ext4_zero_range()`
(the reorder that **exposes** the stable-writes bug)
5–9. WRITE_ZEROES edge-handling / orphan-list work
This patch does **not** depend on 2–9. Later patches that increase tail-
zeroing (especially 4) depend on this one for correctness on stable-
write devices.
Related earlier commit `df0b5afc62f33` (“ext4: remove the redundant
folio_wait_stable()”) is a different path (`ext4_da_write_begin`); it
only shows that ext4 already treats `FGP_WRITEBEGIN` as implying the
stable wait.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Zhang Yi is a regular, high-volume ext4 contributor (tail-
zeroing, WRITE_ZEROES, journal paths). This series was reviewed by Jan
Kara and applied by Ted Ts'o. Related commits in the same week are the
rest of the 1/9 series.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Prerequisite API: `FGP_WRITEBEGIN` from `e999a5c5a19cf` (“fs: Add
FGP_WRITEBEGIN”), present since **v6.4-rc1**. Present in this tree.
- Prerequisite function: `ext4_load_tail_bh()` since **v7.1-rc1**.
Present in this tree.
- **Can apply standalone:** yes. One flag change; no new helpers.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c e1cf7b5f5c8ad` → https://patch.msgid.link/20260714080044.40
38124-2-yi.zhang@huaweicloud.com
- Series revisions: **v3** (2026-07-08) and **v4** (2026-07-14). Cover
letter: v4 has **no code changes** vs v3; v2 **added this patch**.
- Cover letter quote (verified in saved mbox): “Add patch 1 to use
FGP_WRITEBEGIN in ext4_load_tail_bh(), fixing a pre-existing stable-
writes bug exposed by patch 4's reordering.”
- Ted Ts'o applied the series; patch 9 was dropped separately over
error-handling concerns.
- No NAK on this patch. No reviewer asked for `Cc: stable` on patch 1
(patches 7/8 in the same mbox do have `Cc: stable`, for WRITE_ZEROES-
specific bugs).
- WebFetch of lore.kernel.org returned **403**; discussion recovered via
`b4 dig -m /tmp/ext4-fgp.mbox`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
`b4 dig -w` recipients included linux-ext4, linux-fsdevel, tytso,
adilger, Jan Kara, Ojaswin Mujoo, Ritesh Harjani, Huawei ext4
developers.
Record: **Jan Kara Reviewed-by** (in the patch); **Ted Ts'o** applied
it. Right maintainers were on the thread.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: **No standalone bugzilla/syzbot report.** The bug was found
while reworking WRITE_ZEROES unaligned edges. Severity from the author:
pre-existing **stable-writes data-integrity** bug.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone as a fix. The rest of 1/9 is WRITE_ZEROES contract
work and two other pre-existing helper fixes (inline-data skip;
propagate `ext4_get_block()` errors). This commit does not require those
to be correct.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable WebFetch returned **403**. No evidence in
the ext4 thread that this patch 1 was requested for stable or rejected
for stable. **UNVERIFIED** whether linux-stable@ discussed it.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: **`ext4_load_tail_bh()`** only.
**Step 5.2: TRACE CALLERS**
Verified in this tree:
- `ext4_block_do_zero_range()` → `folio_zero_range()` +
`mark_buffer_dirty()`
- `ext4_block_journalled_zero_range()` → journal write access +
`folio_zero_range()`
- Both from `ext4_block_zero_range()`
- That is used by:
- `ext4_block_zero_eof()` — truncate (`ext4_truncate`), append
(`ext4_write_checks` in `fs/ext4/file.c`), extent operations
(`fs/ext4/extents.c`)
- `ext4_zero_partial_blocks()` — punch hole / zero_range /
WRITE_ZEROES (`ext4_punch_hole`, `ext4_zero_range`, extents
WRITE_ZEROES)
Record: **Common filesystem operations**, process context, folio locked.
Not IRQ.
**Step 5.3: TRACE CALLEES**
Record: `__filemap_get_folio()` → on `FGP_STABLE`, `folio_wait_stable()`
→ `folio_wait_writeback()` if `mapping_stable_writes()`. Then
`create_empty_buffers` / `ext4_get_block` / `ext4_read_bh_lock` as
before.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: **Userspace-reachable** without privilege beyond write access to
an ext4 file: `truncate`,
`fallocate(PUNCH_HOLE|ZERO_RANGE|WRITE_ZEROES)`, append `write()`.
**HIGH** reachability.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Other ext4 write paths already use `FGP_WRITEBEGIN`
(`fs/ext4/inline.c`, `fs/ext4/move_extent.c`) and/or explicit
`folio_wait_stable()` (`ext4_write_begin`, `ext4_page_mkwrite`). Tail-
block zeroing was the outlier.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: **`git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`**,
`VERSION=7 PATCHLEVEL=3 SUBLEVEL=0 EXTRAVERSION=-rc4`. Origin is
torvalds/linux (mainline), detached HEAD.
- `ext4_load_tail_bh()` exists at `fs/ext4/inode.c` (currently already
using `FGP_WRITEBEGIN | FGP_ACCESSED` because `e1cf7b5f5c8ad` **is an
ancestor of HEAD**).
- Buggy pre-image (helper with `FGP_LOCK | FGP_ACCESSED | FGP_CREAT`)
existed from **v7.1-rc1** (`3b312a6f510ca`) until this fix in
**v7.3-rc1**.
- `FGP_WRITEBEGIN` exists here (`include/linux/pagemap.h:720`).
The pipeline instruction is to ignore “already selected” markers, not to
treat mainline already containing the original commit as a reason to
reject a backport-worthy fix. The code and prerequisites are in this
tree.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** on this tree (one-line flag change;
`FGP_WRITEBEGIN` present). `git log --oneline -10 -- fs/ext4/inode.c`
shows normal ext4 churn; nothing that would conflict with this hunk.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This exact change **is** HEAD’s current code (`git blame` on the
flags line is `e1cf7b5f5c8ad`). No alternate fix for the same stable-
writes hole in `ext4_load_tail_bh()`. Other `folio_wait_stable()` sites
in ext4 do not cover this helper.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **Subsystem: fs/ext4. Criticality: IMPORTANT** (widely used
filesystem; data-integrity on stable-write devices). Not core mm/VFS,
but truncate/punch/zero are universal ext4 operations.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: **Actively developed** (WRITE_ZEROES series, iomap conversion,
journal/writeback fixes in 7.3). The helper itself is recent (v7.1) but
the missing stable wait is the same pattern as the older zero-page-range
code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **ext4 users whose backing device requires stable writes**, i.e.
`bdev_stable_writes()`: integrity checksums (`CONFIG_BLK_DEV_INTEGRITY`)
**or** `BLK_FEAT_STABLE_WRITES`.
Verified setters of `BLK_FEAT_STABLE_WRITES` in this tree include NVMe
(when `data_digest` is enabled), RAID5 `skip_copy`, dm-integrity, zram,
RBD, iSCSI TCP, MMC, DRBD. Superblock then sets `SB_I_STABLE_WRITES` and
inode mappings get `AS_STABLE_WRITES`.
Not universal, but not a toy config: enterprise integrity, RAID, dm-
integrity, some NVMe.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Trigger: tail/partial-block zeroing while that folio is under
writeback.
- How common: truncate, punch, zero_range, append past EOF —
**routine**. The race still needs concurrent writeback of that folio,
so it is **timing-dependent**.
- Cover letter: patch 4’s reorder **widens** the window; the bug is
still pre-existing without patch 4. This tree **already has patch 4**
(`b16e9d27a643a`).
- Unprivileged users with write access **can** trigger the operations.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Failure mode: in-flight writeback sees torn folio contents /
integrity checksum mismatch.** **Severity: CRITICAL** (data corruption),
limited to stable-write devices. Not a panic path.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit: high** for ext4 on stable-write devices (prevents silent
data corruption on common ops). **Low** for everyone else (wait is a
no-op).
- **Risk: very low** (1 line, standard flags, no API change, no new
locking order).
- **Ratio: strongly favors applying.**
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
**FOR backporting:**
- Author and cover letter call it a **pre-existing stable-writes bug**.
- Mutating a folio under writeback on `AS_STABLE_WRITES` is a known
class of **data corruption**.
- Reachable from truncate / fallocate / append.
- One-line, matches `FGP_WRITEBEGIN` used everywhere else.
- Reviewed by Jan Kara; applied by Ted Ts'o.
- `FGP_WRITEBEGIN` and `ext4_load_tail_bh()` both exist in this 7.3-rc4
tree.
- This tree also has the later reorder (`b16e9d27a643a`) that
**exposes** the race more.
**AGAINST backporting:**
- No Fixes tag, no user/syzbot report (not a valid NO by pipeline
rules).
- Nested in a 9-patch WRITE_ZEROES series; later patches are feature-
contract fixes. This patch is still self-contained.
- Author did not `Cc: stable` on patch 1 (other patches in the same
series did).
- Bug existed in spirit since `find_or_create_page()`; field reports are
absent, so the race may be rare without the v7.3 reorder.
**UNRESOLVED:**
- linux-stable@ archives could not be fetched (HTTP 403).
- Full v2 mailing-list review text for this hunk was not retrieved (lore
403); Jan’s Reviewed-by on the committed patch is verified.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one flag change to the
standard write-begin set; reviewed by Jan Kara; in mainline since
v7.3-rc1.
2. Fixes a real bug that affects users? **PASS** — stable-writes devices
(NVMe digest, RAID5 skip_copy, dm-integrity, zram, T10 PI, etc.).
3. Important issue? **PASS** — data corruption on in-flight writeback,
not a crash, but explicitly in the stable rules list.
4. Small and contained? **PASS** — 1 line, one function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — `FGP_WRITEBEGIN` and
`ext4_load_tail_bh()` are here; the hunk is identical to what already
landed.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **None** (not a device ID, quirk, DT, build, or docs exception).
It qualifies as a normal data-integrity bug fix.
**Step 9.4: MAKE YOUR DECISION**
This tree is **Linux 7.3-rc4** (Linus mainline). The helper lives here,
`FGP_WRITEBEGIN` lives here, and callers still zero the folio
immediately. The change is a one-line restoration of the stable-write
wait that every other write-begin path already does. That is exactly the
kind of small, important data-integrity fix stable trees should take.
The surrounding WRITE_ZEROES series is not required for this hunk to be
correct.
### What the commit solves
`ext4_load_tail_bh()` was grabbing a locked folio without `FGP_STABLE`.
Callers then call `folio_zero_range()` and dirty the buffer. On devices
that set `AS_STABLE_WRITES` (integrity checksums or
`BLK_FEAT_STABLE_WRITES`), that can change page-cache bytes while
writeback DMA is still running. Switching to `FGP_WRITEBEGIN |
FGP_ACCESSED` waits for writeback first; elsewhere the wait is a no-op.
### Stable rules / risk vs benefit
Meets all six stable criteria. Benefit is preventing filesystem data
corruption on a real (if not universal) device class; risk is a single
established flag combination.
### Concerns
- Nested in a larger series, but this patch is standalone.
- No field report; the author found it while reordering zeroing. Still a
concrete integrity bug, and this tree already contains the reorder
that widens it.
- Lore stable-list search was blocked (403); that does not change the
code-level conclusion.
Verification:
- [Phase 1] Parsed tags from `git show e1cf7b5f5c8ad`: Reviewed-by Jan
Kara; Link msgid `...4038124-2...`; no Fixes/Reported-by/Cc:stable
- [Phase 1] Cover letter in `/tmp/ext4-fgp.mbox` msg 5: “pre-existing
stable-writes bug exposed by patch 4's reordering”
- [Phase 2] Diff: 1 line in `ext4_load_tail_bh()`; flags
`FGP_LOCK|FGP_ACCESSED|FGP_CREAT` → `FGP_WRITEBEGIN|FGP_ACCESSED`
- [Phase 2] `FGP_WRITEBEGIN` = `FGP_LOCK|FGP_WRITE|FGP_CREAT|FGP_STABLE`
(`include/linux/pagemap.h:720`)
- [Phase 2] `__filemap_get_folio` calls `folio_wait_stable()` when
`FGP_STABLE` (`mm/filemap.c:1986-1987`)
- [Phase 2] `folio_wait_stable()` only waits if
`mapping_stable_writes()` (`mm/page-writeback.c:3105-3108`)
- [Phase 3] `git describe --contains --match 'v7.*' 3b312a6f510ca` →
v7.1-rc1 (helper introduced)
- [Phase 3] `git describe --contains --match 'v7.*' e1cf7b5f5c8ad` →
v7.3-rc1 (this fix)
- [Phase 3] `git merge-base --is-ancestor e1cf7b5f5c8ad HEAD` true;
`3b312a6f510ca` also ancestor
- [Phase 3] `git show 9d3973de9a374`: folio conversion used the same
non-stable flags; previously `find_or_create_page()`
- [Phase 3] `git show 3b312a6f510ca`: factor-out copied those flags into
`ext4_load_tail_bh()`
- [Phase 4] `b4 dig -c e1cf7b5f5c8ad`: lore URL; v3 then v4; v4 no code
change
- [Phase 4] `b4 dig -w`: linux-ext4, tytso, Jan Kara, adilger, Ojaswin,
Ritesh on Cc
- [Phase 4] `b4 dig -m /tmp/ext4-fgp.mbox`: Ted applied 1–8; patch 9
dropped; no NAK on patch 1
- [Phase 4] WebFetch lore.kernel.org 403 — UNVERIFIED stable-list
discussion
- [Phase 5] Callers: `ext4_block_do_zero_range` /
`ext4_block_journalled_zero_range` → `ext4_block_zero_range` →
`ext4_block_zero_eof` / `ext4_zero_partial_blocks` (truncate, punch,
zero_range, WRITE_ZEROES, append)
- [Phase 5] Other ext4 write paths already use `FGP_WRITEBEGIN` or
`folio_wait_stable()`
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; Makefile
7.3.0-rc4
- [Phase 6] Current `fs/ext4/inode.c:4042-4043` already has
`FGP_WRITEBEGIN | FGP_ACCESSED`
- [Phase 7] fs/ext4, important filesystem
- [Phase 8] `bdev_stable_writes()` = integrity csum OR
`BLK_FEAT_STABLE_WRITES` (`include/linux/blkdev.h:1410-1414`)
- [Phase 8] `BLK_FEAT_STABLE_WRITES` set by nvme (data_digest), raid5
skip_copy, dm-integrity, zram, rbd, iscsi_tcp, mmc, drbd
- [Phase 8] Failure: data corruption on stable-write devices; wait is
no-op otherwise
- UNVERIFIED: linux-stable mailing list history (HTTP 403)
- UNVERIFIED: full v2 review mail body for this hunk (lore 403);
Reviewed-by on the commit is verified
**YES**
fs/ext4/inode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 2e3f7ba1a924b..c3fb5f16f6e39 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4092,7 +4092,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
int err = 0;
folio = __filemap_get_folio(mapping, from >> PAGE_SHIFT,
- FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
+ FGP_WRITEBEGIN | FGP_ACCESSED,
mapping_gfp_constraint(mapping, ~__GFP_FS));
if (IS_ERR(folio))
return PTR_ERR(folio);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] RDMA/irdma: Suppress PF reset on HMC error
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (3 preceding siblings ...)
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-6.6] ext4: use FGP_WRITEBEGIN for tail block zeroing Sasha Levin
@ 2026-10-19 13:44 ` Sasha Levin
2026-10-19 14:00 ` sashiko-bot
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-6.6] iommu/qcom: Enable clocks before hardware access in qcom_iommu_ctx_probe() Sasha Levin
` (511 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Seyeong Kim, Leon Romanovsky, Sasha Levin, tatyana.e.nikolova,
linux-rdma, linux-kernel
From: Seyeong Kim <seyeong.kim@canonical.com>
[ Upstream commit 4dc9c884c0aafac1e8d37536d88d485135e26883 ]
The irdma driver currently issues an unconditional PF reset whenever the
HMC Error interrupt (PFINT_OICR bit 26) fires:
if (event->reg & IRDMAPFINT_OICR_HMC_ERR_M) {
ibdev_err(&iwdev->ibdev, "HMC Error\n");
iwdev->rf->reset = true;
}
request_reset() issues an IIDC_PFR to ice. In practice a single HMC_ERR
can trigger cascading PF resets, IOMMU faults during teardown, and
teardown of every RDMA connection on the device.
i40e handles the identically-named interrupt by reading
PFHMC_ERRORINFO and PFHMC_ERRORDATA and logging them without touching
device state; see commit 9c010ee0ea5f ("i40e: Suppress HMC error to
Interrupt message level") which removed the reset as "not necessary".
This patch mirrors that handling on irdma.
With this change, repeated HMC_ERR no longer produces a reset storm and
RDMA traffic on the device continues uninterrupted.
Signed-off-by: Seyeong Kim <seyeong.kim@canonical.com>
Link: https://patch.msgid.link/20260619050044.1807044-1-seyeong.kim@canonical.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
irdma GEN2 HMC-error path exists here, and this change is a real
production fix for Intel E810 PF-reset storms. Analysis below is for
this tree only.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[RDMA/irdma] [Suppress] [stop issuing a PF reset when the HMC
Error interrupt fires]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none in the commit message
- **Tested-by:** none tagged (author did describe hardware testing in
the RFC/v2 cover)
- **Reviewed-by / Acked-by:** none
- **Link:** `https://patch.msgid.link/20260619050044.1807044-1-
seyeong.kim@canonical.com`
- **Cc: stable:** none (expected)
- **Signed-off-by:** Seyeong Kim (author); Leon Romanovsky (RDMA
maintainer). The pipeline’s “Sasha Levin” SOB is ignored.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `icrdma_iidc_event_handler()` sets `iwdev->rf->reset = true`
on `IRDMAPFINT_OICR_HMC_ERR_M` (PFINT_OICR bit 26). That calls
`request_reset()` → `ice_rdma_request_reset(..., IIDC_FUNC_RESET)` →
`ICE_RESET_PFR`.
- **Symptom:** cascading PF resets, IOMMU/DMAR faults during teardown,
every RDMA connection on the device torn down. On newer NVM a single
forced HMC_ERR still caused a full PF reset and aborted RDMA traffic.
- **Root cause (author):** HMC_ERR was treated as fatal; i40e stopped
resetting on the same interrupt in 9c010ee0ea5f (“reset that was not
necessary”).
- **Version info:** author tested Ubuntu 6.8 (NVM 3.10, cascading resets
+ DMAR) and mainline 7.1-rc4 (NVM 4.51, single reset). Driver path has
existed since irdma GEN2 was added.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not hidden.** This is an explicit error-handling fix: stop a
destructive reset. Diagnostic MMIO reads are extra, not a cleanup
disguised as a fix.
===============================================================
PHASE 2: DIFF ANALYSIS
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `drivers/infiniband/hw/irdma/icrdma_if.c`: HMC_ERR branch (stop reset;
log errinfo/errdata)
- `drivers/infiniband/hw/irdma/irdma.h`: `IRDMA_PFHMC_ERRORINFO`,
`IRDMA_PFHMC_ERRORDATA` before `IRDMA_MAX_REGS`
- `drivers/infiniband/hw/irdma/icrdma_hw.h` / `icrdma_hw.c`: GEN2
offsets `0x00520400` / `0x00520500`
- `drivers/infiniband/hw/irdma/i40iw_hw.c`: matching `0xffffffff`
placeholders so GEN1 array length still matches the enum
**+15 / −3**, five files. **Surgical, single-subsystem.** Function:
`icrdma_iidc_event_handler`.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record: **Before:** HMC_ERR → `ibdev_err("HMC Error")` → `rf->reset =
true` → `request_reset()`. **After:** HMC_ERR → `readl`
ERRORINFO/ERRORDATA → `ibdev_warn` → **do not set reset**. PE_CRITERR
(except Q1 resource check) and PE_PUSH still reset.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Logic / hardware-error handling (over-aggressive recovery).**
Unconditional PF reset on a non-fatal (or at least non-reset-worthy)
interrupt causes reset storms, aux unplug, IOMMU faults, and full RDMA
teardown. Fix: log-only, matching i40e. ice itself already only
*forwards* HMC_ERR to the aux driver and does not reset on that bit.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Core change (clear `rf->reset = true`) is obviously correct
relative to i40e/ice. Diagnostic register plumbing is extra; offsets
were **inferred** from `PFHMC_PDINV` (+0x100/+0x200), same spacing as
i40e’s PDINV/ERRORINFO/ERRORDATA. Forced-interrupt tests read back 0, so
offsets are unverified against a datasheet, but they are **read-only**
and not the recovery change. GEN1/GEN2 arrays were updated together;
GEN3/GEN4 use `ig3rdma_init_hw()` and do not index `IRDMA_MAX_REGS`.
**Regression risk:** leaving a true HMC failure running without reset —
possible, but i40e has done this since 2014, ice does not reset on
HMC_ERR, and PE_CRITERR/PE_PUSH still reset. **Low risk** for the reset-
suppression itself.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Unconditional HMC reset came from **8498a30e1b948**
(“RDMA/irdma: Register auxiliary driver…”, 2021-06-02), moved into
`icrdma_if.c` by **0c2b80cac96e1** (2025 refactor). Present since irdma
GEN2 (~5.14-era), not new 7.3 code.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Related precedent **9c010ee0ea5f** (i40e,
2014) is in this tree (`git merge-base --is-ancestor` succeeded). i40e
still logs HMC error info and does not reset.
**Step 3.3: CHECK FILE HISTORY**
Record: Recent irdma work is GEN3/GEN4 and udata hardening. This patch
is **standalone**, not “X/Y”. Later commits do not revert or replace
this HMC handling.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Seyeong Kim (Canonical) — one irdma commit here. Intel irdma
maintainer is Tatyana Nikolova (CC’d). Applied by Leon Romanovsky.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs `icrdma_if.c`, `IRDMA_GLINT_RATE` in the enum (so new
entries stay last), and ice `IIDC_RDMA_EVENT_CRIT_ERR`. All present in
this 7.3 tree. **Applies standalone** here.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 4dc9c884c0aaf`: RFC + v2. Applied version is **v2**
(`20260619050044.1807044-1`).
- RFC: https://patch.msgid.link/20260416071541.3899471-1-
seyeong.kim@canonical.com
- v2: https://patch.msgid.link/20260619050044.1807044-1-
seyeong.kim@canonical.com
- RFC notes: offsets inferred; “every HMC_ERR is safe to continue” not
datasheet-confirmed; repro via `/dev/mem` write to PFINT_OICR, not
firmware HMC.
- May 22 follow-up: retested on **7.1-rc4**; patch applied unchanged.
- **No NAK** in the saved thread. lore.kernel.org HTML fetch returned
403; thread recovered via `b4 dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): linux-rdma, Krzysztof Czurylo, Tatyana Nikolova,
Jason Gunthorpe, Leon Romanovsky. **No Reviewed-by** in the mbox (RFC,
author ping, then maintainer apply). Right maintainers were CC’d.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: Real-world HMC_ERR → “Requesting a reset” is widely reported:
- GitHub intel/ethernet-linux-ice#12: recurring OICR `0x06000803` / HMC
Error / PF reset on multiple machines; workaround unload/blacklist
irdma.
- Proxmox forum: E810 HMC Error → Corosync loss / node reboots.
- Alpine even blacklists `irdma` by default over this class of issue.
Author also cites a **customer report on NVM 3.10** (cascading PFR +
DMAR).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Single patch (RFC → v2). Not a multi-patch series.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search **403**. No evidence this commit
was NAK’d for stable. Unrelated 6.6 irdma reset patch
(`irdma_modify_qp_to_err`) is a different bug.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: KEY FUNCTIONS**
Record: `icrdma_iidc_event_handler` (behavior). Arrays/enum:
`icrdma_regs`, `i40iw_regs`, `enum irdma_registers`. Init:
`icrdma_init_hw` / `i40iw_init_hw` walk `IRDMA_MAX_REGS`.
**Step 5.2: TRACE CALLERS**
Record: Registered as `.event_handler` on the GEN2 auxiliary driver. ice
misc IRQ sets `ICE_AUX_ERR_PENDING` for `PFINT_OICR_HMC_ERR_M`; service
task sends `IIDC_RDMA_EVENT_CRIT_ERR` with the OICR value.
**Hardware/interrupt-driven**, not a syscall. Hits any system with ice +
irdma loaded (E810 and similar), including hosts that are not running
RDMA traffic.
**Step 5.3: TRACE CALLEES**
Record: After the patch, `readl` of two HMC diagnostic regs. Before,
`icrdma_request_reset` → `ice_rdma_request_reset` →
`ice_schedule_reset(ICE_RESET_PFR)` — full function reset, unplug aux,
drop the NIC datapath.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: ice OICR → service task → aux event → irdma handler → (old) PF
reset. Userspace cannot set OICR, but **firmware/hardware HMC_ERR is
common** on E810. Forced-bit tests still prove the handler’s reset is
what destroys connections.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same interrupt: i40e logs and does not reset; ice does not
reset, only notifies aux. irdma PE_CRITERR already special-cases Q1
resource errors as non-fatal. This HMC change is the same pattern.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `icrdma_iidc_event_handler` in
`drivers/infiniband/hw/irdma/icrdma_if.c`. Pre-fix parent still had
`rf->reset = true` on HMC_ERR. Bug introduced **2021** (8498a30e1b948),
long before 7.3. Current HEAD already contains **4dc9c884c0aaf** (that
is the mainline merge of this fix, not a reason to reject it on merit).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply on this tree.** Context matches. GEN1 placeholders
keep `IRDMA_MAX_REGS` arrays aligned. Would need more care on much older
stables if `IRDMA_GLINT_RATE` or `icrdma_if.c` were missing; **not an
issue here**.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This *is* the HMC-reset suppression. No alternate fix. i40e’s
older analogous change is present.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: **RDMA/irdma (Intel E810 / ice GEN2).** **IMPORTANT** — not core
mm/VFS, but E810 is common in servers/clusters. A PF reset takes down
**Ethernet as well as RDMA**.
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Actively developed (GEN3/GEN4, udata). This handler itself has
been stable since the 2021 introduction / 2025 file move.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: WHO IS AFFECTED**
Record: **Driver-specific** — ice + irdma (Intel E810 and related).
Includes clusters that load irdma by default even when they do not use
RDMA (Proxmox/ice GitHub reports).
**Step 8.2: TRIGGER CONDITIONS**
Record: Hardware HMC_ERR (OICR bit 26). Seen in the field without a
special RDMA workload. Not a userspace-triggered security bug. **Common
enough** that distros document blacklisting irdma.
**Step 8.3: FAILURE MODE SEVERITY**
Record: PF reset → link down, RDMA teardown, IOMMU faults, uverbs WARN
during aux unplug, cluster partition / reboot in reports. **Severity:
HIGH (hang/datapath loss); CRITICAL in HA/cluster setups.**
**Step 8.4: RISK-BENEFIT RATIO**
Record: **Benefit: high** (stops reset storms on a widely deployed NIC).
**Risk: low** for dropping the reset; **very low** extra risk from read-
only diagnostic MMIO (wrong offset would log junk or, at worst, a bad
read — tests did not blow up). Ratio favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real, user-visible bug: PF reset storm, IOMMU faults, full
RDMA/Ethernet disruption on E810.
- Field reports (customer, Proxmox, ice GitHub); Canonical engineer with
before/after on 6.8 and 7.1-rc4.
- Small (+15/-3), contained in irdma.
- Matches i40e (2014, Intel: reset “not necessary”) and ice (forwards
HMC_ERR, does not reset).
- Fatal PE_CRITERR / PE_PUSH paths unchanged.
- RDMA maintainer applied it; Intel irdma maintainers were CC’d.
- Code and prerequisites exist in this 7.3 tree.
AGAINST:
- Diagnostic register offsets inferred, not datasheet-confirmed (reads
were 0 on a *forced* interrupt).
- Author RFC: not proven every firmware HMC_ERR is safe to run through.
- Repro used `/dev/mem` OICR injection, not a firmware HMC event
(customer logs still show the same handler path).
- No Fixes/Cc stable, no Reviewed-by (absence is not a no-vote per the
rules).
UNRESOLVED:
- Full public review text beyond the RFC mbox (lore HTML 403).
- Whether stable@ discussed this specific patch (stable search 403).
- Exact meaning of HMC_ERR on E810 silicon.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — drop destructive reset;
tested on E810; i40e/ice precedent.
2. Fixes a real bug that affects users? **PASS** — production reset
storms.
3. Important (crash/security/corruption/deadlock)? **PASS** — PF reset /
datapath loss / IOMMU faults / cluster impact. HIGH.
4. Small and contained? **PASS** — 15 insertions, one handler.
5. No new features or APIs? **PASS** — error-path policy + diagnostic
reads.
6. Can apply to the local tree? **PASS** — matching irdma GEN2 code in
7.3.0-rc4.
**Step 9.3: EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. It is a
**hardware error-handling workaround** in an existing driver (same class
as USB/PCI quirks: stop a harmful default for real devices).
**Step 9.4: DECISION**
This tree has the irdma GEN2 HMC path. Suppressing PF reset on HMC_ERR
is a small, tested fix for a serious, widely seen E810 failure mode.
Diagnostic MMIO is best-effort; the stable-worthy part is not resetting.
Benefit clearly outweighs risk.
Verification:
- [Phase 1] Tags: Link to msgid 20260619050044; SOB Seyeong Kim + Leon
Romanovsky; no Fixes/Reported-by/Cc stable
- [Phase 2] Diff: 5 files, +15/-3; HMC_ERR no longer sets `rf->reset`;
GEN2 regs + GEN1 0xffffffff pads
- [Phase 2] Confirmed `ice_rdma_request_reset(IIDC_FUNC_RESET)` →
`ICE_RESET_PFR`
- [Phase 3] Blame: reset from 8498a30e1b948 (2021); moved in
0c2b80cac96e1
- [Phase 3] `git merge-base --is-ancestor 9c010ee0ea5f HEAD` = YES; i40e
still log-only
- [Phase 3] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4
- [Phase 3] `git merge-base --is-ancestor 4dc9c884c0aaf HEAD` = YES
(mainline landing of this fix)
- [Phase 4] `b4 dig -c 4dc9c884c0aaf`: RFC then v2; v2 applied; `-w`
CC’d Intel irdma + RDMA maintainers
- [Phase 4] `b4 dig -m`: RFC caveats + 7.1-rc4 retest; no NAK in mbox
- [Phase 4] External: ice GitHub #12 and Proxmox E810 HMC reset reports
- [Phase 4] lore.kernel.org WebFetch 403; stable@ search 403 — listed
UNVERIFIED
- [Phase 5] Handler is ice aux `.event_handler`; GEN3/4 use a different
event path (no HMC reset there)
- [Phase 6] Pre-fix HMC_ERR block present at 4dc9c884c0aaf^; arrays
aligned with enum
- [Phase 8] Failure mode: PF reset / RDMA+Ethernet teardown / IOMMU
faults, severity HIGH
- UNVERIFIED: datasheet-correctness of 0x00520400/0x00520500; public
Intel Acked-by beyond CC
The patch is small, matches long-standing i40e/ice behavior, and
prevents a real E810 reset storm that takes down RDMA and the PF.
**YES**
drivers/infiniband/hw/irdma/i40iw_hw.c | 4 +++-
drivers/infiniband/hw/irdma/icrdma_hw.c | 2 ++
drivers/infiniband/hw/irdma/icrdma_hw.h | 2 ++
drivers/infiniband/hw/irdma/icrdma_if.c | 8 ++++++--
drivers/infiniband/hw/irdma/irdma.h | 2 ++
5 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/i40iw_hw.c b/drivers/infiniband/hw/irdma/i40iw_hw.c
index 60c1f2b1811de..8301938b45432 100644
--- a/drivers/infiniband/hw/irdma/i40iw_hw.c
+++ b/drivers/infiniband/hw/irdma/i40iw_hw.c
@@ -29,7 +29,9 @@ static u32 i40iw_regs[IRDMA_MAX_REGS] = {
I40E_PFHMC_PDINV,
I40E_GLHMC_VFPDINV(0),
I40E_GLPE_CRITERR,
- 0xffffffff /* PFINT_RATEN not used in FPK */
+ 0xffffffff, /* PFINT_RATEN not used in FPK */
+ 0xffffffff, /* PFHMC_ERRORINFO not used in FPK */
+ 0xffffffff /* PFHMC_ERRORDATA not used in FPK */
};
static u32 i40iw_stat_offsets[] = {
diff --git a/drivers/infiniband/hw/irdma/icrdma_hw.c b/drivers/infiniband/hw/irdma/icrdma_hw.c
index 32f26284a788b..b1f1b54857626 100644
--- a/drivers/infiniband/hw/irdma/icrdma_hw.c
+++ b/drivers/infiniband/hw/irdma/icrdma_hw.c
@@ -29,6 +29,8 @@ static u32 icrdma_regs[IRDMA_MAX_REGS] = {
GLHMC_VFPDINV(0),
GLPE_CRITERR,
GLINT_RATE(0),
+ PFHMC_ERRORINFO,
+ PFHMC_ERRORDATA,
};
static u64 icrdma_masks[IRDMA_MAX_MASKS] = {
diff --git a/drivers/infiniband/hw/irdma/icrdma_hw.h b/drivers/infiniband/hw/irdma/icrdma_hw.h
index d97944ab45dac..0acdeda1236d1 100644
--- a/drivers/infiniband/hw/irdma/icrdma_hw.h
+++ b/drivers/infiniband/hw/irdma/icrdma_hw.h
@@ -40,6 +40,8 @@
#define GLHMC_VFPDINV(_i) (0x00528300 + ((_i) * 4)) /* _i=0...31 */
#define GLPE_CRITERR 0x00534000
#define GLINT_RATE(_INT) (0x0015A000 + ((_INT) * 4)) /* _i=0...2047 */ /* Reset Source: CORER */
+#define PFHMC_ERRORINFO 0x00520400
+#define PFHMC_ERRORDATA 0x00520500
#define ICRDMA_DB_ADDR_OFFSET (8 * 1024 * 1024 - 64 * 1024)
diff --git a/drivers/infiniband/hw/irdma/icrdma_if.c b/drivers/infiniband/hw/irdma/icrdma_if.c
index b49fd9cf24765..6c1d285d1c176 100644
--- a/drivers/infiniband/hw/irdma/icrdma_if.c
+++ b/drivers/infiniband/hw/irdma/icrdma_if.c
@@ -91,8 +91,12 @@ static void icrdma_iidc_event_handler(struct iidc_rdma_core_dev_info *cdev_info,
}
}
if (event->reg & IRDMAPFINT_OICR_HMC_ERR_M) {
- ibdev_err(&iwdev->ibdev, "HMC Error\n");
- iwdev->rf->reset = true;
+ u32 hmc_errinfo = readl(iwdev->rf->sc_dev.hw_regs[IRDMA_PFHMC_ERRORINFO]);
+ u32 hmc_errdata = readl(iwdev->rf->sc_dev.hw_regs[IRDMA_PFHMC_ERRORDATA]);
+
+ /* Log diagnostics; do not reset here. */
+ ibdev_warn(&iwdev->ibdev, "HMC Error: errinfo=0x%08x errdata=0x%08x\n",
+ hmc_errinfo, hmc_errdata);
}
if (event->reg & IRDMAPFINT_OICR_PE_PUSH_M) {
ibdev_err(&iwdev->ibdev, "PE Push Error\n");
diff --git a/drivers/infiniband/hw/irdma/irdma.h b/drivers/infiniband/hw/irdma/irdma.h
index ff938a01d70c4..e8cda27d78543 100644
--- a/drivers/infiniband/hw/irdma/irdma.h
+++ b/drivers/infiniband/hw/irdma/irdma.h
@@ -66,6 +66,8 @@ enum irdma_registers {
IRDMA_GLHMC_VFPDINV,
IRDMA_GLPE_CRITERR,
IRDMA_GLINT_RATE,
+ IRDMA_PFHMC_ERRORINFO,
+ IRDMA_PFHMC_ERRORDATA,
IRDMA_MAX_REGS, /* Must be last entry */
};
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] iommu/qcom: Enable clocks before hardware access in qcom_iommu_ctx_probe()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (4 preceding siblings ...)
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18] RDMA/irdma: Suppress PF reset on HMC error Sasha Levin
@ 2026-10-19 13:44 ` Sasha Levin
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-5.10] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context Sasha Levin
` (510 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Mukesh Ojha, Konrad Dybcio, Will Deacon, Sasha Levin, robin.clark,
joro, iommu, linux-arm-msm, linux-arm-kernel, linux-kernel
From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
[ Upstream commit cb776a03a53429aa59e25a8cbc3d1a48bd11afdb ]
qcom_iommu_ctx_probe() reads and writes the CB_FSR register to clear any
stale IRQ left by the bootloader. This happens during
devm_of_platform_populate() which is called from the parent device's
probe before any pm_runtime_get(). The parent's clocks (iface, bus, tbu)
are therefore not guaranteed to be on, making the register access
unreliable on rebind or after a suspend cycle.
Use pm_runtime_resume_and_get() on the parent device to ensure clocks
are enabled before the register access, and release the reference
immediately after.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Signed-off-by: Will Deacon <will@kernel.org>
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: **[iommu/qcom] [Enable] clocks before hardware access in
`qcom_iommu_ctx_probe()`**
“Enable” here is a missing power/clock step before MMIO, not a new
feature.
**Step 1.2: Tags**
Record:
- `Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>`
- `Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>` (author)
- `Signed-off-by: Will Deacon <will@kernel.org>` (IOMMU/SMMU maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Acked-by:`, `Link:`, or
`Cc: stable` (absence is expected)
**Step 1.3: Body**
Record:
- **Bug:** `qcom_iommu_ctx_probe()` reads/writes `CB_FSR` to clear a
stale bootloader IRQ during `devm_of_platform_populate()`, which runs
from the parent probe **before** any `pm_runtime_get()`. Parent clocks
(`iface`, `bus`, `tbu`) may be off.
- **Symptom:** Register access is **unreliable on rebind or after a
suspend cycle**.
- **Root cause:** Child MMIO without a runtime-PM resume of the parent
that actually enables the clocks.
- **Fix:** `pm_runtime_resume_and_get(dev->parent)` around the FSR
access, then `pm_runtime_put_sync()`.
- No stack trace, syzbot, or version range in the message.
**Step 1.4: Hidden bug fix?**
Record: Yes. The subject sounds like enablement, but this is a
correctness fix for MMIO with clocks gated.
---
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/iommu/arm/arm-smmu/qcom_iommu.c` (+6 / −1)
- Function: `qcom_iommu_ctx_probe()`
- Scope: single-file, surgical
**Step 2.2: Flow change**
Record: **Before:** if the context is not secure, immediately
`readl`/`writel` `ARM_SMMU_CB_FSR`. **After:** same access, but only
after a successful parent `pm_runtime_resume_and_get()`, then
`pm_runtime_put_sync()`. Resume failure fails probe. This is the child
probe path invoked from parent `devm_of_platform_populate()`.
**Step 2.3: Bug mechanism**
Record: **Hardware access / PM correctness.** Clocks are enabled only in
`qcom_iommu_resume()` via `clk_bulk_prepare_enable()`. Parent probe
order is `devm_pm_runtime_enable()` then `devm_of_platform_populate()` —
RPM enable does not turn clocks on. The parent already wraps its own
`SMMU_INTR_SEL_NS` write with resume/get; the child FSR access did not.
**Step 2.4: Fix quality**
Record: Obviously correct and matches the parent’s existing pattern.
`pm_runtime_resume_and_get()` drops the usage count on failure, so there
is no extra `put` needed. Regression risk is low: resume runs after
clocks/drvdata are set; multiple context banks each get/put
independently. No API or data-structure change.
---
## Phase 3: Git history
**Step 3.1: Blame**
Record: FSR-clear comment and access come from **`0ae349a0f33fb0`
(“iommu/qcom: Add qcom_iommu”, Rob Clark, 2017-08-09)**, first in
**v4.14-rc1**. Secure-ctx skip is from `e30c960d3f44b7` (2023). The bug
is old, not recent.
**Step 3.2: Fixes: tag**
Record: None. The introducing commit is `0ae349a0f33fb0`, present in
this tree (`git merge-base --is-ancestor` succeeded).
**Step 3.3: Related file history**
Record: Same-day series by Mukesh Ojha (v2 6/6 “Misc Fixes”):
1. `1f33b8208a197` inverted fault report
2. `bf69e515b1802` `devm_pm_runtime_enable()` (cleanup)
3. `e910315ae08a2` check RPM return on parent `SMMU_INTR_SEL_NS` write
4. `3c748a5554f96` pgtbl_ops leak
5. `a05b67cd45ad0` pgtbl_ops publish vs mutex
6. **this commit** `cb776a03a5342`
This patch does not need 2–5. It only uses
`pm_runtime_resume_and_get()`, present since `dd8088d5a8969`.
**Step 3.4: Author**
Record: Qualcomm engineer; series reviewed by Konrad Dybcio (Qualcomm)
and applied by Will Deacon. Not a drive-by.
**Step 3.5: Dependencies**
Record: Standalone. Applies to the pre-commit `ctx_probe` body in this
tree. No new helpers.
---
## Phase 4: Mailing list
**Step 4.1: Original discussion**
Record:
- Lore/msgid: https://patch.msgid.link/20260717144608.3216274-7-
mukesh.ojha@oss.qualcomm.com
- v1: `[PATCH 7/8]` 2026-06-23, same diff
- v2: `[PATCH v2 6/6]` 2026-07-17 (dropped unrelated 6/8 and 8/8)
- Cover: “Series to address fixes in legacy qcom_iommu driver”
- Konrad Reviewed-by on v1 7/8 with no requested changes; v2 unchanged
- Will: “Applied to iommu (arm/smmu/updates)”
- No NAK, no `Cc: stable` request
**Step 4.2: Recipients (`b4 dig -w`)**
Record: Will Deacon, Joerg Roedel, Robin Murphy, Rob Clark, Konrad
Dybcio, iommu@lists.linux.dev, linux-arm-msm, linux-arm-kernel.
**Step 4.3: Bug report**
Record: No external bugzilla/syzbot. Qualcomm-authored; trigger
described as rebind / post-suspend.
**Step 4.4: Series**
Record: Independent of the other five patches. Same pattern as patch 3/6
on the parent.
**Step 4.5: Stable list**
Record: **UNVERIFIED** — lore.kernel.org returned 403; no stable thread
in the saved mbox.
---
## Phase 5: Code semantics
**Step 5.1: Functions**
Record: `qcom_iommu_ctx_probe()` only.
**Step 5.2: Callers**
Record: Sole caller is `.probe = qcom_iommu_ctx_probe` on
`qcom_iommu_ctx_driver`. Invoked from `qcom_iommu_device_probe()` →
`devm_of_platform_populate()`. Device-init / bind path, not a syscall
hot path.
**Step 5.3: Callees**
Record: `pm_runtime_resume_and_get(parent)` → `qcom_iommu_resume()` →
`clk_bulk_prepare_enable()` (and optional `qcom_scm_restore_sec_cfg`);
then `iommu_readl`/`iommu_writel` `ARM_SMMU_CB_FSR`; then
`pm_runtime_put_sync()`.
**Step 5.4: Reachability**
Record: Yes, on every non-secure context probe for `qcom,msm-iommu-v1` /
`v2`. DT users include MSM8916/8917/8937/8939/8953/8976. First boot
often still has bootloader clocks; **rebind, deferred probe after
`clk_disable_unused`, and probe after suspend/remove** can have clocks
off. Unprivileged users do not trigger this directly; driver
bind/suspend does.
**Step 5.5: Similar patterns**
Record: Parent already does resume/get around `SMMU_INTR_SEL_NS`
(`e910315ae08a2`). This is the matching child-side hole.
---
## Phase 6: This checkout
**Step 6.1: Buggy code in this tree?**
Record: **Yes.** Tree is **v7.3-rc4** (`VERSION=7 PATCHLEVEL=3
SUBLEVEL=0 EXTRAVERSION=-rc4`, `git describe`:
`v7.3-rc4-27-gf0100363d8c37`). Driver and FSR-clear exist since v4.14.
Candidate `cb776a03a5342` is already an ancestor of HEAD (merged via
`iommu-updates-v7.3`, in v7.3-rc1). Pre-commit code still has the
unguarded FSR access.
**Step 6.2: Backport difficulty**
Record: Clean apply on this file’s `ctx_probe`. Needs
`linux/pm_runtime.h` (already included) and
`pm_runtime_resume_and_get()` (in this tree).
**Step 6.3: Related fixes already here**
Record: The candidate itself is already in this 7.3-rc4 tree. No
alternate FSR-clock fix besides this commit.
---
## Phase 7: Subsystem
**Step 7.1**
Record: **iommu / Qualcomm legacy SMMU** (`drivers/iommu/arm/arm-
smmu/qcom_iommu.c`). **IMPORTANT** for those SoCs (DMA/IOMMU), not core-
mm/VFS. `CONFIG_QCOM_IOMMU`, `depends on ARCH_QCOM`.
**Step 7.2**
Record: Mature “legacy qcom_iommu” driver; low churn except this 2026
fix series.
---
## Phase 8: Impact and risk
**Step 8.1: Who**
Record: Qualcomm MSM IOMMU v1/v2 platforms (older/mid-range SoCs still
in LTS images), not all machines.
**Step 8.2: Trigger**
Record: Child probe with parent clocks off: driver rebind, probe after
`pm_runtime_force_suspend` on remove, deferred probe after unused clocks
are gated. Not every boot. Not a userspace exploit path.
**Step 8.3: Failure mode**
Record: MMIO to a clock-gated SMMU context bank. On these platforms that
is typically a **bus timeout / NOC hang / SError**, or a failed FSR
clear so a bootloader IRQ fires as soon as `devm_request_irq()` runs.
Severity: **HIGH** (probe hang/abort), not a confirmed UAF/CVE.
**Step 8.4: Risk-benefit**
Record: **Benefit: medium-high** for affected hardware (prevents bad
MMIO during probe). **Risk: low** (6 lines, existing RPM API, same
pattern as parent). Ratio favors backport.
---
## Phase 9: Synthesis
**For:**
- Real bug: FSR MMIO before parent clocks are enabled; present since
v4.14.
- Can hang or fail IRQ clear on rebind / post-suspend / deferred probe.
- 6-line, obviously correct; reviewed by Konrad, applied by Will.
- Standalone; no new API.
- Same RPM wrap the parent already uses for `SMMU_INTR_SEL_NS`.
- Driver still used (MSM8916-class DT).
**Against:**
- No `Reported-by` / syzbot / crash log.
- Message says “unreliable”, not “panic”.
- Not a universal hot path.
- Lore stable search could not be fetched (403).
**Unresolved:** Exact production crash vs silent bad read on every SoC
variant — not verified beyond Qualcomm’s description.
**Stable rules:**
1. Obviously correct and tested? **PASS** (review + maintainer apply;
pattern already in-tree)
2. Real user-facing bug? **PASS** (clock-gated MMIO on probe/rebind)
3. Important (crash/hang/corruption)? **PASS** (HIGH: interconnect hang
/ SError / stale IOMMU IRQ)
4. Small and contained? **PASS** (6 lines, one function)
5. No new features/APIs? **PASS**
6. Applies to this tree? **PASS** (driver and RPM API present)
**Exception category:** none (not an ID/quirk/DT/build/doc add). It is a
normal small driver bugfix.
This tree is v7.3-rc4 and already contains `cb776a03a5342`; that is the
upstream commit, not a reason to reject on merit. The buggy FSR-without-
clocks path is in this driver and has been since v4.14. The fix is
small, local, and prevents a real probe-time hardware access failure on
Qualcomm IOMMU platforms.
### What it solves for stable users
Without the RPM get, context-bank probe can touch `CB_FSR` while
iface/bus/tbu clocks are off. That is the same class of bug the parent
already fixed for `SMMU_INTR_SEL_NS`. On rebind or after suspend/remove
(and on deferred probe after unused clocks are disabled), that access is
a hang or a missed IRQ clear, then a surprise fault IRQ.
### Risk vs benefit
Benefit is avoiding probe-time MMIO with clocks gated on still-shipping
MSM IOMMU v1/v2 boards. Risk is a few lines of standard
`resume_and_get`/`put_sync` around an existing register poke. No locking
or API change.
### Concerns
No public reproducer. Independent of the rest of the “Misc Fixes”
series. `pm_runtime_resume_and_get()` is already in this tree.
Verification:
- [Phase 1] Tags: Reviewed-by Konrad Dybcio; SOBs Mukesh Ojha, Will
Deacon; no Fixes/Reported-by/Cc-stable
- [Phase 2] Diff: +6/−1 in `qcom_iommu_ctx_probe()` wrapping FSR MMIO
with parent RPM get/put
- [Phase 3] Blame: FSR clear from `0ae349a0f33fb0` (v4.14-rc1); ancestor
of HEAD
- [Phase 3] Series mates `bf69e515b1802` / `e910315ae08a2` are not
prerequisites
- [Phase 3] `pm_runtime_resume_and_get` from `dd8088d5a8969`; ancestor
of HEAD
- [Phase 4] `b4 dig -c cb776a03a5342`: https://patch.msgid.link/20260717
144608.3216274-7-mukesh.ojha@oss.qualcomm.com
- [Phase 4] `b4 dig -a`: v1 7/8 identical diff; Konrad R-b; v2 applied
by Will; no NAK
- [Phase 4] Cover letter: “fixes in legacy qcom_iommu driver”
- [Phase 4] UNVERIFIED: lore.kernel.org/stable HTTP 403
- [Phase 5] Only caller: platform `.probe` via
`devm_of_platform_populate()` from parent probe
- [Phase 5] Resume path enables clocks in `qcom_iommu_resume()` →
`clk_bulk_prepare_enable()`
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4
- [Phase 6] `git merge-base --is-ancestor cb776a03a5342 HEAD` succeeded
(fix already in this 7.3 tree)
- [Phase 6] Pre-image of the commit still has unguarded
`iommu_writel`/`iommu_readl` on `ARM_SMMU_CB_FSR`
- [Phase 8] Failure mode: clock-gated SMMU MMIO → hang/SError or stale
fault IRQ; severity HIGH
- UNVERIFIED: no captured oops from a reporter
**YES**
drivers/iommu/arm/arm-smmu/qcom_iommu.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index fbe4bd3ec0c42..792585321bd11 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -704,8 +704,13 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev)
/* clear IRQs before registering fault handler, just in case the
* boot-loader left us a surprise:
*/
- if (!ctx->secured_ctx)
+ if (!ctx->secured_ctx) {
+ ret = pm_runtime_resume_and_get(dev->parent);
+ if (ret)
+ return ret;
iommu_writel(ctx, ARM_SMMU_CB_FSR, iommu_readl(ctx, ARM_SMMU_CB_FSR));
+ pm_runtime_put_sync(dev->parent);
+ }
ret = devm_request_irq(dev, irq,
qcom_iommu_fault,
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (5 preceding siblings ...)
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-6.6] iommu/qcom: Enable clocks before hardware access in qcom_iommu_ctx_probe() Sasha Levin
@ 2026-10-19 13:44 ` Sasha Levin
2026-10-19 14:07 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] libbpf: Skip bpf_object__probe_loading() when BPF token is in use Sasha Levin
` (509 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:44 UTC (permalink / raw)
To: patches, stable
Cc: Allison Henderson, Jakub Kicinski, Sasha Levin, davem, edumazet,
pabeni, netdev, linux-rdma, rds-devel, linux-kernel
From: Allison Henderson <achender@kernel.org>
[ Upstream commit d100966325f782aa7775e5f0e8fb04f66f56308e ]
rds_rdma_free_op() and rds_atomic_free_op() are reached from the IB
send completion path via
rds_ib_tasklet_fn_send()
rds_ib_send_cqe_handler()
rds_message_put()
rds_message_purge()
rds_rdma_free_op() / rds_atomic_free_op()
which runs in tasklet (softirq) context. Both functions unpin the
user pages of the op with unpin_user_pages_dirty_lock(), which uses
set_page_dirty_lock() and thus may take the folio lock and sleep.
Sleeping in softirq context is not allowed and can deadlock or crash.
Dirtying the pages with the non-sleeping set_page_dirty() instead
would just trade one bug for another, as pointed out during review:
the pinned range can be file-backed. rds_pin_pages() pins with
FOLL_LONGTERM, which refuses fs-dax but takes the page-cache pages
of a MAP_SHARED file mapping just fine, and RDS does not restrict
what memory the caller registers as an RDMA destination.
For a file-backed page, set_page_dirty() from a tasklet can take
non-irq-safe filesystem locks (e.g. mapping->i_private_lock and
inode->i_lock in block_dirty_folio()) and deadlock against the task
it interrupted. Without the folio lock, it races with truncation
clearing folio->mapping, which is the race set_page_dirty_lock()
exists to close. The pre-pin_user_pages() version of this code
dirtied pages that way from the tasklet, so that bug is older than
the sleeping unpin.
The page dirtying therefore has to move to process context, not
merely avoid the folio lock. When the final rds_message_put() runs
in atomic context, rds_rdma_free_op() and rds_atomic_free_op() now
leave the op's pages pinned and flag the op. Later, rds_message_put()
hands the message to a work item that unpins the flagged ops' pages
and frees the message from process context. Here,
unpin_user_pages_dirty_lock() is safe outside the atomic context.
Everything else keeps running in the caller's context exactly as
before: the rest of the purge - the zerocopy completion, the socket
put and the MR reference drops - as well as RDMA writes, whose pages
the remote side only reads and which unpin without dirtying,
everything on rds_tcp, and final puts that already happen in process
context (socket close, connection teardown).
Deferring only the unpin means the work item touches nothing but the
pinned pages and the rds module's own memory: it cannot call back
into a transport module, so it changes nothing about the transports'
shutdown and unload ordering. rds_exit() drains any pending unpin
work via destroy_workqueue(rds_wq) before the module goes away.
The Oracle UEK kernel avoids the sleeping unpin by calling
set_page_dirty() directly from the tasklet, which is subject to the
file-backed page problem above, so this deliberately does not follow
UEK here.
Signed-off-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20260730041629.3512480-2-achender@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a real sleep-in-softirq bug on the RDS IB completion path, and
the buggy code is present in this 5.10.270 tree. The fix is self-
contained and should be backported.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [net/rds] [don't use] don't call `unpin_user_pages_dirty_lock()`
from atomic/softirq context. "don't use" is a prevent/avoid-style fix.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Allison Henderson `<achender@kernel.org>` (author;
ignore pipeline SOB)
- Signed-off-by: Jakub Kicinski `<kuba@kernel.org>` (netdev maintainer)
- Link: `https://patch.msgid.link/20260730041629.3512480-2-
achender@kernel.org`
- No Reported-by, Tested-by, Reviewed-by, Acked-by, or Cc: stable in the
provided message
- Mailing-list v4 **did** include `Fixes: 0d4597c8c5ab ("net/rds: Track
user mapped pages through special API")`; that tag is in this tree
(verified with `git merge-base --is-ancestor`)
- Message-ID `-2` is patch 1/4 of `[PATCH net v4 0/4] net/rds: Bug fix
ports` (cover letter is `-1`)
- Assisted-by Claude appears on the lore submission only
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: `rds_rdma_free_op()` / `rds_atomic_free_op()` run from the IB
send tasklet and call `unpin_user_pages_dirty_lock()`, which uses
`set_page_dirty_lock()` → `lock_page()`, which may sleep.
- Symptom: sleep in softirq → deadlock or crash.
- Switching to `set_page_dirty()` from the tasklet is also wrong for
file-backed pins (`FOLL_LONGTERM` MAP_SHARED): non-irq-safe fs locks
and truncation races.
- Fix: if the final put is atomic and pages need dirtying, leave them
pinned, set `op_unpin_deferred`, and finish unpin+free on `rds_wq`.
- Author notes this is older than the pin API (pre-pin code already
dirtied from the tasklet) and that UEK’s `set_page_dirty()`-from-
tasklet approach is intentionally not followed.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not hidden. Explicit sleep-in-atomic / deadlock fix.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- `net/rds/message.c`: add `rds_message_unpin_worker()`, defer `kfree`
from `rds_message_put()` when unpin was deferred
- `net/rds/rdma.c`: split unpin helpers; `rds_rdma_free_op()` /
`rds_atomic_free_op()` unpin inline only when safe (`in_task()` or
RDMA write)
- `net/rds/rds.h`: `m_unpin_work`, `op_unpin_deferred` bitfields, helper
prototypes
- Scope: ~74 insertions / 11 deletions, three RDS files, surgical
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: final `rds_message_put()` always purges and unpins (possibly
dirtying) in the caller’s context, including the send CQ tasklet.
- After: purge still runs in the caller (zerocopy, sock_put, MR krefs).
Dirtying unpin is deferred to process context. RDMA writes still unpin
immediately (no dirty). Process-context final puts still unpin
immediately.
- Error path `rds_cmsg_rdma_args()` → `rds_rdma_free_op()` is
sendmsg/process context, so `in_task()` is true and pages are not
leaked.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [Deadlock / sleep-in-atomic] `lock_page()` from tasklet/softirq.
Workqueue deferral is the correct class of fix; dirtying cannot stay in
the tasklet.
Step 2.4: ASSESS THE FIX QUALITY
Record: v4 is the review-hardened design (v1 used `set_page_dirty()` in
the tasklet; v2/v3 deferred the whole purge and needed extra IB-module
flushes). Risk is the usual workqueue lifetime issues; mitigated because
the worker only unpins pages and `kfree`s the message, and `rds_exit()`
→ `rds_threads_exit()` → `destroy_workqueue(rds_wq)` drains it. Messages
are `kzalloc`’d, so new flags/work_struct start zeroed.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Sleeping unpin: `0d4597c8c5abd` ("net/rds: Track user mapped pages
through special API", Leon Romanovsky, 2020) — **in this tree**
- Call from tasklet: `rds_rdma_free_op` / `rds_message_put` date to
2009–2010 (Andy Grover)
- Pre-pin code already dirtied from this path
Step 3.2: FOLLOW THE FIXES: TAG
Record: `0d4597c8c5ab` is an ancestor of HEAD (`git merge-base --is-
ancestor` exit 0). No later in-tree substitute for this unpin-from-
tasklet bug. `338a3ba30c5ef` ("net:rds: Fix possible deadlock in
rds_message_put") is a different lock-order bug in `recv.c`.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Recent `net/rds/` work here is unrelated (zerocopy, MR cleanup,
tcp corruption). This is standalone, not patch 2-of-N that needs earlier
series members.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Allison Henderson is a long-time RDS contributor; this tree
already has several of her RDS fixes. Author is the right subsystem
person.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Series mates (socket ref on MR, send_xmit leak, MR teardown
unpin) are independent bugs. Needed APIs exist here: `in_task()`,
`unpin_user_pages_dirty_lock()`, `rds_wq`, `pin_user_pages_fast()` +
`FOLL_LONGTERM`. No missing helpers.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 mbox` on msgid `20260730041629.3512480-2-achender@kernel.org`:
8-message thread
- Lore/WebFetch of lore.kernel.org and patch.msgid.link returned 403;
discussion recovered via b4 + openwall
- Revisions: v1 2026-07-11, v2 2026-07-25, v3 2026-07-26, v4 2026-07-29
(applied)
- v1 NAK’d conceptually: `set_page_dirty()` from softirq can deadlock on
fs locks and race truncation
- v3 extra `rds_ib_exit()` flushes dropped in v4 by deferring only unpin
- Applied to netdev/net-next as `d100966325f7` (not this tree)
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: To/Cc included netdev, linux-rdma, Kicinski, Abeni, Dumazet,
Horms. No subsystem Reviewed-by on v4. Kicinski: “I don't have much
confidence in my ability to review this, so let's queue this for -next.”
Author agreed they are old, non-simple bugs.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla in the thread. Motivation is code analysis +
UEK carrying a related (weaker) fix. Oracle RDS/IB users are the
affected population.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: 4-patch “Bug fix ports” series. This patch is 1/4 and does not
depend on 2–4. Patch 4 is a separate pin-vs-put_page leak in
`__rds_ib_teardown_mr()`.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No useful hit on lore.kernel.org/stable for this subject (search
was noisy/unrelated). Originally aimed at `net` because of Fixes:; moved
to net-next. Absence of stable-list discussion is not a NAK.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `rds_message_unpin_worker` (new), `rds_message_put`,
`rds_rdma_op_unpin_pages` (new), `rds_rdma_free_op`,
`rds_atomic_op_unpin_page` (new), `rds_atomic_free_op`
Step 5.2: TRACE CALLERS
Record:
- `rds_message_put()`: send.c, ib_send.c, ib_cm.c, message.c, loop.c,
connection.c
- Confirmed atomic path: `rds_ib_tasklet_fn_send()` → `poll_scq()` →
`rds_ib_send_cqe_handler()` → `rds_message_put()` (`net/rds/ib_cm.c`,
`ib_send.c`)
- `rds_rdma_free_op()`: `rds_message_purge()` and `rds_cmsg_rdma_args()`
error path (process context)
- `rds_atomic_free_op()`: only `rds_message_purge()`
Step 5.3: TRACE CALLEES
Record: `unpin_user_pages_dirty_lock()` → `set_page_dirty_lock()` →
`lock_page()` (sleeping). Non-dirty path uses `unpin_user_pages()` only.
Worker uses `queue_work(rds_wq)` / `kfree`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace `sendmsg` with `RDS_CMSG_RDMA_ARGS` / atomic cmsg → IB
RDMA READ or atomic WR → CQ completion in tasklet → final put. Reachable
from sockets if `CONFIG_RDS_RDMA`. Not a theoretical path.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Local `__rds_ib_teardown_mr()` still does `set_page_dirty()` +
`put_page()` (series patch 4). `rds_info.c` unpins from getsockopt
(process context) — OK. Same class of bug is already treated as
backport-worthy in this tree (`88fdf5948f538` Don't sleep inside
`rds_ib_conn_path_shutdown`).
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. This checkout is **5.10.270** (`pending-5.10`, `git
describe` `p-5.10-1-gce56b7a73b64b`).
- `net/rds/rdma.c:500` and `:517` call `unpin_user_pages_dirty_lock()`
- `rds_ib_tasklet_fn_send` still a tasklet
- `rds_pin_pages()` uses `FOLL_LONGTERM`
- Introduced by `0d4597c8c5ab` (v5.7-era), present on this branch
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Semantic apply is straightforward. `rdma.c` / `rds.h` match the
old side of the diff. `message.c` context after `rds_message_put()`
still assigns `hdr->h_exthdr[0]` instead of `memset` of the ext header —
**minor context conflict**, not a rework. `work_struct` / `queue_work` /
`in_task()` are available (`rds.h` → `sock.h` → `netdevice.h` →
`workqueue.h`; `hardirq.h` → `preempt.h`). `rds_wq` is destroyed on
module exit.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No equivalent deferred-unpin fix. `338a3ba30c5ef` is a different
deadlock.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [net/rds] IMPORTANT for RDS-over-IB (Oracle RAC / HPC). Not core
networking; production users of 5.10 LTS do run this.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature. Core free/put path has been stable for years; this is a
long-standing latent bug, not churn on new code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Config-specific / driver-specific: `CONFIG_RDS` +
`CONFIG_RDS_RDMA`, IB completions of RDMA READ / atomic ops against
pinned user memory (including MAP_SHARED file pages).
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Common on RDS RDMA READ completion. Timing-dependent on folio
already locked (writeback). Unprivileged user with an RDS socket and
registered memory can hit it. Not every boot.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Sleep in softirq / `lock_page()` from tasklet → deadlock or
crash. **CRITICAL**. File-backed `set_page_dirty()` alternative would
also be CRITICAL (fs lock deadlock / mapping UAF).
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: high for RDS/IB users (prevents deadlock/oops on a real
completion path)
- Risk: low–medium (workqueue deferral, ~70 lines, one subsystem; worker
does not call into the IB module)
- Ratio: benefit outweighs risk. Larger than a 5-line NULL check, but
the pattern is standard and v4 was specifically reduced to avoid
unload races.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Sleep in softirq is a real, important bug
- Path exists on this 5.10 tree and is userspace-reachable via RDS RDMA
- Fixes target `0d4597c8c5ab` is in the tree
- Small, RDS-only, no new uAPI
- Needed kernel APIs exist
- v4 design addresses earlier review NAKs
- `destroy_workqueue(rds_wq)` drains deferred work
- RDS maintainer-authored; netdev applied it upstream
AGAINST:
- ~70 lines and a new work item (not a one-liner)
- Queued to net-next; Kicinski was uneasy reviewing it
- No syzbot/Tested-by on the committed message
- Trivial `message.c` context tweak for `rds_message_populate_header()`
UNRESOLVED:
- Could not fetch lore.kernel.org in-browser (403); used b4 mbox instead
- No evidence of a later revert or follow-up for `d100966325f7` (search
did not turn one up)
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — v4 is the review-fixed
design; mechanism matches the bug. (Confidence is “good”, not
“trivial one-liner”.)
2. Fixes a real bug that affects users? **PASS**
3. Important issue? **PASS** — deadlock/crash, CRITICAL
4. Small and contained? **PASS** — 3 files, RDS only
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — code present; at most a minor
context adjustment
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID/quirk/DT/build/docs exception). Qualifies
as a normal important bugfix.
Step 9.4: MAKE YOUR DECISION
This tree still unpins and dirties RDMA/atomic pages in the IB send
tasklet. That can sleep. Deferring only that unpin onto existing
`rds_wq` is the right fix here and does not need the rest of the v4
series.
What it solves for 5.10 users: RDS-over-InfiniBand RDMA READ/atomic
completion can call `lock_page()` in softirq, which can deadlock or
crash. That is exactly the class of bug stable is for.
Risk vs benefit: contained RDS change, process-context unpin, workqueue
drained on unload. Benefit is preventing a serious completion-path
failure.
Concerns: expect a small `message.c` context edit around
`rds_message_populate_header()`; do not pull series patches 2–4 as
prerequisites.
Verification:
- [Phase 1] Tags: SOB Henderson/Kicinski; Link msgid; lore v4 had Fixes:
0d4597c8c5ab
- [Phase 2] Diff: defer dirtying unpin via work item; RDMA write still
unpins in caller
- [Phase 3] `git describe` / Makefile: 5.10.270; blame unpin lines →
0d4597c8c5ab; ancestor check exit 0
- [Phase 3] `338a3ba30c5ef` is a different recv.c deadlock
- [Phase 4] `b4 mbox`: 8 msgs, v1–v4, applied as d100966325f7; Kicinski
queued net-next
- [Phase 4] WebFetch lore/msgid.link: 403; discussion from b4 + openwall
- [Phase 5] Call chain verified in ib_cm.c / ib_send.c;
`set_page_dirty_lock()` uses `lock_page()` in mm/page-writeback.c
- [Phase 5] Other `rds_rdma_free_op()` caller is process-context error
path in rdma.c:796
- [Phase 6] Local rdma.c still has sleeping unpin; `in_task()` and
`rds_wq` exist; messages kzalloc’d
- [Phase 6] Header context differs (`h_exthdr[0]` vs memset) — minor
backport
- [Phase 8] Failure mode: sleep-in-softirq / deadlock, CRITICAL
- UNVERIFIED: live lore HTML; no later revert found
**YES**
net/rds/message.c | 26 +++++++++++++++++++++++++
net/rds/rdma.c | 49 ++++++++++++++++++++++++++++++++++++-----------
net/rds/rds.h | 10 ++++++++++
3 files changed, 74 insertions(+), 11 deletions(-)
diff --git a/net/rds/message.c b/net/rds/message.c
index 19202aa33f6f4..bdd340f4cce65 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -180,6 +180,19 @@ static void rds_message_purge(struct rds_message *rm)
kref_put(&rm->atomic.op_rdma_mr->r_kref, __rds_put_mr_final);
}
+static void rds_message_unpin_worker(struct work_struct *work)
+{
+ struct rds_message *rm = container_of(work, struct rds_message,
+ m_unpin_work);
+
+ if (rm->rdma.op_unpin_deferred)
+ rds_rdma_op_unpin_pages(&rm->rdma);
+ if (rm->atomic.op_unpin_deferred)
+ rds_atomic_op_unpin_page(&rm->atomic);
+
+ kfree(rm);
+}
+
void rds_message_put(struct rds_message *rm)
{
rdsdebug("put rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
@@ -187,8 +200,21 @@ void rds_message_put(struct rds_message *rm)
if (refcount_dec_and_test(&rm->m_refcount)) {
BUG_ON(!list_empty(&rm->m_sock_item));
BUG_ON(!list_empty(&rm->m_conn_item));
+
rds_message_purge(rm);
+ /* A final put in atomic context cannot dirty the ops'
+ * user pages on unpin, so rds_rdma_free_op() and
+ * rds_atomic_free_op() deferred it. Finish the unpin,
+ * and the free, from process context.
+ */
+ if (rm->rdma.op_unpin_deferred ||
+ rm->atomic.op_unpin_deferred) {
+ INIT_WORK(&rm->m_unpin_work, rds_message_unpin_worker);
+ queue_work(rds_wq, &rm->m_unpin_work);
+ return;
+ }
+
kfree(rm);
}
}
diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index 34d9333e4229f..37695056756be 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -483,22 +483,36 @@ void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force)
kref_put(&mr->r_kref, __rds_put_mr_final);
}
-void rds_rdma_free_op(struct rm_rdma_op *ro)
+void rds_rdma_op_unpin_pages(struct rm_rdma_op *ro)
{
unsigned int i;
+ for (i = 0; i < ro->op_nents; i++) {
+ struct page *page = sg_page(&ro->op_sg[i]);
+
+ /* Mark page dirty if it was possibly modified, which
+ * is the case for a RDMA_READ which copies from remote
+ * to local memory
+ */
+ unpin_user_pages_dirty_lock(&page, 1, !ro->op_write);
+ }
+}
+
+void rds_rdma_free_op(struct rm_rdma_op *ro)
+{
if (ro->op_odp_mr) {
kref_put(&ro->op_odp_mr->r_kref, __rds_put_mr_final);
+ } else if (in_task() || ro->op_write) {
+ /* An RDMA write's pages are only read by the remote
+ * side; unpinning without dirtying does not sleep.
+ */
+ rds_rdma_op_unpin_pages(ro);
} else {
- for (i = 0; i < ro->op_nents; i++) {
- struct page *page = sg_page(&ro->op_sg[i]);
-
- /* Mark page dirty if it was possibly modified, which
- * is the case for a RDMA_READ which copies from remote
- * to local memory
- */
- unpin_user_pages_dirty_lock(&page, 1, !ro->op_write);
- }
+ /* Dirtying the pages on unpin can sleep; leave them
+ * pinned and have rds_message_put() finish the unpin
+ * from process context.
+ */
+ ro->op_unpin_deferred = 1;
}
kfree(ro->op_notifier);
@@ -507,7 +521,7 @@ void rds_rdma_free_op(struct rm_rdma_op *ro)
ro->op_odp_mr = NULL;
}
-void rds_atomic_free_op(struct rm_atomic_op *ao)
+void rds_atomic_op_unpin_page(struct rm_atomic_op *ao)
{
struct page *page = sg_page(ao->op_sg);
@@ -515,6 +529,19 @@ void rds_atomic_free_op(struct rm_atomic_op *ao)
* is the case for a RDMA_READ which copies from remote
* to local memory */
unpin_user_pages_dirty_lock(&page, 1, true);
+}
+
+void rds_atomic_free_op(struct rm_atomic_op *ao)
+{
+ if (in_task()) {
+ rds_atomic_op_unpin_page(ao);
+ } else {
+ /* Dirtying the page on unpin can sleep; leave it
+ * pinned and have rds_message_put() finish the unpin
+ * from process context.
+ */
+ ao->op_unpin_deferred = 1;
+ }
kfree(ao->op_notifier);
ao->op_notifier = NULL;
diff --git a/net/rds/rds.h b/net/rds/rds.h
index a029e5fcdea72..a4816da162930 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -424,6 +424,12 @@ struct rds_message {
void *m_final_op;
+ /* Unpins the ops' user pages and frees the message from
+ * process context when the final put happens in atomic
+ * context: dirtying the pages on unpin can sleep.
+ */
+ struct work_struct m_unpin_work;
+
struct {
struct rm_atomic_op {
int op_type;
@@ -447,6 +453,7 @@ struct rds_message {
unsigned int op_mapped:1;
unsigned int op_silent:1;
unsigned int op_active:1;
+ unsigned int op_unpin_deferred:1;
struct scatterlist *op_sg;
struct rds_notifier *op_notifier;
@@ -462,6 +469,7 @@ struct rds_message {
unsigned int op_mapped:1;
unsigned int op_silent:1;
unsigned int op_active:1;
+ unsigned int op_unpin_deferred:1;
unsigned int op_bytes;
unsigned int op_nents;
unsigned int op_count;
@@ -938,6 +946,8 @@ int rds_cmsg_rdma_map(struct rds_sock *rs, struct rds_message *rm,
struct cmsghdr *cmsg);
void rds_rdma_free_op(struct rm_rdma_op *ro);
void rds_atomic_free_op(struct rm_atomic_op *ao);
+void rds_rdma_op_unpin_pages(struct rm_rdma_op *ro);
+void rds_atomic_op_unpin_page(struct rm_atomic_op *ao);
void rds_rdma_send_complete(struct rds_message *rm, int wc_status);
void rds_atomic_send_complete(struct rds_message *rm, int wc_status);
int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (6 preceding siblings ...)
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-5.10] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: skip fallocate for SMB2_CREATE_ALLOCATION_SIZE on a stream handle Sasha Levin
` (508 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Yuan Chen, Andrii Nakryiko, Sasha Levin, eddyz87, ast, daniel,
memxor, bpf, linux-kernel
From: Yuan Chen <chenyuan@kylinos.cn>
[ Upstream commit d262a25d8b58b697b2a1a2fe4b0078446cc00e11 ]
bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
TRACEPOINT programs to verify the BPF environment works. When a
BPF token is in use with restricted program type permissions, these
probe loads may fail because the token does not allow the specific
program types, even though BPF loading is perfectly functional.
Fix by skipping the probe when a token FD is present: BPF token
creation itself proves the kernel has a working BPF subsystem.
Real BPF issues will be caught during actual program and map loading.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260610145059.113412-2-chenyuan_fl@163.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a real libbpf load-path bug in this 6.18 tree: restricted BPF
tokens make `bpf_object__probe_loading()` fail even when the actual
programs would load. The change is small, already present in the
matching 6.18 code, and is worth backporting.
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: `[libbpf] [Skip] Skip bpf_object__probe_loading() when BPF
token is in use`
- Subsystem: `libbpf` (userspace library in `tools/lib/bpf/`)
- Verb “Skip” is a workaround/fix for a false-negative probe, not a
feature.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- `Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>` (author)
- `Signed-off-by: Andrii Nakryiko <andrii@kernel.org>` (libbpf/BPF
maintainer)
- `Link: https://lore.kernel.org/bpf/20260610145059.113412-2-
chenyuan_fl@163.com`
- No `Fixes:`, `Reported-by`, `Tested-by`, `Reviewed-by`, `Acked-by`,
or `Cc: stable` in the committed message (absence of Fixes/Cc-stable
is expected here)
- Mailing-list review did include `Acked-by: Mykyta Yatsenko
<yatsenko@meta.com>` (not copied into the final commit text)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record:
- **Bug:** `bpf_object__probe_loading()` loads dummy `SOCKET_FILTER`
and `TRACEPOINT` programs. With a BPF token whose allowed program
types exclude those, the probe fails even though real loads would
work.
- **Symptom:** `bpf_object__load()` / `bpf_object__prepare()` returns
an error and warns that BPF/RLIMIT_MEMLOCK is broken. In-tree token
selftests (`obj_priv_map`, `obj_priv_prog`, freplace, implicit-
token, struct_ops BTF cases) hit this.
- **Cover letter (v3):** same probe can also drop the token path and
then break later loads (struct_ops + global data: `fd X is not
pointing to valid bpf_map`).
- **Root cause:** probe uses hardcoded program types and passes
`obj->token_fd`.
- **Fix:** skip the probe when `token_fd` is set; creating the token
already proves BPF syscalls work.
- **Versions:** no version list in the message. BPF tokens exist since
~6.9; this 6.18 tree has them.
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: Not a disguised cleanup. It is an explicit functional fix for
a false probe failure. Skipping the probe is the fix, not a refactor.
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- Record:
- File: `tools/lib/bpf/libbpf.c` — 3 insertions, 7 deletions
- Function: `bpf_object__probe_loading()`
- Scope: single-file surgical change
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record:
- **Before:** After `bpf_object_prepare_token()`, probe always runs
(except `gen_loader`). It passes `token_fd` / `BPF_F_TOKEN_FD` into
dummy `SOCKET_FILTER` then `TRACEPOINT` loads. Either failure aborts
object prepare/load.
- **After:** If `obj->token_fd` is set, return 0 immediately (same as
`gen_loader`). Dummy loads no longer use token opts (`NULL` opts).
- **Path:** initialization/prepare of every `bpf_object` load, not a
rare error path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record:
- **Category:** logic/correctness (false failure in a capability
probe)
- **Mechanism:** probe assumes `SOCKET_FILTER` or `TRACEPOINT` is
allowed. Restricted tokens are the whole point of BPF token
delegation. Probe failure is treated as “BPF is unavailable,” so
legitimate objects never load.
- Not UAF/leak/race/overflow.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record:
- Obviously correct: token creation already used `bpf_token_create()`.
Real map/prog errors still happen in the real load path.
- Minimal: one extra skip condition; dummy loads drop unused token
opts.
- `bpf_prog_load(..., NULL)` is valid: `OPTS_VALID` treats NULL as OK;
`OPTS_GET` falls back to 0. Same as empty opts when `token_fd == 0`.
- Regression risk is low. Skipping `bump_rlimit_memlock()` in this
function is fine: `bpf_prog_load()` still calls it, and tokens imply
6.9+ with memcg BPF accounting.
- Residual gap: series patch 2 (feature probes using hardcoded types)
is **not** in this tree. This patch still stands alone for the
probe_loading hard-fail.
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Record:
- Probe itself: Stanislav Fomichev, 2018 (`47eff61777c7`).
- Token opts in the probe: `6b434b61b4d9e` (“libbpf: Wire up BPF token
support at BPF object level”), Andrii Nakryiko, 2024-01-23 (kernel
~6.9).
- Buggy pattern has been in this 6.18 line since the branch, not a
post-6.18 introduction.
**Step 3.2: FOLLOW THE FIXES: TAG**
- Record: No `Fixes:` tag (Mykyta asked for one; it was never added).
The introducing commit is `6b434b61b4d9e`, which **is** in this tree
(`git merge-base --is-ancestor` succeeded).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
- Record:
- `f9bceaa59c5c4` already skips this probe for light skeleton
(`gen_loader`); this patch extends that idea to tokens.
- `1315c28ed8095` split load into `bpf_object__prepare()` / load;
probe now runs from `bpf_object_prepare()`.
- Series patch 2 (“fetch probeable prog type from token”) is **not**
in this tree.
- Standalone: Andrii said this was the only v2 patch that should land
on its own.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
- Record: Yuan Chen has another libbpf fix here (`aa485e8789d56`, NULL
deref in `btf_dump__free`). Not the libbpf maintainer. Applied by
Andrii Nakryiko.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
- Record: Needs `obj->token_fd` and `bpf_object__probe_loading()`, both
present. No new helpers. Applies standalone. Patch 2 is a related but
separate feature-probe issue.
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record:
- `b4 dig -c d262a25d8b58`:
https://patch.msgid.link/20260610145059.113412-2-chenyuan_fl@163.com
- Revisions:
- v1 (2026-05-29): selftest workaround — add
SOCKET_FILTER/TRACEPOINT to token tests
- v2 (2026-06-04): 3 patches; this skip plus selftest ARRAY map plus
feature-probe skip
- `[PATCH bpf]` (2026-06-09): this patch alone after Andrii asked to
resend it
- v3 (2026-06-10): 2 patches; this skip plus smarter feature probes
— **this is what landed**
- Review:
- Mykyta: skip is correct; making the probe token-aware would be
worse. `Acked-by`.
- Andrii: this is the only v2 patch that should apply; resend it
alone.
- Mykyta on the bpf-tree resend: retarget **bpf-next**, add a Fixes
tag, include Acks. No NAK.
- No reviewer `Cc: stable`. bpf-next targeting is a process note, not
a statement that the bug is absent from 6.18.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
- Record: Recipients included Andrii Nakryiko, Alexei Starovoitov,
Daniel Borkmann, Eduard Zingerman, Mykyta Yatsenko,
`bpf@vger.kernel.org`. Right maintainers. Applied by Andrii.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: No syzbot/bugzilla. Trigger is in-tree
`tools/testing/selftests/bpf/prog_tests/token.c`: `obj_priv_map`
(QUEUE map only), `obj_priv_prog` (XDP only), freplace, implicit-token
struct_ops. Author hit failing tests; v1 tried widening token
permissions instead of fixing libbpf.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
- Record: v3 2/2 is the feature-probe follow-up (`features.c`). Not
required for this skip to be correct. Not in this tree.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
- Record: lore.kernel.org/stable search returned HTTP 403. UNVERIFIED
whether stable@ discussed this. No in-tree evidence of a prior
rejection.
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
- Record: `bpf_object__probe_loading()` only.
**Step 5.2: TRACE CALLERS**
- Record: Single caller, `bpf_object_prepare()` (`libbpf.c` ~8705),
which is called from:
- `bpf_object_load()` if state `< OBJ_PREPARED`
- public `bpf_object__prepare()`
- Every normal `bpf_object__load()` / skeleton load goes through this
after token setup.
**Step 5.3: TRACE CALLEES**
- Record: `bump_rlimit_memlock()`, `bpf_prog_load()`, `close()`,
`pr_warn()`. After the skip, those are not used when a token is
present.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: Userspace, reachable from any app using in-tree
libbpf/bpftool/selftests with a BPF token (explicit `bpf_token_path`
or implicit `/sys/fs/bpf`). Not a kernel oops path. Unprivileged user-
namespace workloads with delegated tokens are the intended users.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
- Record: Same skip already exists for `obj->gen_loader`.
`tools/lib/bpf/features.c` still hardcodes probe program types with
`token_fd` — that is series patch 2, still open in this tree.
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
- Record:
- Local tree: `v6.18.53` (`Makefile` 6.18.53, `git describe HEAD` =
`v6.18.53-5049-g0f0bdc2b0dffb`), branch `autosel`.
- `v6.18:tools/lib/bpf/libbpf.c` has the pre-fix probe: token opts +
`SOCKET_FILTER`/`TRACEPOINT`.
- Pre-fix hunk md5 matches `v6.18` exactly.
- Kernel BPF token (`kernel/bpf/token.c`, `35f96de04127d`) is in 6.18.
- Bug introduced ~6.9 (`6b434b61b4d9e`), well before 6.18.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
- Record: Clean apply. Context around `bpf_object__probe_loading()`
matches 6.18. No refactor in the way.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
- Record: No other skip of this probe for tokens. No equivalent feature-
probe fix. Token selftests still omit SOCKET_FILTER/TRACEPOINT for
`obj_priv_*`, so they still depend on this libbpf change.
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
- Record: `tools/lib/bpf` — IMPORTANT, not CORE kernel. Used by bpftool,
selftests, and distro in-tree libbpf. BPF tokens are the supported
unprivileged/container path.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
- Record: Active (recent libbpf mmap/percpu/relocation fixes). Token
wiring itself has been stable since 6.9; this is a late correctness
fix, not churn in brand-new code.
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
- Record: Config/driver-specific in the BPF-token sense: users of libbpf
object load with a token whose allowed types exclude SOCKET_FILTER
**and** TRACEPOINT. That includes the in-tree token selftests and
container/user-ns setups that delegate only XDP, struct_ops, maps,
etc.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
- Record: Trigger is common for token users: every
`bpf_object__load()`/`prepare()`. Not a race. Unprivileged tasks in a
delegated user ns can hit it; that is the token design.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
- Record: Object load/prepare fails outright with a misleading “Couldn't
load trivial BPF program” warning. Not a kernel oops/corruption.
**Severity: MEDIUM-HIGH** for token users (feature completely
unusable), **LOW** for everyone else (`token_fd == 0` path is
unchanged).
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
- Record:
- **Benefit:** Restricted-token libbpf loads work; in-tree token tests
can pass; matches the token least-privilege model.
- **Risk:** Very low (net −4 lines, one extra early return).
- **Ratio:** Strongly favorable for 6.18.
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real, reproducible false failure on every object load with a
restricted token
- In-tree selftests exercise exactly this (XDP-only, map-only,
struct_ops-only tokens)
- Buggy code is in 6.18; tokens are in 6.18
- 10-line, obviously correct skip; same pattern as `gen_loader`
- Acked by Mykyta Yatsenko; applied by Andrii Nakryiko
- Clean apply; no new API
- Andrii treated this patch as independently landable
AGAINST:
- Userspace libbpf, not a kernel oops/UAF/deadlock
- No `Cc: stable`; reviewers asked for bpf-next (process, not “bug
absent from 6.18”)
- Series patch 2 (feature probes) is still missing; some
struct_ops+global-data cases may still fail
- Specialized to BPF token users, not all machines
UNRESOLVED:
- Stable@ thread search failed (HTTP 403)
- Cover-letter claim that a failed probe “drops the token reference” in
the kernel was not independently verified; the libbpf-level hard-fail
is verified from code and tests
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — skip is the same idea as
`gen_loader`; reviewed/acked; tests exist
2. Fixes a real bug that affects users? **PASS** — object load fails for
valid token configs
3. Important issue? **PASS** (MEDIUM-HIGH for token users) — complete
load failure, not theoretical; fits “oh, that's not good”
4. Small and contained? **PASS** — 3/7 lines, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — 6.18 source matches the pre-
image
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
- Record: None (not a device ID, quirk, DT, build, or docs fix).
Qualifies as a normal small bugfix.
**Step 9.4: DECISION**
6.18 ships BPF tokens and this probe. Without the skip, libbpf treats a
least-privilege token as “BPF does not work” and aborts prepare/load.
That is a real, user-visible break for the token feature and for in-tree
tests, with a tiny, maintainer-reviewed fix and negligible regression
risk.
### What the commit solves for this tree
Restricted BPF tokens cannot load objects through libbpf because a dummy
SOCKET_FILTER/TRACEPOINT probe is not in the token’s allow-list.
Skipping the probe when a token FD exists restores load/prepare for
those objects.
### Stable rules / risk
Meets the written rules: small, obviously correct, real bug, no new API,
applies cleanly to 6.18. Benefit is restoring a supported 6.18 feature;
risk is an extra early return on a userspace probe.
### Concerns
Feature-probe hardcoded types (series patch 2) remain in this tree, so
some token+global-data cases may still be incomplete. That does not
remove the standalone value of stopping probe_loading from failing the
whole load.
Verification:
- [Phase 1] Parsed tags: author Yuan Chen; SOB Andrii Nakryiko; lore
link; no Fixes/Reported-by/Cc-stable in the commit
- [Phase 2] Diff: `tools/lib/bpf/libbpf.c`,
`bpf_object__probe_loading()`, +3/−7; skip on `obj->token_fd`; dummy
loads use NULL opts
- [Phase 2] Confirmed `OPTS_VALID(NULL)` is true in `libbpf_internal.h`
- [Phase 3] Blame: token opts added in `6b434b61b4d9e` (2024-01-23);
ancestor of this tree
- [Phase 3] No Fixes tag; introducing commit present; patch 2 not in
this tree
- [Phase 4] `b4 dig -c d262a25d8b58`: lore
https://patch.msgid.link/20260610145059.113412-2-chenyuan_fl@163.com
- [Phase 4] `b4 dig -a`: v1 selftest workaround → v2 series → bpf-only
resend → v3 1/2 (landed)
- [Phase 4] `b4 dig -w`: bpf maintainers on Cc
- [Phase 4] mbox: Mykyta Acked-by; Andrii asked to land this patch
alone; later asked bpf-next + Fixes tag
- [Phase 5] Only caller is `bpf_object_prepare()` ← `bpf_object_load()`
and `bpf_object__prepare()`
- [Phase 6] `git describe HEAD` / `make kernelversion`: 6.18.53; `v6.18`
file matches pre-fix hunk md5
- [Phase 6] Token selftests in this tree still use XDP-only / map-only
tokens without SOCKET_FILTER/TRACEPOINT
- [Phase 8] Failure mode: userspace object load abort, not kernel oops;
severity MEDIUM-HIGH for token users
- UNVERIFIED: stable@ mailing-list discussion (lore 403); kernel “drops
token reference” cover-letter claim
**YES**
tools/lib/bpf/libbpf.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b21d2f842579f..1aaf2bdf26857 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5070,12 +5070,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
BPF_EXIT_INSN(),
};
int ret, insn_cnt = ARRAY_SIZE(insns);
- LIBBPF_OPTS(bpf_prog_load_opts, opts,
- .token_fd = obj->token_fd,
- .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
- );
- if (obj->gen_loader)
+ if (obj->gen_loader || obj->token_fd)
return 0;
ret = bump_rlimit_memlock();
@@ -5084,9 +5080,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
errstr(ret));
/* make sure basic loading works */
- ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0)
- ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0) {
ret = errno;
pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] ksmbd: skip fallocate for SMB2_CREATE_ALLOCATION_SIZE on a stream handle
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (7 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] libbpf: Skip bpf_object__probe_loading() when BPF token is in use Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] clk: clocking-wizard: fix clock difference detection Sasha Levin
` (507 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Gael Blivet, Namjae Jeon, Sasha Levin, linux-cifs, linux-kernel
From: Gael Blivet <gael.blivet@gmail.com>
[ Upstream commit bfdf81c62f4f52a3626ea62db0744def6778e83f ]
smb2_open() calls vfs_fallocate(fp->filp, ...) unconditionally when a
client's CREATE request includes an AllocationSize create context.
For a stream handle, fp->filp refers to the base file's data fork
(streams are xattr-backed on the same underlying file, not separate
files), so this pre-allocates storage on the base file's actual data
instead of doing anything meaningful for the stream -- fallocate has
no applicability to an xattr-backed stream at all.
Skip the fallocate call for stream handles.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Gael Blivet <gael.blivet@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111**. The buggy `vfs_fallocate()` on stream
CREATEs is present here, and the skip is a small, self-contained
correctness fix that applies to this checkout.
## Phase 1: Commit message forensics
**Step 1.1: Subject line**
- Record: **[ksmbd] [skip] skip fallocate for
SMB2_CREATE_ALLOCATION_SIZE on a stream handle**
- Subsystem: ksmbd (in-kernel SMB3 server). Verb “skip” here means “do
not run a VFS operation that does not apply.”
**Step 1.2: Tags**
- Record:
- `Assisted-by: Claude:claude-sonnet-5`
- `Signed-off-by: Gael Blivet <gael.blivet@gmail.com>`
- `Acked-by: Namjae Jeon <linkinjeon@kernel.org>` (on `e360be3d03f77`;
the candidate copy uses `Signed-off-by: Namjae Jeon`)
- `Signed-off-by: Steve French` (on the smb.git copy)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Cc: stable`, or `Link:`
- Absence of `Fixes:`/`Cc: stable` is expected for this review
pipeline
**Step 1.3: Body**
- Record:
- **Bug:** `smb2_open()` always calls `vfs_fallocate(fp->filp,
FALLOC_FL_KEEP_SIZE, …)` when CREATE has an AllocationSize context.
- **Root cause:** For a named-stream handle, `fp->filp` is the **base
file**. Streams are xattr-backed, not separate files.
- **Symptom:** Preallocation (and a level-II oplock break) hits the
base file’s data fork instead of the stream.
- **Failure mode:** Wrong-file disk preallocation; unexpected oplock
break on the base file.
- No stack trace, no version list, no user report.
**Step 1.4: Hidden bug fix?**
- Record: **Yes, this is an explicit bug fix**, not cleanup. Cover
letter for series 8/8: opening a stream with AllocationSize
“fallocates storage on the underlying base file’s actual data.”
## Phase 2: Diff analysis
**Step 2.1: Inventory**
- Record:
- File: `fs/smb/server/smb2pdu.c` only
- Scope: **+16 / −7** (net +9), one function: `smb2_open()`
- Classification: **single-file surgical fix**
**Step 2.2: Code-flow change**
- Record:
- **Before:** If CREATE has `SMB2_CREATE_ALLOCATION_SIZE`, always
`smb_break_all_levII_oplock(work, fp, 1)` then
`vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0, alloc_size)`.
Failures are only debug-logged.
- **After:** Same path, but only when `!ksmbd_stream_fd(fp)`. Stream
handles skip both the oplock break and fallocate.
- Affected path: SMB2 CREATE with AllocationSize on a stream, after
the file is already opened.
**Step 2.3: Bug mechanism**
- Record:
- **Category:** logic / correctness (wrong object for a VFS call),
with resource side effects
- **Mechanism:** Stream fds share the base `struct file`.
`ksmbd_stream_fd()` is `fp->stream.name != NULL`. Stream I/O already
goes through xattrs (`ksmbd_vfs_stream_read`/`_write`); fallocate
has no stream equivalent.
- `FALLOC_FL_KEEP_SIZE` does not change `i_size`, but it **does**
allocate blocks on the base inode and can fill the filesystem.
`vfs_fallocate()` also takes `file_start_write()` and may run for a
long time on a large client-supplied size (bounded by `s_maxbytes`).
**Step 2.4: Fix quality**
- Record:
- Obviously correct: skip a VFS op that cannot apply to an xattr
stream.
- Matches existing stream guards (read/write/copy-chunk).
- Regression risk is **very low**: regular-file CREATE is unchanged;
stream CREATE only stops a harmful no-op-for-the-stream.
- Incomplete vs SET_INFO: `set_file_allocation_info()` in this tree
still fallocates `fp->filp` with no stream check. That does not make
this CREATE skip wrong.
## Phase 3: Git history
**Step 3.1: Blame**
- Record:
- Unconditional fallocate in `smb2_open()` comes from `e8c061917133dd`
(“ksmbd: opencode to avoid trivial wrappers”, 2021-06-22), replacing
`ksmbd_vfs_alloc_size()`.
- That commit **is an ancestor of this HEAD**.
- `ksmbd_stream_fd()` is from `f44158485826c0` (2021-03-16) and is
also an ancestor.
- Bug has been in ksmbd for the lifetime of this 6.12 line.
**Step 3.2: Fixes: tag**
- Record: **N/A** (no `Fixes:`). Introducer is the original CREATE
AllocationSize handling, present since cifsd/`e8c0619`.
**Step 3.3: Related file history**
- Record:
- `a9f106c765c12` — “fix wrong allocation size update in smb2_open()”
(response timing, not this bug).
- `2a4179c99bc6b` — overflow in `set_file_allocation_info()` (already
in this tree).
- `3b41d8b05dc89` — “return requested create allocation size” is
**not** in this tree (`merge-base --is-ancestor` failed). Candidate
parent uses outer-scope `alloc_size`; 6.12 still has a local `loff_t
alloc_size`. Functional hunk still matches.
**Step 3.4: Author**
- Record: Gael Blivet, stream/AAPL/Time Machine work; maintainer Namjae
Jeon acked and applied this patch. Not a drive-by.
**Step 3.5: Dependencies**
- Record:
- Cover: **“None of this depends on or touches the AAPL/Time Machine
feature series.”**
- Needs only `ksmbd_stream_fd()`, which exists here.
- Series is **[PATCH 8/8]**; this hunk does not need patches 1–7.
- `git apply --check` of `e360be3d03f77` on this tree: **Hunk #1
succeeded at 3593 (offset -504 lines).**
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
- Record:
- `b4 dig -c e360be3d03f77` →
https://patch.msgid.link/20260709000548.66445-9-g.blivet@me.com
- Series: **[PATCH 0/8] ksmbd: follow-up fixes to previously-merged
patches** (2026-07-09)
- Only **v1** found (`b4 dig -a`).
- Namjae Jeon: **“Applied them except 0002, 0005 patch”** — this is
patch 8, so it was applied. No NAK on patch 8. No `Cc: stable` in
review.
**Step 4.2: Recipients (`b4 dig -w`)**
- Record: Gaël Blivet-Bailly, Namjae Jeon, `linux-cifs@vger.kernel.org`.
Maintainer was on To/Cc and acked.
**Step 4.3: Bug report**
- Record: No syzbot/bugzilla. Found by **Sashiko (LLM review)** of
stream-handling code. Related real-world class: namjaejeon/ksmbd#507
(SetInfo/EOF on a stream truncated the **base** file because
`fp->filp` is the base file). Same object-confusion pattern.
**Step 4.4: Series context**
- Record: Eight independent follow-ups. Patch 8 is standalone. Also
listed in the 7.3-rc1 ksmbd pull under alternate-data-stream handling
(`e360be3d03f77`).
**Step 4.5: Stable list**
- Record: lore.kernel.org/stable returned **403**. **UNVERIFIED**
whether stable@ already discussed this; that does not change the
technical verdict.
## Phase 5: Semantic / call-graph
**Step 5.1: Functions**
- Record: `smb2_open()` only. Helper used: `ksmbd_stream_fd()`.
**Step 5.2: Callers**
- Record: `fs/smb/server/smb2ops.c` maps `SMB2_CREATE_HE` → `smb2_open`.
Reachable from any authenticated SMB2 CREATE.
**Step 5.3: Callees**
- Record: `smb2_find_context_vals()`, `smb_break_all_levII_oplock()`,
`vfs_fallocate()`. Stream CREATE still sets `fp->stream.name` via
`smb2_set_stream_name_xattr()` **before** this block (around line
3485).
**Step 5.4: Reachability**
- Record: **Yes, from the network.** Requires:
1. `CONFIG_SMB_SERVER`
2. Share with `KSMBD_SHARE_FLAG_STREAMS`
3. CREATE of `name:stream` plus AllocationSize create context (`AlSi`)
- Windows ADS and macOS resource-fork/Finder streams are the usual
clients. Unprivileged local syscall is not the path; an authenticated
SMB client is.
**Step 5.5: Similar patterns**
- Record: `ksmbd_vfs_read`/`write` already branch on
`ksmbd_stream_fd()`. `ksmbd_vfs_copy_file_ranges()` returns `-EBADF`
for streams. This CREATE fallocate path was the missing guard.
`set_file_allocation_info()` still unguarded in **this** tree.
## Phase 6: This tree (6.12.111)
**Step 6.1: Buggy code present?**
- Record: **Yes.** `fs/smb/server/smb2pdu.c` ~3596–3602:
```3592:3602:fs/smb/server/smb2pdu.c
alloc_size =
le64_to_cpu(az_req->AllocationSize);
ksmbd_debug(SMB,
"request smb2 create allocate size :
%llu\n",
alloc_size);
smb_break_all_levII_oplock(work, fp, 1);
err = vfs_fallocate(fp->filp,
FALLOC_FL_KEEP_SIZE, 0,
alloc_size);
if (err < 0)
ksmbd_debug(SMB,
"vfs_fallocate is failed :
%d\n",
err);
```
- `ksmbd_stream_fd()` is in `fs/smb/server/vfs_cache.h`.
- Candidate SHAs `e360be3d03f77` / `bfdf81c62f4f` are **not** ancestors
of HEAD.
**Step 6.2: Backport difficulty**
- Record: **Clean apply with offset** (`git apply --check` succeeded at
line 3593). Local `loff_t alloc_size` vs later outer-scope
`alloc_size` does not conflict with the wrapped lines.
**Step 6.3: Related fixes already here?**
- Record: No skip of CREATE fallocate for streams. Overflow check in
SET_INFO allocation is a different bug.
## Phase 7: Subsystem context
**Step 7.1**
- Record: **ksmbd (`fs/smb/server`)**, **IMPORTANT** (in-kernel SMB3
server for NAS/shares). Not mm/core, but network-facing and used in
production.
**Step 7.2**
- Record: Actively backported on this branch (many ksmbd fixes in recent
`git log -- fs/smb/server`).
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
- Record: ksmbd users with **streams enabled**, when a client CREATEs a
named stream with AllocationSize. Typical Windows/macOS
interoperability.
**Step 8.2: Trigger**
- Record: Authenticated SMB CREATE of `file:stream` + AllocationSize.
Not every open; common enough for ADS-aware clients. Same client could
already write the file; unique harm is **wrong object** (base file)
and a large fallocate without intending to preallocate the data fork.
**Step 8.3: Failure mode**
- Record:
- Preallocates blocks on the **base file** (`FALLOC_FL_KEEP_SIZE` → no
size change, but real space use).
- Breaks level-II oplocks on the base file (other clients can lose
caching).
- Large `AllocationSize` can run a long `fallocate` under
`file_start_write()` (filesystem write exclusion).
- **Severity: HIGH** for disk/oplock side effects on a NAS; not a
panic/UAF. Not content corruption of existing data.
**Step 8.4: Risk–benefit**
- Record:
- **Benefit:** Stops wrong-file preallocation and spurious oplock
breaks; one `if` around existing code.
- **Risk:** Very low. Stream CREATE AllocationSize currently does the
wrong thing; skipping is the correct xattr-stream behavior.
- **Ratio:** Favorable.
## Phase 9: Synthesis
**Step 9.1: Evidence**
**For:**
- Real wrong-file VFS operation, present since 2021, present in 6.12.111
- User-visible: disk on the base file, oplock disruption
- Small, obviously correct, applies with offset
- `ksmbd_stream_fd()` already here; no AAPL/Time Machine dependency
- Maintainer applied it (patch 8 of 8)
- Same stream/`fp->filp` confusion class as documented user bugs
**Against:**
- No crash/UAF/CVE; found by automated review, not a reporter
- SET_INFO allocation path still unfixed here
- Needs streams share flag
- lore stable search unverified (HTTP 403)
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — skip is correct; maintainer
applied it.
2. Real bug affecting users? **PASS** — wrong-file fallocate on stream
CREATE.
3. Important (crash/security/corruption/deadlock/etc.)? **PASS** —
unexpected allocation and oplock break on the base file of a network
file server; can consume substantial disk.
4. Small and contained? **PASS** — ~9 lines, one function.
5. No new features/APIs? **PASS**
6. Applies to this tree? **PASS** — `git apply --check` succeeded.
**Step 9.3: Exceptions**
- Record: Not a device-ID/quirk/DT/build/doc exception. Qualifies as a
normal small bugfix.
**Step 9.4: Decision**
Backport to **this** 6.12.111 tree. The bug is here, the helper is here,
the patch applies, and the change only disables a harmful path.
---
### What this solves for 6.12 users
On ksmbd shares with named streams, an SMB2 CREATE of an alternate data
stream that includes AllocationSize currently calls `vfs_fallocate()` on
the **base file**. That can allocate disk and break oplocks on the wrong
object. Streams are xattr-backed; fallocate cannot apply to them.
Skipping it is the correct, minimal fix.
### Verification
- **[Phase 1]** Parsed tags on `e360be3d03f77` / `bfdf81c62f4f` (same
patch-id `8e46981f5116…`); no Fixes/Reported-by/Cc:stable
- **[Phase 2]** Diff: wrap fallocate + oplock break in `if
(!ksmbd_stream_fd(fp))` in `smb2_open()`
- **[Phase 3]** `git blame`: fallocate from `e8c061917133dd` (ancestor);
`ksmbd_stream_fd` from `f44158485826c0` (ancestor)
- **[Phase 3]** `git merge-base --is-ancestor e360be3d03f77 HEAD` → not
in this tree
- **[Phase 3]** `git merge-base --is-ancestor 3b41d8b05dc89 HEAD` →
later alloc_size-field commit not here
- **[Phase 4]** `b4 dig -c e360be3d03f77` → lore msgid
`20260709000548.66445-9-g.blivet@me.com`; series 8/8
- **[Phase 4]** `b4 dig -a`: v1 only; `b4 dig -w`: linux-cifs + Namjae
Jeon
- **[Phase 4]** mbox: Namjae “Applied them except 0002, 0005”; patch 8
applied; no NAK
- **[Phase 4]** Cover: independent of Time Machine/AAPL
- **[Phase 5]** `SMB2_CREATE_HE` → `smb2_open`; streams gated by
`KSMBD_SHARE_FLAG_STREAMS`
- **[Phase 6]** `git describe HEAD` → `p-6.12-3-gc504cf0baa3d8`; `make
kernelversion` → **6.12.111**
- **[Phase 6]** Buggy lines at `smb2pdu.c:3596–3602`; `git apply
--check` succeeded at 3593
- **[Phase 8]** Failure mode: wrong-file preallocation + oplock break;
severity HIGH for ksmbd/NAS, not a panic
- **UNVERIFIED:** stable@ lore search (HTTP 403); whether Windows always
sends AllocationSize on ADS CREATE (bug is still real when it does)
**YES**
fs/smb/server/smb2pdu.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index f383d1e5e5cb7..9c5275d3640cc 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -3633,13 +3633,22 @@ int smb2_open(struct ksmbd_work *work)
ksmbd_debug(SMB,
"request smb2 create allocate size : %llu\n",
alloc_size);
- smb_break_all_levII_oplock(work, fp, 1);
- err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
- alloc_size);
- if (err < 0)
- ksmbd_debug(SMB,
- "vfs_fallocate is failed : %d\n",
- err);
+ /*
+ * fp->filp is the base file's data fork for a stream
+ * handle (streams are xattr-backed on the same
+ * underlying file) -- fallocate has no meaning for a
+ * stream and would otherwise pre-allocate storage on
+ * the base file's data instead.
+ */
+ if (!ksmbd_stream_fd(fp)) {
+ smb_break_all_levII_oplock(work, fp, 1);
+ err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
+ alloc_size);
+ if (err < 0)
+ ksmbd_debug(SMB,
+ "vfs_fallocate is failed : %d\n",
+ err);
+ }
}
context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] clk: clocking-wizard: fix clock difference detection
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (8 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: skip fallocate for SMB2_CREATE_ALLOCATION_SIZE on a stream handle Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: add buf length check Sasha Levin
` (506 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Colin Foster, Shubhrajyoti Datta, Brian Masney, Sasha Levin,
sboyd, bmasney+clk, jbrunet+clk, michal.simek, anatoliy.klymenko,
linux-clk, linux-arm-kernel, linux-kernel
From: Colin Foster <colin.foster@in-advantage.com>
[ Upstream commit 006ba909c240b832c876b7aed29c6beec9d1f5e5 ]
Reviewed-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
Signed-off-by: Brian Masney <bmasney@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
change is a one-line restoration of `abs()` in Xilinx Clocking Wizard
divisor search: unsigned wrap made frequencies below the request look
like ~2^64 error, so they were ignored.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[clk / xilinx clocking-wizard] [fix] [clock difference
detection]** — restore correct closest-match comparison when computed
frequency is below the requested rate.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record (from `git show 006ba909c240b`):
- Reviewed-by: Shubhrajyoti Datta \<shubhrajyoti.datta@amd.com\>
(Xilinx/AMD clocking-wizard author)
- Reviewed-by: Brian Masney \<bmasney@redhat.com\> (clk co-maintainer;
also committer)
- Signed-off-by: Colin Foster \<colin.foster@in-advantage.com\> (author)
- Signed-off-by: Brian Masney \<bmasney@redhat.com\>
- No Fixes:, Cc: stable, Reported-by, Tested-by, Link, or Acked-by in
the **merged** commit
- Absence of Fixes/Cc:stable is expected for this review pipeline and is
not a negative
The merged git message has **no body**. The mailing-list submission did
(see Phase 4).
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Merged commit: subject + tags only.
Mailing-list body (from b4 mbox, not in git): unsigned “rollover” in
`diff = freq - rate`. Frequencies below the request produced diffs like
`18446744073708237796` (2^64 wrap) and were not considered. Author
included before/after traces at 133312500 Hz / parent 99999000 Hz.
Cover letter: this is patch **1/3** of “clock-wizard fixups”. The series
also optimizes exact-match search (2/3) and removes the 20 kHz
`WZRD_MIN_ERR` cutoff (3/3). Cover letter: the 20 kHz check made **out-
of-tree consumers fail `clk_set_rate`**; patch 1 is the separate
difference-calculation bug.
Record: **[Bug: unsigned underflow when freq \< rate] [Symptom: wrong
closest match and/or -EBUSY from set_rate/determine_rate] [Root cause:
abs() dropped in a later refactor] [No version tags in the commit
itself]**
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not hidden.** Subject says “fix”. It is a real comparison bug,
not cleanup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/clk/xilinx/clk-xlnx-clock-wizard.c` — **1 insertion, 1
deletion**
- Function: `clk_wzrd_get_divisors()`
- Scope: **single-file surgical one-liner**
- Versal sibling `clk_wzrd_get_divisors_ver()` is **not** changed
(already uses `abs()`)
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Before: `diff = freq - rate` with `freq`/`diff` as `u64`. If `freq <
rate`, subtraction wraps. `best_diff` starts at `-1ULL`. Wrapped diffs
lose to any over-rate candidate; if every candidate is under-rate,
`best_diff` stays huge and `return best_diff < WZRD_MIN_ERR ? 0 :
-EBUSY` returns **-EBUSY** (20 kHz threshold still present in the parent
of this commit).
After: `diff = abs(freq - rate)` so both sides of the target compete;
closest match wins.
Path: clock **determine_rate / set_rate** for non-Versal Clocking Wizard
(dynamic reconfig / fractional M and O).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Logic / correctness + unsigned wrap]** — `abs()` was dropped
when 7681f64e6404ed switched the search to `u64` and `best_diff`.
Original v6.4 code in 595c88cda65d30 used `diff = abs(freq - rate)`.
This restores that.
Kernel `abs()` on the `u64` difference works here: wrap of a small Hz
delta becomes a negative `signed long long`, then `abs()` yields the
true delta. Clock Hz values are far below 2^63. Same pattern as the
Versal function.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: **Obviously correct, minimal, matches the pre-regression and
Versal code.** Regression risk is low: set_rate may now succeed with a
slightly-below rate instead of failing or picking a worse over-rate.
That is the intended fix. `abs_diff()` would be cleaner with matching
types, but reviewers accepted `abs()`, and it matches the sibling.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Current `abs()` line: **006ba909c240b** (this commit), 2026-06-29
- Surrounding fractional search: **7681f64e6404ed** (“calculate dividers
fractional parts”), 2025-01-06, **v6.13-rc1**
- Function introduced: **595c88cda65d30** (v6.4-rc1) **with abs()
already**
- 7681f64e **removed** `abs()` and used `diff = freq - rate`
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Buggy commit is **7681f64e6404ed**, ancestor
of HEAD (`git merge-base --is-ancestor`).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: 3-patch series, same author/date:
1. **006ba909c240b** — this fix (1/3)
2. **9329714414d1f** — early-out on exact match (optimization, 2/3)
3. **54ed94b709e03** — drop 20 kHz `WZRD_MIN_ERR` (3/3)
This patch is **standalone**. It does not need 2/3 or 3/3. With the 20
kHz check still present, `abs()` is what lets a close **under**-rate
pass `best_diff < 20000` instead of wrapping to -EBUSY.
Related: **4adf593c6fc5a** overflow fix in the same file (`Cc: stable`,
Fixes: 7681f64e). **e0a94c6bb5b48** (v6.18-rc1) already used `abs()` on
the Versal path.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Colin Foster is not the historical driver author (that is
Shubhrajyoti Datta / AMD). Datta reviewed this. Foster’s three clocking-
wizard commits are this series.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs `clk_wzrd_get_divisors()` with `u64` `freq`/`diff` as in
7681f64e. That is in this tree. **Applies standalone.** `abs()` is in
`include/linux/math.h`.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 006ba909c240b` →
https://patch.msgid.link/20260629205346.3228886-2-colin.foster@in-
advantage.com
- `b4 dig -a`: only **PATCH v2 1/3** (v2: rebase + signoffs). v1 not in
the matched thread.
- Saved mbox: cover + 3 patches, **no reply NAKs** in that thread
- WebFetch/curl to lore.kernel.org: **403** — discussion beyond the mbox
is UNVERIFIED
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
`b4 dig -w` To/Cc: linux-clk, linux-arm-kernel, linux-kernel,
Shubhrajyoti Datta, Michal Simek, Brian Masney, Stephen Boyd, Michael
Turquette.
Record: **Clk lists + clk maintainers CC’d; Reviewed-by from AMD driver
author and Brian Masney.**
**Step 4.3: SEARCH FOR THE BUG REPORT**
No syzbot/bugzilla. Evidence is the author’s traces (unsigned wrap
~2^64) and cover-letter `clk_set_rate` failures.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: **v2 0/3 “clock-wizard fixups”.** 1/3 is this logic fix; 2/3
optimization; 3/3 policy (allow error ≥ 20 kHz). 1/3 does not depend on
the others.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned **403**. UNVERIFIED
whether stable@ discussed it.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
semcode MCP: **not available**. Used grep + callers in this file.
**Step 5.1: KEY FUNCTIONS**
Record: **`clk_wzrd_get_divisors()`** only.
**Step 5.2: TRACE CALLERS**
- `clk_wzrd_dynamic_all_nolock()` → `clk_wzrd_dynamic_all()` →
`clk_wzrd_clk_div_all_ops.set_rate`
- `clk_wzrd_determine_rate_all()` →
`clk_wzrd_clk_div_all_ops.determine_rate`
Versal ops use `clk_wzrd_get_divisors_ver()`, already using `abs()`.
**Step 5.3: TRACE CALLEES**
`div64_u64`, `DIV_ROUND_CLOSEST_ULL`, writes into
`divider->{m,m_frac,d,o,o_frac}`. No allocation/locking inside the
search.
**Step 5.4: FOLLOW THE CALL CHAIN**
Probe registers outputs with `clk_wzrd_clk_div_all_ops` for non-Versal
dynamic-reconfig Clocking Wizard (`xlnx,clocking-wizard`, v5.2, v6.0).
`clk_set_rate` / `clk_round_rate` from consumers (display pixel clocks
were the reason fractional M/O were added).
Record: **Reachable from userspace/driver clock APIs on that IP. Not a
syscall bug by itself; standard clk consumer path.**
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Versal `clk_wzrd_get_divisors_ver()` already has `diff = abs(freq -
rate)` (e0a94c6bb5b48). Original non-Versal code had abs() until
7681f64e dropped it.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Tree: **v7.3-rc4** / Makefile **7.3.0-rc4**
- File and `clk_wzrd_get_divisors()` **exist**
- HEAD already has `diff = abs(freq - rate)` because **006ba909c240b is
an ancestor** (`git merge-base --is-ancestor` → yes). `git describe
--contains` → **v7.3-rc1**
- Bug introduced **v6.13** (7681f64e), long before 7.3
- Pre-fix code (parent of 006ba909) still had `diff = freq - rate` and
`WZRD_MIN_ERR` 20000
This is **not** “bug added after this branch.” The driver and the
regression are part of this 7.3 line.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
On **this** checkout the one-liner is already applied; a second apply
would not change anything. Against the pre-fix function the hunk is
context-identical (one line). Expected difficulty: **clean apply** on a
tree that still has `diff = freq - rate`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This exact fix **is** in HEAD, plus 2/3 and 3/3. That is the
mainline landing, not a separate in-tree workaround. No competing
alternate fix.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **`drivers/clk/xilinx/`** — Xilinx Clocking Wizard
(`CONFIG_COMMON_CLK_XLNX_CLKWZRD`, `depends on OF`). **PERIPHERAL /
platform-specific** (FPGA/SoC), but it is the clock provider for that
IP, including pixel-clock accuracy.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Active through 2025–2026 (fractional dividers, Versal, overflow
fix, this series). Mature in-tree driver, not staging.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific / config-specific** —
`COMMON_CLK_XLNX_CLKWZRD`, non-Versal Clocking Wizard with dynamic
reconfig / fractional search. Not universal.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: **`clk_set_rate` / determine_rate** when the closest achievable
frequency is below the request, or when under-rate candidates must
compete with worse over-rate ones. Common for arbitrary pixel/device
rates. Unprivileged userspace can hit it if a consumer exposes clock
control; typically a device driver at probe/modeset.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Wrong clock chosen or `clk_wzrd_get_divisors()` returns
-EBUSY** so rate set fails. Not oops/UAF/deadlock. Author showed
wraparound and `clk_set_rate` failure in the series. **Severity:
MEDIUM** (functional breakage on that hardware, including display
clocks).
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: **Benefit: medium** for Clocking Wizard users (correct closest
rate; fewer false -EBUSY). **Risk: very low** (1 line, same as
old/Versal code). **Ratio: favorable.**
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real unsigned wrap; traces show ~2^64 diffs for freq \< rate
- Regression: 595c88cd used `abs()`; 7681f64e dropped it in v6.13
- Restores closest-match; can avoid -EBUSY under the 20 kHz check
- 1 line, obviously correct
- Reviewed by AMD driver author and clk co-maintainer
- Driver and function exist in this 7.3 tree; bug predates 7.3
- Standalone; not a new API
AGAINST:
- Merged commit message has no body (explanation only on list)
- Not crash/security/corruption
- Peripheral Xilinx FPGA/SoC driver
- Cover letter also talks about OOT consumers and patch 3’s 20 kHz
policy
- Author’s 133312500 Hz sample still picked the over-rate 19500 Hz
candidate; abs() matters when the **best** match is below the request
- lore.kernel.org HTTP 403; no stable@ thread verified
UNRESOLVED:
- Full v1 review thread
- Whether stable@ already took this (403)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — wrap math is clear; author
posted before/after; two Reviewed-by
2. Fixes a real bug that affects users? **PASS** — wrong diffs; set_rate
can fail or pick a worse rate
3. Important issue? **PASS** (medium) — not a panic, but the driver’s
job is correct rates; pixel-clock path was the reason fractional
search exists
4. Small and contained? **PASS** — 1 line, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — same function is here; HEAD
already contains this commit as of v7.3-rc1, which means 7.3’s own
code already includes the fix. That does not make the fix unsuitable;
it confirms the code matches.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **None** (not a device ID, quirk, DT, build, or docs exception).
It is a normal small correctness fix.
**Step 9.4: MAKE YOUR DECISION**
This tree is 7.3-rc4 and already contains the line, because the commit
landed in v7.3-rc1. The decision is still whether this is appropriate
**for this tree’s code**, not whether the pipeline already “selected”
it.
It is a **v6.13 regression** (accidental drop of `abs()`), one line,
reviewed, and it fixes real closest-rate / -EBUSY behavior on Xilinx
Clocking Wizard. That meets stable rules for this checkout. Later series
patches (search micro-opt, dropping 20 kHz) are separate and not
required.
===============================================================
DETAILED EXPLANATION
===============================================================
**Problem:** `clk_wzrd_get_divisors()` ranked candidates with unsigned
`freq - rate`. Any frequency below the request wrapped to ~2^64, so
those configs were ignored. Combined with `best_diff < 20000`, that
yields **-EBUSY** when the only close match is slightly low, or a
**worse higher** clock when a closer lower one exists. That is exactly
the fractional-divider accuracy the v6.13 work was supposed to provide
(pixel clocks).
**Why it matters here:** This 7.3 tree has that search (7681f64e).
Consumers of `xlnx,clocking-wizard` that call `clk_set_rate` can fail or
lock the IP to the wrong rate.
**Stable rules:** Small, obvious, real bug, no new API. Risk is a
correct rate instead of failure/wrong rate.
**Concerns:** Empty merged commit message; not a crash. Series 3/3 is a
policy change and should not be required. No backport rework is needed
on a tree that still has `diff = freq - rate`.
===============================================================
Verification:
- [Phase 1] `git show 006ba909c240b`: subject+tags only; Reviewed-by
Datta and Masney; no Fixes/stable
- [Phase 1] b4 mbox body: wraparound explanation and traces (133312500
Hz)
- [Phase 2] Diff: one line `diff = freq - rate` → `diff = abs(freq -
rate)` in `clk_wzrd_get_divisors`
- [Phase 2] Parent still has `return best_diff < WZRD_MIN_ERR ? 0 :
-EBUSY` with `WZRD_MIN_ERR` 20000
- [Phase 2] `include/linux/math.h`: `abs()` signed conversion; Hz deltas
fit
- [Phase 3] blame: abs line is 006ba909; search from 7681f64e6404ed
(v6.13-rc1)
- [Phase 3] 595c88cda65d30 originally used `diff = abs(freq - rate)`;
7681f64e removed it
- [Phase 3] `git merge-base --is-ancestor 006ba909c240b HEAD` → yes;
`--contains` → v7.3-rc1
- [Phase 3] Series 006ba909, 9329714414d1f, 54ed94b709e03; this patch is
1/3 standalone
- [Phase 4] `b4 dig -c`:
patch.msgid.link/20260629205346.3228886-2-colin.foster@in-
advantage.com
- [Phase 4] `b4 dig -a`: v2 1/3 only in match; cover v2 rebase +
signoffs
- [Phase 4] `b4 dig -w`: linux-clk, Boyd, Turquette, Datta, Simek,
Masney
- [Phase 4] WebFetch/curl lore: 403; stable@ discussion UNVERIFIED
- [Phase 5] Callers: `clk_wzrd_dynamic_all_nolock`,
`clk_wzrd_determine_rate_all` (non-Versal ops)
- [Phase 5] Versal sibling already `abs()` via e0a94c6bb5b48 (v6.18-rc1)
- [Phase 6] `git describe HEAD` v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` 7.3.0-rc4
- [Phase 6] HEAD already has `diff = abs(freq - rate)` at lines 375 and
416
- [Phase 7] Kconfig `COMMON_CLK_XLNX_CLKWZRD`; compatibles
xlnx,clocking-wizard{,-v5.2,-v6.0}
- [Phase 8] Failure mode: wrong rate or -EBUSY on set_rate; severity
MEDIUM
- UNVERIFIED: v1 thread contents; stable@ history (lore 403)
===============================================================
**YES**
drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
index dbef983eb4252..4ef0595f7d993 100644
--- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
+++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
@@ -406,7 +406,7 @@ static int clk_wzrd_get_divisors(struct clk_hw *hw, unsigned long rate,
if (o < omin || o > omax)
continue;
freq = DIV_ROUND_CLOSEST_ULL(vco_freq, o);
- diff = freq - rate;
+ diff = abs(freq - rate);
if (diff < best_diff) {
best_diff = diff;
divider->m = m >> 3;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: add buf length check
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (9 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] clk: clocking-wizard: fix clock difference detection Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm: Validate Vega hwmgr PowerPlay table bounds Sasha Levin
` (505 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Gangliang Xie, Tao Zhou, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Gangliang Xie <ganglxie@amd.com>
[ Upstream commit 473f99e4a262776141366f7fb10f101d0f22b019 ]
add buf length check before using it to access data
Signed-off-by: Gangliang Xie <ganglxie@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.18.53** (`v6.18.53-5049-g0f0bdc2b0dffb` on
`autosel`). The buggy debugfs TA load/invoke paths are in this tree; the
length checks are not in the `v6.18.53` tag. Verdict is for this
checkout only.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[drm/amdgpu] [add] [buf length check before using a userspace-
supplied length to copy/access data]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Fixes:` — none (expected)
- `Reported-by:` — none
- `Tested-by:` — none
- `Reviewed-by: Tao Zhou <tao.zhou1@amd.com>`
- `Acked-by:` — none
- `Link:` — none in the commit; lore found separately
- `Cc: stable@vger.kernel.org` — none (expected)
- `Signed-off-by: Gangliang Xie <ganglxie@amd.com>` (author)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (amdgpu
maintainer)
- Ignore: `[Upstream commit 473f99e4a262…]`, `Signed-off-by: Sasha
Levin` (pipeline)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug description: userspace-supplied buffer lengths are used to
copy/access data without enough validation
- Symptom: out-of-bounds access / invalid allocation when the length is
too small or too large
- Version info: none in the message
- Root cause: `ta_bin_len` / `shared_buf_len` from `copy_from_user` are
trusted after only a partial check (load has an upper bound; invoke
has none)
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: This is a real bounds-check fix, not cleanup. “Add buf length
check before using it to access data” is an OOB / crash-prevention
patch.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c` (+4 / -1)
- Functions: `ta_if_load_debugfs_write()`,
`ta_if_invoke_debugfs_write()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Load, before: reject only `ta_bin_len > PSP_1_MEG` (`0x100000`).
`ta_bin_len == 0` or smaller than `struct common_firmware_header` (32
bytes) still proceeds to `memdup_user()` then `get_bin_version()`.
- Load, after: also reject `ta_bin_len < sizeof(struct
common_firmware_header)`.
- Invoke, before: `shared_buf_len` is copied from userspace and passed
straight to `memdup_user()` with no min/max check.
- Invoke, after: reject `shared_buf_len == 0` or `shared_buf_len >
PSP_1_MEG`.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Memory safety / size validation (OOB read + unbounded copy).**
Load path (the crash):
- `get_bin_version()` does `hdr->ucode_version` at offset 16 of `struct
common_firmware_header`.
- `ta_bin_len == 0`: `memdup_user(..., 0)` goes through `kmalloc(0)` →
`ZERO_SIZE_PTR` (`(void *)16`). Reading `ucode_version` is a distinct
fault.
- `0 < ta_bin_len < 32`: allocated buffer is smaller than the header;
reading `ucode_version` is an out-of-bounds read (KASAN OOB / slab
overrun).
Invoke path:
- No upper bound: `memdup_user()` of a user-controlled `uint32_t` (up to
~4GiB). That is an unbounded kernel allocation.
`prep_ta_mem_context()` later rejects lengths above `shared_mem_size`
(`PSP_RAS_SHARED_MEM_SIZE` = 0x4000), so this is not an OOB write into
TA shared memory, but it is still a large GFP_USER allocation from
debugfs.
- Zero length: `memcpy` of 0 bytes would not crash; the
`!shared_buf_len` check is defensive.
This completes `c99769bceab4e` (“Validate TA binary size” / “avoid OOB
write”), which added only the load-path upper bound and was `Cc:
stable@vger.kernel.org`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct, 4 lines, no API/locking/structure changes.
Regression risk is very low: only rejects sizes that cannot be a valid
firmware header or that exceed the existing 1MiB PSP cap. Invoke still
allows up to 1MiB while shared mem is 16KiB; that is conservative, not
wrong.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Buggy debugfs TA I/F: `e50d9ba0d2cd0` (2022-04-21) “Add debugfs TA
load/unload/invoke support” — in this tree (present since ~v5.19-era).
- Load upper bound: `c99769bceab4e` (2024-08-20) — in v6.18.
- `memdup_user` conversion: `99eeb8358e6cd` (2025-09-08) — in v6.18; no
functional change.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The incomplete prior fix is `c99769bceab4e`,
which is in this tree.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Recent related commits on this file: locking (`5c42d9f8b0049`,
not in `v6.18.53`), `memdup_user`, “Validate TA binary size”. This patch
is standalone; it only tightens existing `if` checks and does not depend
on the locking change. Dry-run apply of the upstream diff onto the
`v6.18.53` file succeeded.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Gangliang Xie is an AMD contributor with nearby hardening checks
(`add first record offset check`, `add check for xcp id`). Not the
subsystem maintainer. Maintainer Alex Deucher signed it off.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None required. The functions, `PSP_1_MEG`, `memdup_user`, and
the load-path upper bound all exist in this tree. Standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 473f99e4a262`:
https://patch.msgid.link/20260616093508.37315-1-ganglxie@amd.com
- `b4 dig -a`: single revision **v1 only** (2026-06-16), no v2/v3
- Thread: author patch + `Reviewed-by: Tao Zhou`. No NAK, no stable
nomination in review, no discussion of risk
- lore.kernel.org HTTP fetch returned 403; thread recovered via `b4 dig
-m`
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To `amd-gfx@lists.freedesktop.org`; Cc Hawking
Zhang, Tao Zhou. Reviewed-by Tao Zhou; Signed-off-by Alex Deucher
(amdgpu maintainer).
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No `Reported-by`, syzbot, or bugzilla. Internal AMD hardening,
not a public crash report.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone one-patch series. Sibling in-tree OOB fix
`c99769bceab4e` was explicitly `Cc: stable`.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable HTTP 403. No evidence in the amd-gfx
thread that this was rejected for stable. UNVERIFIED: no stable-list
discussion recovered.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `ta_if_load_debugfs_write`, `ta_if_invoke_debugfs_write`.
Helpers used: `get_bin_version`, `prep_ta_mem_context`, `memdup_user`.
**Step 5.2: TRACE CALLERS**
Record: Only wired as `.write` in `ta_load_debugfs_fops` /
`ta_invoke_debugfs_fops`. Created by `amdgpu_ta_if_debugfs_init()` from
`amdgpu_debugfs.c` as:
- `/sys/kernel/debug/dri/<N>/ta_if/ta_load` (mode 0200)
- `/sys/kernel/debug/dri/<N>/ta_if/ta_invoke` (mode 0200)
Under `#if defined(CONFIG_DEBUG_FS)`.
**Step 5.3: TRACE CALLEES**
Record: `copy_from_user` → `memdup_user` → `get_bin_version` /
`prep_ta_mem_context` → PSP TA load/invoke. `psp_copy_fw()` already uses
`if (!bin_size || bin_size > PSP_1_MEG)` before memcpy into a 1MiB
buffer — the same pattern this patch adds.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable from a write to those debugfs files. Not a syscall for
unprivileged users; debugfs is typically root/`CAP_SYS_ADMIN`. Still a
documented load path: writing a truncated TA blob follows the intended
interface and oopses.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same 0 / `PSP_1_MEG` check already exists in `psp_copy_fw()`.
The 2024 load-path upper bound was the same class of bug and went to
stable.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `v6.18.53` has:
```
if (ta_bin_len > PSP_1_MEG)
return -EINVAL;
```
and invoke `memdup_user(&buf[copy_pos], shared_buf_len)` with no length
check. Bug introduced in 2022 (`e50d9ba0d2cd0`); load upper bound only
since 2024.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply onto the `v6.18.53` file (dry-run `patch -p1` return
0). Context matches. No rework needed.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Upper-bound-only fix `c99769bceab4e` is in this tree. This
commit is the missing lower bound and the invoke-path check. No
duplicate of this exact fix in `v6.18.53`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/gpu/drm/amd/amdgpu` — IMPORTANT (very common GPU
driver), but this path is debugfs/CONFIG_DEBUG_FS, so impact is narrower
than core amdgpu.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively developed; this file has had several stability fixes
(NULL deref, locking, OOB size). Mature debugfs interface (since 2022),
not brand-new code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: AMDGPU users with `CONFIG_DEBUG_FS`, writing
`dri/<N>/ta_if/ta_load` or `ta_invoke`. Driver-specific + config-
specific (debugfs). Not universal.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Write a length field that is 0, smaller than the firmware
header, or (invoke) larger than 1MiB. Easy to hit with a truncated TA
binary on the documented load interface. Unprivileged users generally
cannot; root/debugfs can.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Load, `ta_bin_len == 0`: `ZERO_SIZE_PTR` deref → oops. **HIGH**
- Load, undersized header: OOB read. **HIGH**
- Invoke, huge length: large `GFP_USER` alloc, then `-EINVAL` from
`prep_ta_mem_context`. **MEDIUM** (DoS-ish, privileged)
- Invoke, zero length: not a demonstrated crash. **LOW**
Overall severity: **HIGH** for the load-path oops/OOB; interface is
privileged.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: prevents a kernel oops/OOB on a shipped debugfs firmware-load
path; finishes a check that stable already accepted
- Risk: 4 lines, reject-only, very low
- Ratio: benefit > risk
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB / `ZERO_SIZE_PTR` crash on load with a too-small `ta_bin_len`
- Invoke path had no length cap at all (unbounded `memdup_user`)
- Same file’s prior OOB size check was `Cc: stable`
- Same `!size || size > PSP_1_MEG` pattern already used in
`psp_copy_fw()`
- 4-line, obviously correct, maintainer-acked
- Buggy code exists in this 6.18.53 tree; patch applies cleanly
- No new API/feature
AGAINST:
- debugfs, mode 0200, typically root-only
- No public reporter, syzbot, or crash log
- Sparse commit message; no `Fixes:`
- Invoke zero-length is not itself a crash
UNRESOLVED:
- Could not read lore.kernel.org/stable over HTTP (403)
- No evidence of an in-the-wild crash, only code-path analysis
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — reviewed, maintainer SOB,
trivial predicates
2. Fixes a real bug that affects users? **PASS** — documented TA load
path oopses on a truncated blob
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
kernel oops / OOB read (privileged debugfs, still a crash)
4. Small and contained? **PASS** — +4/-1, one file
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — clean apply to `v6.18.53`
file; all helpers present
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary small
memory-safety fix.
**Step 9.4: MAKE YOUR DECISION**
This belongs in this 6.18.y tree. The load-path hole is a real oops, the
invoke path was never given the cap that load got in 2024, and the patch
is the smallest possible completion of that already-stable-worthy check.
What it solves for stable users: writing a too-small TA binary to
`ta_load` no longer walks off a kernel buffer (or `ZERO_SIZE_PTR`);
`ta_invoke` no longer `memdup_user`s an unchecked userspace length.
Risk vs benefit: four reject-only lines vs. a debugfs-triggered oops on
a common driver. Backport.
Verification:
- [Phase 1] Parsed tags: Reviewed-by Tao Zhou; SOB Alex Deucher; no
Fixes/Reported-by/Cc:stable
- [Phase 1] Body: “add buf length check before using it to access data”
- [Phase 2] Diff: +4/-1 in `amdgpu_psp_ta.c`; load min-size; invoke
0/`PSP_1_MEG`
- [Phase 2] `common_firmware_header` is 32 bytes; `ucode_version` at
offset 16 (`amdgpu_ucode.h`)
- [Phase 2] `memdup_user()` → `kmem_buckets_alloc` → `kmalloc`;
`kmalloc(0)` returns `ZERO_SIZE_PTR` (`include/linux/slab.h`)
- [Phase 3] File added in `e50d9ba0d2cd0` (2022); upper bound
`c99769bceab4e` (Cc:stable, in v6.18); `memdup_user` `99eeb8358e6cd`
in v6.18
- [Phase 3] No Fixes tag; `git merge-base --is-ancestor e50d9ba0d2cd0
HEAD` yes
- [Phase 3] Author: AMD contributor; maintainer merged
- [Phase 4] `b4 dig -c 473f99e4a262`: msgid
20260616093508.37315-1-ganglxie@amd.com
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: amd-gfx, Hawking Zhang, Tao Zhou
- [Phase 4] mbox: Reviewed-by only; no NAK
- [Phase 4] lore.kernel.org WebFetch 403; stable-list search UNVERIFIED
- [Phase 5] Callers: debugfs fops only; `amdgpu_ta_if_debugfs_init()`
from `amdgpu_debugfs.c`
- [Phase 5] `psp_copy_fw()` already has `!bin_size || bin_size >
PSP_1_MEG`
- [Phase 5] `PSP_RAS_SHARED_MEM_SIZE` = 0x4000
- [Phase 6] `git describe HEAD` → `v6.18.53-5049-g0f0bdc2b0dffb`; `make
kernelversion` → 6.18.53
- [Phase 6] `v6.18.53` file lacks both new checks; dry-run apply of
upstream diff: success
- [Phase 6] `git merge-base --is-ancestor 473f99e4a262 HEAD` no
(upstream not in this history as that SHA); buggy code is still
present at the v6.18.53 tag
- [Phase 8] Failure: load-path oops/OOB HIGH; invoke unbounded alloc
MEDIUM; trigger is debugfs write
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
index 0d3c18f04ac36..8ae72c862d112 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
@@ -166,7 +166,8 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t
if (ret)
return -EFAULT;
- if (ta_bin_len > PSP_1_MEG)
+ if (ta_bin_len < sizeof(struct common_firmware_header) ||
+ ta_bin_len > PSP_1_MEG)
return -EINVAL;
copy_pos += sizeof(uint32_t);
@@ -321,6 +322,8 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
if (ret)
return -EFAULT;
+ if (!shared_buf_len || shared_buf_len > PSP_1_MEG)
+ return -EINVAL;
copy_pos += sizeof(uint32_t);
shared_buf = memdup_user(&buf[copy_pos], shared_buf_len);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/amd/pm: Validate Vega hwmgr PowerPlay table bounds
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (10 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: add buf length check Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] clk: mediatek: mt6735-vencsys: add missing MODULE_DEVICE_TABLE() Sasha Levin
` (504 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Yang Wang, Hawking Zhang, Alex Deucher, Sasha Levin, kenneth.feng,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Yang Wang <kevinyang.wang@amd.com>
[ Upstream commit 3a8d8e0b7f61cd759d5d4870b6220161f8a5b114 ]
The Vega hwmgr PowerPlay table parsers read fixed table fields,
state array entries, or SMC PPT fields before validating that the
VBIOS table buffer covers those structures. A truncated table can
therefore lead to out-of-bounds reads during hwmgr initialization.
Reject tables smaller than the fixed PowerPlay table. For Vega10, also
validate the state array offset and entry range before dereferencing
the state array.
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: the 6.18.53 tree still has the unvalidated Vega
parsers, the patch applies cleanly, and it closes a real out-of-bounds
read on init and `pp_table` upload.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[drm/amd/pm] [Validate] Vega hwmgr PowerPlay table bounds` —
add missing size/offset checks before parsing Vega10/12/20 PowerPlay
tables.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Yang Wang <kevinyang.wang@amd.com>` (author)
- `Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>` (AMD)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (drm/amd
maintainer)
- Pipeline-added tags ignored per instructions (`[Upstream commit
3a8d8e0b7f61...]`, `Signed-off-by: Sasha Levin`)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Cc: stable`, `Link:`, or
syzbot tags (absence is expected)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: Vega hwmgr parsers read fixed PowerPlay fields, Vega10 state-
array entries, or Vega12/20 SMC PPT fields without checking that
`soft_pp_table` is large enough.
- Symptom: out-of-bounds reads during hwmgr initialization (GPU probe /
table re-init).
- Root cause: truncated or offset-corrupt VBIOS/custom PPTable; pointer
arithmetic from `usStateArrayOffset` and struct-sized reads happen
before a size check.
- No specific kernel-version range in the message.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. Explicit memory-safety fix (OOB read). Also
corrects `entry_index <= ucNumEntries` to `<` (off-by-one).
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `vega10_processpptables.c`: +43/−21 (refactor `check_powerplay_tables`
into `get_vega10_state_array`; reuse it from entry lookup)
- `vega12_processpptables.c`: +7
- `vega20_processpptables.c`: +7
- Net: 52 insertions, 21 deletions; three files, one subsystem
- Functions: `get_vega10_state_array` (new), `check_powerplay_tables`
(all three), `vega10_get_number_of_powerplay_table_entries`,
`vega10_get_powerplay_table_entry`
- Scope: surgical, same-family parsers only
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Vega10 before: `check_powerplay_tables` / entry getters add
`usStateArrayOffset` to the table pointer, then read `ucNumEntries`
with no size check. Offset/revision checks happen *after* that
dereference.
- Vega10 after: require `soft_pp_table_size >=
sizeof(*powerplay_table)`; then offset `<= table_size -
sizeof(*state_arrays)`; then `struct_size(..., ucNumEntries) <=
remaining`.
- Vega12/20 before: only format_revision / structuresize (and Vega20 SMC
version).
- Vega12/20 after: also `table_size >= offsetofend(..., smcPPTable)`
before those field reads.
- Vega10 entry lookup: `entry_index <= ucNumEntries` → `entry_index <
ucNumEntries`.
- Path: init/error-reject of bad tables, not a new feature path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Memory safety / OOB read**, plus a **logic off-by-one**.
- Mechanism: VBIOS/custom table is smaller than the structures, or
`usStateArrayOffset`/`ucNumEntries` describe data past the buffer. The
driver still computed pointers and read them.
- Fix: reject before dereference using `soft_pp_table_size` (already
filled by `smu_atom_get_data_table` / cached table).
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct integer bounds checks. Uses existing
`struct_size` / `offsetofend`. Reject path is the same
`PP_ASSERT_WITH_CODE(... return -1)` style already used. Regression risk
is low: a genuine Vega PPTable is at least the header/SMC-PPT size.
Worst case a truncated table that previously “worked” by reading
adjacent BIOS bytes would now fail init instead of over-reading — that
is the intended failure mode. No API/lock/data-structure changes.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Vega10 `check_powerplay_tables`: `f83a9991648bb4` (Eric Huang,
2017-03-06)
- Vega12: `2cac05dee6e309` (Evan Quan, 2018-03-19)
- Vega20: `da958630d53025` (Evan Quan, 2018-08-02)
- Bug is long-standing (4.x/5.x era), present throughout 6.18.y.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Not applicable.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same-author series (2026-06-23), of which this is **patch 4/5**:
1. `Validate pp_table header before reading size` (swsmu)
2. `Use uploaded size for legacy custom PPTable` (`amd_powerplay.c`)
3. `Validate Tonga PowerPlay state array bounds`
4. **This commit**
5. `Validate legacy hwmgr PP table offsets`
Follow-up (separate series): `Validate Vega10 PPTable subtable bounds` —
more subtables, not a prerequisite for these checks.
None of 1–5 are in `v6.18.53`. This hunk does not need 1–3 to compile or
run: it only uses `hwmgr->soft_pp_table_size`, which
`get_powerplay_table()` already sets in this tree.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Yang Wang is an AMD pm contributor with a run of PPTable
bounds/UAF fixes (`fix pptable use-after-free` is already in v6.18.53).
Hawking Zhang reviewed; Alex Deucher merged.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone for these three files. `struct_size` and
`offsetofend` exist (`include/linux/overflow.h`,
`include/linux/stddef.h`). Flexible-array `states[]` is already in
v6.18.53 (`bae82e8418234` is an ancestor). Patch 2/5 (upload size) makes
short sysfs uploads match `soft_pp_table_size`; this patch still stops
offsets past the *allocated* buffer on 6.18.53, because that tree keeps
the original VBIOS size as the buffer size.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 3a8d8e0b7f61...` → https://patch.msgid.link/20260623034151.
263746-4-kevinyang.wang@amd.com
- Series: v1 `[PATCH 1/5] ... [PATCH 5/5]`; this is 4/5. `b4 dig -a`
showed only this v1 (no later revision of *this* patch).
- Mbox: Hawking Zhang: “Series is Reviewed-by: Hawking Zhang”. No NAK,
no stable-risk comments.
- lore.kernel.org HTTP fetch returned 403; discussion recovered via `b4
dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc `amd-gfx@lists.freedesktop.org`, Alex
Deucher, Hawking Zhang, Kenneth Feng. Maintainer merge + AMD review.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No `Reported-by` / bugzilla / syzbot. Author-driven audit of
PPTable parsers, consistent with the rest of the series. Trigger is
still real (init + sysfs upload), not speculative code.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Self-contained Vega header/state-array/SMC-PPT checks. Follow-up
subtable patch is extra coverage, not required for these checks to be
correct.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: UNVERIFIED — `lore.kernel.org/stable/` returned 403. No evidence
in-tree of a prior rejection.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `get_vega10_state_array`, `check_powerplay_tables`
(vega10/12/20), `vega10_get_number_of_powerplay_table_entries`,
`vega10_get_powerplay_table_entry`.
**Step 5.2: TRACE CALLERS**
Record:
- `check_powerplay_tables` ← `vega10_pp_tables_initialize` / vega12/20
equivalents, and `vega10_baco_set_cap`
- `pptable_init` ← `hwmgr.c` during hwmgr init
- `vega10_get_number_of_powerplay_table_entries` / `get_pp_table_entry`
← `psm_init_power_state_table()` (`for (i = 0; i < table_entries;
i++)`)
- Context: process/workqueue GPU init, not IRQ. Also re-entered from
`pp_dpm_set_pp_table` → `amd_powerplay_reset` → `hwmgr_hw_init`.
**Step 5.3: TRACE CALLEES**
Record: `get_powerplay_table` → `smu_atom_get_data_table` (pointer into
ATOM BIOS + ATOM-reported size). `PP_ASSERT_WITH_CODE` warns and runs
`return -1`. No new allocations/locks.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable on every Vega10/12/20 GPU probe. Also reachable from
sysfs `pp_table` (`AMDGPU_DEVICE_ATTR_RW` → `S_IRUGO | S_IWUSR`, root
write). Unprivileged users cannot write it; root/firmware can still
drive the OOB.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same pattern in Tonga (`process_pptables_v1_0.c`) and legacy
(`processpptables.c`) in the same series. Vega12
`get_powerplay_table_entry` still uses a raw offset after this patch;
Vega10 is the family that actually walks a state array here. Remaining
holes are why the follow-up exists; they do not invalidate this patch.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. Local tree is **6.18.53** (`git describe HEAD` →
`v6.18.53-5049-g0f0bdc2b0dffb`, `make kernelversion` → 6.18.53). `git
merge-base --is-ancestor 10510a4c2c397 v6.18.53` is false. `v6.18.53`
`check_powerplay_tables` still dereferences the state array / SMC PPT
with no size check.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply onto v6.18.53 file contents (`patch --dry-run` on
the three files succeeded). `git apply --check` on current HEAD fails
only because the candidate + follow-up are already stacked on the
autosel branch.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: The older `fix pptable use-after-free` is in v6.18.53. No
equivalent Vega bounds check is. v6.18.53 `pp_dpm_set_pp_table` still
`memcpy`s into a buffer sized from the original VBIOS table and does
**not** shrink `soft_pp_table_size`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/gpu/drm/amd/pm/powerplay` — Vega PowerPlay table
parsing. **IMPORTANT** (common AMD dGPU driver; Vega10/12/20 still in
the field). Not core mm/net, not staging.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature parser (2017–2018) with recent bounds-hardening. Long-
lived bug, not churn from a new subsystem.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific: Vega10/Vega12/Vega20 amdgpu powerplay. Also
anyone writing `/sys/class/drm/card*/device/pp_table` on those GPUs.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Normal good VBIOS: not triggered.
- Truncated/corrupt ATOM PPTable at probe: GPU init OOB.
- Root write of a crafted `pp_table` that re-inits hwmgr: same path.
- Unprivileged: no (sysfs is `S_IWUSR`).
- Off-by-one `<=` is latent: `psm_init_power_state_table` uses `i <
table_entries`, so the common loop never passes `entry_index ==
ucNumEntries`. Still a real bounds bug if any caller passes
`ucNumEntries`.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Kernel OOB read (KASAN/oops, possible info leak from adjacent
BIOS/kmalloc). Init failure on reject is the safe outcome. Severity:
**HIGH** (memory safety). Not a guaranteed panic on every boot.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: HIGH for Vega + custom PPTable users; stops OOB on init.
- Risk: LOW (~50 lines, assert-and-return, no locking/API).
- Ratio: favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB read in GPU power-management init, present since 2017/2018 in
this 6.18 tree
- Triggerable from truncated VBIOS and from root `pp_table` sysfs re-
init
- Small, obviously correct bounds checks; AMD Reviewed-by + maintainer
SOB
- Applies cleanly to v6.18.53; helpers already present
- Matches stable’s buffer-overflow / memory-safety class
AGAINST:
- No public crash/syzbot/CVE write-up
- Privileged sysfs / firmware trigger, not unprivileged
- Series 4/5; later patch covers more Vega10 subtables (not required for
this hunk)
- Good VBIOS never hits it
UNRESOLVED:
- Stable-list discussion (lore.kernel.org/stable 403)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — integer bounds; reviewed and
merged by AMD
2. Fixes a real bug that affects users? **PASS** — OOB read of PPTable
buffer
3. Important issue? **PASS** — memory-safety OOB (HIGH), not a style fix
4. Small and contained? **PASS** — 3 files, ~50 net lines
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — v6.18.53 still has the bug;
dry-run apply clean
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/docs exception. Ordinary memory-safety
bugfix.
**Step 9.4: MAKE YOUR DECISION**
Backport. This tree still performs unvalidated Vega PPTable pointer math
during hwmgr init. The patch is the minimal, already-reviewed guard for
that path.
What it solves for 6.18.y users: Vega probe and `pp_table` reload can
read past the PowerPlay buffer if the table is short or
`usStateArrayOffset`/`ucNumEntries` (Vega10) / SMC PPT (Vega12/20) stick
past `soft_pp_table_size`. That is an OOB read, not a feature.
Risk vs benefit: low-risk reject-invalid-table change vs stopping kernel
over-reads on a supported amdgpu path.
Concerns: more complete subtable checks come later; v6.18.53 custom-
upload still keeps the old VBIOS size (patch 2/5). Neither blocks this
patch: it still applies and still stops offsets past the allocated
buffer.
Verification:
- [Phase 1] Tags: author Yang Wang; Reviewed-by Hawking Zhang; SOB Alex
Deucher; no Fixes/syzbot
- [Phase 2] Diff: 52/21 across three Vega processpptables files;
size/offset checks + off-by-one
- [Phase 3] Blame: Vega10 2017 (`f83a9991648bb4`), Vega12 2018, Vega20
2018; present in v6.18.53
- [Phase 3] Series 4/5; no code dependency on 1–3 for these files
- [Phase 3] `struct_size`/`offsetofend` and flexible `states[]` already
in this tree
- [Phase 4] `b4 dig -c 3a8d8e0b7f61...` → msgid 20260623034151.263746-4;
series R-b from Hawking; no NAK
- [Phase 4] lore.kernel.org HTTP 403; mbox via `b4 dig -m` used instead
- [Phase 5] Callers: `pptable_init` from `hwmgr.c`;
`psm_init_power_state_table`; `pp_dpm_set_pp_table` reset
- [Phase 5] `smu_atom_get_data_table` returns BIOS pointer + ATOM size
- [Phase 6] `git describe HEAD` v6.18.53-5049; `merge-base --is-
ancestor` vs v6.18.53: not present; buggy code confirmed in `git show
v6.18.53:...`
- [Phase 6] `patch --dry-run` on v6.18.53 copies of the three files:
clean
- [Phase 8] Failure mode: OOB read during hwmgr init; sysfs `pp_table`
is `S_IWUSR`
- UNVERIFIED: stable@ mailing-list thread (HTTP 403)
**YES**
.../powerplay/hwmgr/vega10_processpptables.c | 59 ++++++++++++-------
.../powerplay/hwmgr/vega12_processpptables.c | 7 +++
.../powerplay/hwmgr/vega20_processpptables.c | 7 +++
3 files changed, 52 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c
index 3be616af327ef..64cff9f4850a6 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c
@@ -63,14 +63,17 @@ static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
return table_address;
}
-static int check_powerplay_tables(
- struct pp_hwmgr *hwmgr,
- const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
+static int get_vega10_state_array(struct pp_hwmgr *hwmgr,
+ const ATOM_Vega10_POWERPLAYTABLE *powerplay_table,
+ const ATOM_Vega10_State_Array **state_array)
{
const ATOM_Vega10_State_Array *state_arrays;
+ u16 state_array_offset;
+ size_t state_array_size;
+ size_t table_size = hwmgr->soft_pp_table_size;
- state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)powerplay_table) +
- le16_to_cpu(powerplay_table->usStateArrayOffset));
+ PP_ASSERT_WITH_CODE((table_size >= sizeof(*powerplay_table)),
+ "Invalid PowerPlay Table!", return -1);
PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
ATOM_Vega10_TABLE_REVISION_VEGA10),
@@ -79,12 +82,34 @@ static int check_powerplay_tables(
"State table is not set!", return -1);
PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0,
"Invalid PowerPlay Table!", return -1);
+
+ state_array_offset = le16_to_cpu(powerplay_table->usStateArrayOffset);
+ PP_ASSERT_WITH_CODE((state_array_offset <=
+ table_size - sizeof(*state_arrays)),
+ "Invalid PowerPlay Table!", return -1);
+
+ state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)powerplay_table) +
+ state_array_offset);
PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
"Invalid PowerPlay Table!", return -1);
+ state_array_size = struct_size(state_arrays, states, state_arrays->ucNumEntries);
+ PP_ASSERT_WITH_CODE((state_array_size <= table_size - state_array_offset),
+ "Invalid PowerPlay Table!", return -1);
+
+ *state_array = state_arrays;
+
return 0;
}
+static int check_powerplay_tables(struct pp_hwmgr *hwmgr,
+ const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
+{
+ const ATOM_Vega10_State_Array *state_arrays;
+
+ return get_vega10_state_array(hwmgr, powerplay_table, &state_arrays);
+}
+
static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
{
set_hw_cap(
@@ -1249,15 +1274,14 @@ int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr)
{
const ATOM_Vega10_State_Array *state_arrays;
const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
+ int result;
PP_ASSERT_WITH_CODE((pp_table != NULL),
"Missing PowerPlay Table!", return -1);
- PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >=
- ATOM_Vega10_TABLE_REVISION_VEGA10),
- "Incorrect PowerPlay table revision!", return -1);
- state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) +
- le16_to_cpu(pp_table->usStateArrayOffset));
+ result = get_vega10_state_array(hwmgr, pp_table, &state_arrays);
+ PP_ASSERT_WITH_CODE((result == 0),
+ "Invalid PowerPlay Table State Array.", return result);
return (uint32_t)(state_arrays->ucNumEntries);
}
@@ -1308,17 +1332,11 @@ int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr,
if (pp_table->sHeader.format_revision >=
ATOM_Vega10_TABLE_REVISION_VEGA10) {
- state_arrays = (ATOM_Vega10_State_Array *)
- (((unsigned long)pp_table) +
- le16_to_cpu(pp_table->usStateArrayOffset));
-
- PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0,
- "Invalid PowerPlay Table State Array Offset.",
- return -1);
- PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
+ result = get_vega10_state_array(hwmgr, pp_table, &state_arrays);
+ PP_ASSERT_WITH_CODE((result == 0),
"Invalid PowerPlay Table State Array.",
- return -1);
- PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
+ return result);
+ PP_ASSERT_WITH_CODE((entry_index < state_arrays->ucNumEntries),
"Invalid PowerPlay Table State Array Entry.",
return -1);
@@ -1360,4 +1378,3 @@ int vega10_baco_set_cap(struct pp_hwmgr *hwmgr)
PHM_PlatformCaps_BACO);
return result;
}
-
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c
index 89148f73b514a..8e6b1565d00de 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c
@@ -64,6 +64,13 @@ static int check_powerplay_tables(
struct pp_hwmgr *hwmgr,
const ATOM_Vega12_POWERPLAYTABLE *powerplay_table)
{
+ size_t smc_pptable_size =
+ offsetofend(ATOM_Vega12_POWERPLAYTABLE, smcPPTable);
+ size_t table_size = hwmgr->soft_pp_table_size;
+
+ PP_ASSERT_WITH_CODE((table_size >= smc_pptable_size),
+ "Invalid PowerPlay Table!", return -1);
+
PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
ATOM_VEGA12_TABLE_REVISION_VEGA12),
"Unsupported PPTable format!", return -1);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c
index 2b446f8866bac..0d008573c0388 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c
@@ -66,6 +66,13 @@ static int check_powerplay_tables(
struct pp_hwmgr *hwmgr,
const ATOM_Vega20_POWERPLAYTABLE *powerplay_table)
{
+ size_t smc_pptable_size =
+ offsetofend(ATOM_Vega20_POWERPLAYTABLE, smcPPTable);
+ size_t table_size = hwmgr->soft_pp_table_size;
+
+ PP_ASSERT_WITH_CODE((table_size >= smc_pptable_size),
+ "Invalid PowerPlay Table!", return -1);
+
PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
ATOM_VEGA20_TABLE_REVISION_VEGA20),
"Unsupported PPTable format!", return -1);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] clk: mediatek: mt6735-vencsys: add missing MODULE_DEVICE_TABLE()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (11 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm: Validate Vega hwmgr PowerPlay table bounds Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] selftests: net: reuseport_bpf_numa: consider cpuless numa node Sasha Levin
` (503 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Brian Masney, Sasha Levin, y.oudjana, sboyd,
bmasney+clk, jbrunet+clk, matthias.bgg, angelogioacchino.delregno,
linux-clk, linux-mediatek, linux-kernel, linux-arm-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 36cf8d279ff90835f4b002dec28eedb059554842 ]
The driver has an OF match table wired to .of_match_table, but does
not export the table with MODULE_DEVICE_TABLE().
Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias
information is generated for OF based module autoloading.
This is a source-level fix. It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the platform driver, and the missing module alias publication.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Signed-off-by: Brian Masney <bmasney@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Connection lost, reconnecting to https://agentn.us.api5.cursor.sh
(attempt 1)...
Retry attempt 1...
This tree is **Linux 7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
driver exists here; the change is a one-line `MODULE_DEVICE_TABLE(of,
...)` so the vencsys clock module can autoload from DT.
## Phase 1: Commit message forensics
**Step 1.1: Subject line**
- Record: `[clk/mediatek] [add] add missing MODULE_DEVICE_TABLE() for
mt6735-vencsys`
**Step 1.2: Tags**
- Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** Brian Masney `<bmasney@redhat.com>` (COMMON CLK
FRAMEWORK maintainer)
- **Acked-by:** none
- **Link:** none in the commit; mailing list found via `b4 dig`
- **Cc: stable:** none (not a negative signal)
- **Signed-off-by:** Pengpeng Hou `<pengpeng@iscas.ac.cn>` (author);
Brian Masney `<bmasney@redhat.com>` (clk maintainer who applied it)
- Notable: maintainer review + maintainer SOB; no user/syzbot report
**Step 1.3: Body**
- Record:
- **Bug:** OF match table is wired to `.of_match_table` but not
exported with `MODULE_DEVICE_TABLE()`, so `file2alias` does not emit
`of:` aliases.
- **Symptom:** when `CONFIG_COMMON_CLK_MT6735_VENCSYS=m`,
udev/modprobe cannot autoload `clk-mt6735-vencsys` from
`mediatek,mt6735-vencsys`.
- **Version info:** none in the message. Git: driver added in
**v6.13-rc1** (`0bd9b1211f741`); this fix first appears in
**v7.3-rc1**.
- **Root cause:** omitted alias publication, not a runtime logic
error.
**Step 1.4: Hidden bug fix?**
- Record: Not hidden. It is a real functional gap (module autoload), not
a crash/UAF. The “source-level fix / no hardware reproduction” wording
matches the original lore submission, not pipeline decoration.
## Phase 2: Diff analysis
**Step 2.1: Inventory**
- Record:
- `drivers/clk/mediatek/clk-mt6735-vencsys.c`: **+1 / -0**
- Function/data: `of_match_mt6735_vencsys[]` (file scope)
- Scope: single-file, one-line surgical change
**Step 2.2: Code flow**
- Record: Before, the table is only consumed by
`platform_driver.driver.of_match_table` (bind if the module is already
loaded or built-in). After, `MODULE_DEVICE_TABLE(of,
of_match_mt6735_vencsys)` also creates a `__mod_device_table` alias so
`scripts/mod/file2alias.c` `do_of_entry()` emits
`of:N*T*Cmediatek,mt6735-vencsys`. Build-time metadata only; no probe-
path change.
**Step 2.3: Bug mechanism**
- Record: **Hardware matching / module autoload** (same class as missing
device IDs). Match table exists but is not published for modules.
**Step 2.4: Fix quality**
- Record: Obviously correct; matches sibling MT6735 files that shipped
with `MODULE_DEVICE_TABLE` (`apmixedsys`, `infracfg`, `pericfg`,
`topckgen`). No runtime lock/API/data-structure change. Regression
risk is essentially none. `imgsys` and `mfgcfg` still lack the macro;
this patch does not depend on those.
## Phase 3: Git history
**Step 3.1: Blame**
- Record: Match table and driver introduced by `0bd9b1211f741` (“clk:
mediatek: Add drivers for MT6735 syscon clock and reset controllers”,
Yassine Oudjana, 2024-11-06, applied 2024-11-14). First in
**v6.13-rc1**. `MODULE_DEVICE_TABLE` line is this commit
`36cf8d279ff90`.
**Step 3.2: Fixes: tag**
- Record: No `Fixes:` tag. The omission dates from the introducing
commit `0bd9b1211f741`, which **is** an ancestor of this tree.
**Step 3.3: File history**
- Record: Only two commits on this file: introducer + this fix. No later
conflicting refactor. Sibling same-day commit `096ab64a0e694` does the
same for `clk-mt6735-vdecsys.c`. Standalone; not patch 2/N.
**Step 3.4: Author**
- Record: Pengpeng Hou is not the MT6735 clk maintainer (that is Yassine
Oudjana). Same author also added `MODULE_DEVICE_TABLE` in `clk-
mt6735-vdecsys.c` and two i.MX clk drivers. Applied by clk co-
maintainer Brian Masney.
**Step 3.5: Dependencies**
- Record: None. Uses existing `MODULE_DEVICE_TABLE` / `of_device_id`.
Applies on top of the original driver with no prerequisites.
## Phase 4: Mailing list and external research
**Step 4.1: Original discussion**
- Record: `b4 dig -c 36cf8d279ff90` →
https://patch.msgid.link/20260704124808.19916-1-pengpeng@iscas.ac.cn
- `b4 dig -a`: **v1 only** (2026-07-04). Applied version is that v1.
- Thread (mbox): author patch + Brian Masney `Reviewed-by`. No NAK, no
stable nomination, no risk discussion.
**Step 4.2: Recipients (`b4 dig -w`)**
- Record: Yassine Oudjana (MT6735 clk maintainer), Stephen Boyd, Brian
Masney, Michael Turquette, Matthias Brugger, AngeloGioacchino Del
Regno; `linux-clk`, `linux-mediatek`, `linux-arm-kernel`, `linux-
kernel`. Right maintainers and lists.
**Step 4.3: Bug report**
- Record: No Reported-by, no syzbot, no bugzilla. Author states there
was no hardware reproduction.
**Step 4.4: Series**
- Record: Independent single patches (vencsys + vdecsys), not a numbered
series. This commit does not need the vdecsys patch.
**Step 4.5: Stable list**
- Record: **UNVERIFIED.** `curl` to lore.kernel.org/stable returned HTTP
403. No in-tree evidence this was rejected for stable.
## Phase 5: Code semantic analysis
**Step 5.1: Functions**
- Record: No function body changed. Adds `MODULE_DEVICE_TABLE` next to
`of_match_mt6735_vencsys[]`. Driver still uses
`module_platform_driver` → `mtk_clk_simple_probe` /
`mtk_clk_simple_remove`.
**Step 5.2: Callers**
- Record: Platform core binds via OF compatible. Probe is boot/device-
instantiation, not a syscall hot path. Impact is whether the **module
is loaded at all**.
**Step 5.3: Callees**
- Record: Unchanged. `mtk_clk_simple_probe()` in `clk-mtk.c` registers
the vencsys gates from `vencsys_clks`.
**Step 5.4: Reachability**
- Record: Reachable when DT has `mediatek,mt6735-vencsys` and the driver
is a module. **No in-tree `.dts`/`.dtsi` uses that compatible** (only
`Documentation/devicetree/bindings/clock/mediatek,syscon.yaml`). Users
need out-of-tree DT (typical for older MT6735 phones). Built-in (`=y`)
is unaffected.
**Step 5.5: Similar patterns**
- Record: Same omission still present in `clk-mt6735-imgsys.c` and `clk-
mt6735-mfgcfg.c`. Four other MT6735 clk files had
`MODULE_DEVICE_TABLE` from day one (`43c04ed791892` for apmixedsys).
Pattern is systematic but this patch is complete for vencsys.
## Phase 6: Local tree cross-reference
**Step 6.1: Buggy code in this tree?**
- Record: Yes. File exists; current tree already has the fix at line 40.
Bug was the missing alias from v6.13 until v7.3-rc1.
`CONFIG_COMMON_CLK_MT6735_VENCSYS` is **tristate**.
**Step 6.2: Backport difficulty**
- Record: **Clean apply.** File is essentially unchanged since
introduction. One inserted line after the match table.
**Step 6.3: Related fixes already here**
- Record: This exact commit is already an ancestor of HEAD (`git merge-
base --is-ancestor 36cf8d279ff90 HEAD` → yes). That is mainline
history, not a reason to reject on merit. No alternate fix. Sibling
vdecsys fix is also present; imgsys/mfgcfg still missing.
## Phase 7: Subsystem context
**Step 7.1: Subsystem / criticality**
- Record: `drivers/clk/mediatek/` — SoC clock driver. **PERIPHERAL**
(MT6735 video-encoder clocks only). Not mm/fs/net core.
**Step 7.2: Activity**
- Record: Mediatek clk is actively maintained; this file is not. Two
commits total. Mature omission, not churn.
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
- Record: Only MT6735 systems with `CONFIG_COMMON_CLK_MT6735_VENCSYS=m`
and a DT node `mediatek,mt6735-vencsys`. Driver- and config-specific;
small population (no in-tree board DTS).
**Step 8.2: Trigger**
- Record: Modular boot + OF device present. Not a race. Unprivileged
users do not trigger it; udev autoload fails. Built-in and manual
`modprobe` work.
**Step 8.3: Failure mode**
- Record: Module does not autoload → vencsys clocks (smi_larb3, venc,
jpgenc, jpgdec) never register → video encode/JPEG on that SoC can
fail. **Severity: MEDIUM** (functional miss, not
oops/corruption/deadlock). Fits stable-rules “oh, that’s not good” and
the device-ID-style enablement exception.
**Step 8.4: Risk-benefit**
- Record: **Benefit:** correct autoload for a supported tristate driver;
one line. **Risk:** negligible (modinfo/depmod metadata only). Ratio
favors applying it on trees that have this driver.
## Phase 9: Final synthesis
**Step 9.1: Evidence**
FOR:
- Real autoload bug: match table used, aliases not published
- One line, obviously correct, reviewed and applied by clk maintainer
Brian Masney
- Driver is tristate; modular build is an intended config
- Same class as device-ID additions (publish existing OF IDs)
- Sibling MT6735 files already had the macro; this was an omission from
`0bd9b1211f741`
- Zero runtime regression risk; applies cleanly
- Driver and bug exist in this 7.3 tree (introduced v6.13)
AGAINST:
- Not a crash, UAF, deadlock, or security issue
- No user report and no hardware reproduction
- No in-tree DT consumer for this compatible
- Niche SoC; often clocks are built-in
UNRESOLVED:
- Whether this was discussed on the stable list (lore HTTP 403)
**Step 9.2: Stable rules checklist**
1. Obviously correct and tested? **PASS** — one-line, standard macro,
maintainer Reviewed-by/SOB. No runtime test; correctness is
mechanical.
2. Real bug that affects users? **PASS** — modular OF autoload is
broken. User set is small but real if they use `=m`.
3. Important issue? **PASS** (low end of “oh, that’s not good” /
hardware-enablement), not CRITICAL.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS** — publishes existing match table.
6. Can apply to this tree? **PASS** — file and table exist; patch is a
clean one-liner.
**Step 9.3: Exception category**
- Record: Closest match is **device ID / hardware matching** (OF module
aliases), not a new driver.
**Step 9.4: Decision**
Backport this. It is a one-line, obviously correct fix for failed OF
module autoload on an existing tristate driver. That is the same kind of
enablement stable already takes for new device IDs, with no runtime
behavior change if the module is built-in or loaded by other means. This
7.3 tree has the driver (since v6.13); there are no missing
prerequisites. Limited hardware and no crash report lower urgency, not
correctness.
### What it solves for stable users
If `clk-mt6735-vencsys` is a module, userspace cannot match
`mediatek,mt6735-vencsys` and load it. Video-encoder clocks then never
appear. `MODULE_DEVICE_TABLE(of, ...)` generates the aliases
`file2alias` already knows how to emit.
### Risk vs benefit
Benefit is correct autoload on MT6735 modular configs. Risk is
negligible: no probe, locking, or ABI change.
## Verification
- [Phase 1] Parsed tags: Reviewed-by + SOB Brian Masney; no
Fixes/Reported-by/Cc:stable
- [Phase 1] `git show -s 36cf8d279ff90`: body matches the candidate;
“source-level fix” is in the real commit and lore v1
- [Phase 2] Diff: +1 `MODULE_DEVICE_TABLE(of, of_match_mt6735_vencsys)`
in `clk-mt6735-vencsys.c`
- [Phase 2] `include/linux/module.h` and `scripts/mod/file2alias.c`
`do_of_entry()`: confirmed alias generation from that macro
- [Phase 3] `git blame`: table from `0bd9b1211f741` (v6.13-rc1); macro
from `36cf8d279ff90`
- [Phase 3] `git describe --contains 0bd9b1211f741`: v6.13-rc1; fix
contained in v7.3-rc1; `git merge-base --is-ancestor` vs v7.2: not in
v7.2
- [Phase 3] File log: only introducer + this commit; sibling
`096ab64a0e694` for vdecsys
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 lore thread; Masney Reviewed-by;
correct clk/mediatek CCs; no NAK
- [Phase 4] WebFetch lore/msgid.link: HTTP 403; used mbox instead
- [Phase 5] Kconfig: `COMMON_CLK_MT6735_VENCSYS` tristate; Makefile
`obj-$(CONFIG_COMMON_CLK_MT6735_VENCSYS)`
- [Phase 5] `mtk_clk_simple_probe` in `clk-mtk.c` used unchanged
- [Phase 5] Grep: no in-tree dts/dtsi `mediatek,mt6735-vencsys`; binding
in `mediatek,syscon.yaml`
- [Phase 5] imgsys/mfgcfg still lack `MODULE_DEVICE_TABLE`
- [Phase 6] `make kernelversion` / `git describe HEAD`: 7.3.0-rc4 /
v7.3-rc4-27-gf0100363d8c37
- [Phase 6] File currently contains the macro; `git merge-base --is-
ancestor 36cf8d279ff90 HEAD` = yes
- [Phase 7] MAINTAINERS: MT6735 clk → Yassine Oudjana; COMMON CLK →
Stephen Boyd, Brian Masney, Jerome Brunet
- [Phase 8] Failure mode: missing module autoload, not oops; severity
MEDIUM
- UNVERIFIED: stable@ lore discussion (HTTP 403)
**YES**
drivers/clk/mediatek/clk-mt6735-vencsys.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/clk/mediatek/clk-mt6735-vencsys.c b/drivers/clk/mediatek/clk-mt6735-vencsys.c
index 8dec7f98492ac..64ba9da9fd427 100644
--- a/drivers/clk/mediatek/clk-mt6735-vencsys.c
+++ b/drivers/clk/mediatek/clk-mt6735-vencsys.c
@@ -37,6 +37,7 @@ static const struct of_device_id of_match_mt6735_vencsys[] = {
{ .compatible = "mediatek,mt6735-vencsys", .data = &vencsys_clks },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, of_match_mt6735_vencsys);
static struct platform_driver clk_mt6735_vencsys = {
.probe = mtk_clk_simple_probe,
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] selftests: net: reuseport_bpf_numa: consider cpuless numa node
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (12 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] clk: mediatek: mt6735-vencsys: add missing MODULE_DEVICE_TABLE() Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] nvme: zns: cap zone report nr_zones by DMA buffer size Sasha Levin
` (502 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Feng Tang, Simon Horman, Paolo Abeni, Sasha Levin, davem,
edumazet, kuba, shuah, netdev, linux-kselftest, linux-kernel
From: Feng Tang <feng.tang@linux.alibaba.com>
[ Upstream commit 88b8d85e889e2fe1cce3e66e50c3029dda94842a ]
reuseport_bpf_numa case failed when testing on a platform with CXL
memory:
#./reuseport_bpf_numa
---- IPv4 UDP ----
send node 0, receive socket 0
./reuseport_bpf_numa: failed to pin to node: Invalid argument
The root cause is that the platform has 2 numa nodes: node 0 has
both cpu and memory, while node 1 is a CXL node which only has
memory, and caused numa_run_on_node() to fail.
Add sanity check to skip cpuless numa node for the numa binding test.
Signed-off-by: Feng Tang <feng.tang@linux.alibaba.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260807002436.43991-1-feng.tang@linux.alibaba.com
Signed-off-by: Paolo Abeni <pabeni@redhat.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: `[selftests: net]` `[consider]` skip CPU-less NUMA nodes in
`reuseport_bpf_numa` so the test does not abort when
`numa_run_on_node()` cannot pin to a memory-only node.
**Step 1.2: Tags**
- Record: `Reviewed-by: Simon Horman <horms@kernel.org>`; `Link: https:/
/patch.msgid.link/20260807002436.43991-1-feng.tang@linux.alibaba.com`;
`Signed-off-by: Feng Tang <feng.tang@linux.alibaba.com>`; `Signed-off-
by: Paolo Abeni <pabeni@redhat.com>`.
- No `Fixes:`, no `Reported-by:`, no `Tested-by:`, no `Cc: stable`
(absence is expected). Ignore any pipeline `Signed-off-by: Sasha
Levin` / `[Upstream commit ...]` markers.
**Step 1.3: Body**
- Record: On a 2-node CXL box, node 0 has CPU+memory and node 1 is
memory-only. The test prints `send node 0, receive socket 0` then dies
with `failed to pin to node: Invalid argument` from
`numa_run_on_node()`. Root cause is treating every bit in
`numa_nodes_ptr` as a pin-able CPU node. Fix: skip CPU-less nodes.
**Step 1.4: Hidden bug fix?**
- Record: Yes. “Consider” is test-robustness language, but the program
currently `error(1, ...)` and fails. This is a real false failure, not
style cleanup.
## Phase 2: Diff analysis
**Step 2.1: Inventory**
- Record: One file, `tools/testing/selftests/net/reuseport_bpf_numa.c`.
About +24 lines. New helper `is_cpuless_node()`; `test()` gains two
`continue`s. Surgical, single-file, userspace selftest only.
**Step 2.2: Flow**
- Record: Before: both forward and reverse loops skip only nodes unset
in `numa_nodes_ptr`, then call `send_from_node()` which does
`numa_run_on_node()` and aborts on failure. After: also skip nodes
whose libnuma CPU mask has weight 0. Normal send/receive path for CPU-
bearing nodes is unchanged.
**Step 2.3: Bug mechanism**
- Record: Logic/correctness in a selftest. Memory-only NUMA nodes are
present in `numa_nodes_ptr` (the 2021 skip does not drop them) but
have an empty CPU mask, so pinning returns EINVAL. `is_cpuless_node()`
uses `numa_allocate_cpumask()` / `numa_node_to_cpus()` /
`numa_bitmask_weight()`; on helper error it returns false (do not
skip), which is conservative.
**Step 2.4: Fix quality**
- Record: Obviously correct and minimal. Skipping a CPU-less node is
right: `bpf_get_numa_node_id()` is the current CPU’s node, so a
memory-only node can never be the sender. Regression risk is very low
(userspace test only). Helper allocation failure still hits the old
abort path.
## Phase 3: Git history
**Step 3.1: Blame**
- Record: Loops come from `3c2c3c16aaf6a` (Daniel Borkmann, 2016-10-21,
“reuseport, bpf: add test case for bpf_get_numa_node_id”), first
contained in v4.10-rc1. The existing skip is `a38bc45a08e97` (Kleber
Sacilotto de Souza, 2021-11-01), contained in v5.16-rc1: skip nodes
not in `numa_nodes_ptr` (non-consecutive IDs). That does not cover
CPU-less memory nodes.
**Step 3.2: Fixes: tag**
- Record: None. Buggy assumption is in the original 2016 test, still
present here.
**Step 3.3: File history**
- Record: This tree only has later `0273d10182ec4` (ARRAY_SIZE warning),
then the 2021 skip, 2018 numa-skip-if-unavailable, SPDX, and the
original test. No `setup_netns()` in this file (0 matches).
Standalone; not patch X/Y.
**Step 3.4: Author**
- Record: Feng Tang has other tools/selftests work in this history (e.g.
mm `compaction_test`) but no other net `reuseport_bpf_numa` commits.
Not the net maintainer. Applied by Paolo Abeni after Simon Horman’s
review.
**Step 3.5: Prerequisites**
- Record: Needs existing libnuma usage (`numa_nodes_ptr`,
`numa_run_on_node`, `-lnuma`). All present. Makefile already has
`$(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma`. No missing kernel
APIs. Can apply standalone.
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
- Record: `b4 mbox` for msgid
`20260807002436.43991-1-feng.tang@linux.alibaba.com` returned 404;
lore.kernel.org fetches returned 403. Recovered from
Openwall/LKML/Patchew.
- v1 (`20260730113040.75718-1-...`): check inside `send_from_node()`,
return -1, no NULL check on `numa_allocate_cpumask()`.
- v2 (`[PATCH net v2]`): lift check into `test()`, add alloc-failure
handling; typo “unlikeyly”; unnecessary `inline`.
- v3 (`[PATCH net-next v3]`): spelling + drop `inline` (Jakub, Sashiko).
Committed version matches v3.
- No NAKs. No reviewer `Cc: stable` found.
**Step 4.2: Reviewers**
- Record: To/Cc included Jakub Kicinski, David Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan, Andi Kleen, netdev, linux-
kselftest, bpf. Jakub reviewed v2 (inline). Simon Horman `Reviewed-by`
on v3. Paolo applied.
**Step 4.3: Bug report**
- Record: Author reproduced on CXL hardware; commit body has the exact
abort. No syzbot/bugzilla. Severity for testers: hard FAIL after the
first successful node-0 send.
**Step 4.4: Series**
- Record: Single patch, three revisions. No sibling patches required.
**Step 4.5: Stable list**
- Record: No stable-list hit found. UNVERIFIED that nobody asked for it
on stable@ (lore 403).
## Phase 5: Semantic analysis
**Step 5.1: Functions**
- Record: Adds `is_cpuless_node()`. Touches `test()`. `send_from_node()`
unchanged.
**Step 5.2: Callers**
- Record: `is_cpuless_node` only from `test()`. `test()` only from
`main()` (IPv4/IPv6 × UDP/TCP). Userspace kselftest, not kernel.
**Step 5.3: Callees**
- Record: libnuma `numa_allocate_cpumask`, `numa_node_to_cpus`,
`numa_bitmask_weight`, `numa_bitmask_free`. Already linked with
`-lnuma`.
**Step 5.4: Reachability**
- Record: Triggered by running `./reuseport_bpf_numa` on NUMA
(`CONFIG_NUMA=y` in `tools/testing/selftests/net/config`) with at
least one CPU-less node. Not a syscall/kernel path.
**Step 5.5: Similar patterns**
- Record: Same file already skips unavailable nodes (`a38bc45a08e97`).
This is the CPU-less counterpart. No other `numa_run_on_node`
selftests in this tree.
## Phase 6: This tree (6.12.111)
**Step 6.1: Buggy code present?**
- Record: Yes. Local tree is `pending-6.12` / `p-6.12-3-gc504cf0baa3d8`,
`make kernelversion` = **6.12.111**. File has the 2016 loops and the
2021 `numa_nodes_ptr` skip, and still calls `send_from_node()` without
a CPU-less check (`git merge-base --is-ancestor` for both historical
commits succeeded). `git log --grep="consider cpuless"` on this file
is empty. CXL is in this tree (`drivers/cxl/`).
**Step 6.2: Backport difficulty**
- Record: Clean apply. The three functional contexts exist verbatim
(helper insertion after `attach_bpf()`, two loop sites). Mainline
trailing `setup_netns()` context is **not** in 6.12 and is not part of
the v3 hunks. `bool` is already used in other net selftests here
without extra headers.
**Step 6.3: Related fixes already here?**
- Record: Only the 2021 unavailable-node skip. It does not fix CXL
memory-only nodes. No equivalent `is_cpuless_node` fix.
## Phase 7: Subsystem context
**Step 7.1:** Record: `tools/testing/selftests/net` — kselftest for
SO_REUSEPORT + `bpf_get_numa_node_id`. Criticality: PERIPHERAL for
production runtime; IMPORTANT for people who run net kselftests (this
6.12.y tree already took ~100 `tools/testing/selftests/net` commits
since `v6.12`).
**Step 7.2:** Record: Net selftests are actively backported here (UAF in
tests, br_netfilter false failures, HZ=100 skips, portable timeouts,
etc.).
## Phase 8: Impact and risk
**Step 8.1:** Record: Testers running this binary on NUMA machines with
CPU-less nodes (CXL memory, similar memory-only nodes). Not a production
kernel path.
**Step 8.2:** Record: Trigger is running the selftest on that topology.
First CPU node can succeed; the next CPU-less node aborts. Unprivileged
if the test is run that way; not a kernel exploit path.
**Step 8.3:** Record: Failure mode = kselftest abort (`error(1, errno,
"failed to pin to node")`). Severity LOW–MEDIUM for the kernel (no
oops/corruption), HIGH for CI on those machines (hard fail).
**Step 8.4:** Record: Benefit medium for CXL/NUMA testers of 6.12.y;
risk very low (userspace, +24 lines, no kernel change). Ratio favors
backport on this tree, which already takes kselftest false-fail fixes.
## Phase 9: Synthesis
**For**
- Real, reproduced FAIL on CXL memory-only NUMA; 6.12 has both the test
and CXL.
- Completes the 2021 skip: `numa_nodes_ptr` still includes CPU-less
nodes.
- Small, reviewed, v3 is the applied form; no series deps.
- Applies cleanly here; zero kernel runtime risk.
- This tree regularly backports the same class (e.g. `selftests:
netfilter: packetdrill: avoid failure on HZ=100 kernel`,
vxlan/br_netfilter false-fail fixes).
- v2 was sent to `net` as a bugfix.
**Against**
- Not a kernel crash, security hole, or data-corruption fix.
- Affects one selftest on a subset of NUMA topologies.
- Final submission was `net-next`; no `Cc: stable` in the thread I could
read.
**Unresolved**
- Exact mainline SHA (not on this branch).
- lore.kernel.org / `b4` thread dump (403/404).
- Whether stable@ ever discussed it.
**Stable rules checklist**
1. Obviously correct and tested? **PASS** (libnuma weight 0; Reviewed-by
Horman; author reproduced).
2. Real bug that bothers people? **PASS** (hard selftest FAIL on real
CXL hardware).
3. Important (crash/security/corruption/deadlock)? **PASS** under this
tree’s documented “oh, that’s not good” / kselftest-false-fail
practice; not a production oops.
4. Small and contained? **PASS** (~24 lines, one file).
5. No new features/APIs? **PASS**.
6. Can apply to this tree? **PASS** (contexts verified).
**Exception category:** none of ID/quirk/DT/build/docs; it is a
kselftest correctness/robustness fix, which this 6.12.y tree already
accepts.
The test in 6.12.111 still assumes every exposed NUMA node has CPUs.
That is false on CXL memory-only nodes, so `reuseport_bpf_numa` aborts.
The patch only skips those nodes and does not change kernel behavior.
That is a contained, low-risk fix worth taking on this tree.
### Verification
- [Phase 1] Parsed tags: Reviewed-by Simon Horman; Link msgid; SOBs Feng
Tang / Paolo Abeni; no Fixes/Reported-by/Cc:stable.
- [Phase 2] Diff: +24 lines, `is_cpuless_node()` + two `continue`s in
`test()`; `send_from_node()` still `error(1)` on pin failure.
- [Phase 3] `git blame` loops: `3c2c3c16aaf6a` (2016) and
`a38bc45a08e97` (2021 skip). Both are ancestors of HEAD.
- [Phase 3] `git describe --contains`: original test v4.10-rc1; 2021
skip v5.16-rc1.
- [Phase 3] `git log --grep="consider cpuless"` on this file: empty (fix
not in tree).
- [Phase 4] `b4 mbox` msgid: 404; lore WebFetch: 403; used
Openwall/LKML/Patchew for v1–v3.
- [Phase 4] v1→v3: Sashiko NULL-check; lift skip out of
`send_from_node`; Jakub spelling/`inline`; Horman Reviewed-by; no NAK.
- [Phase 5] Callers: `main` → `test` → `send_from_node`; userspace only.
`grep numa_run_on_node` only this file under selftests.
- [Phase 6] `git describe HEAD` / `make kernelversion`: pending-6.12,
6.12.111. File matches patch contexts (`hunk1 present`, two loop
sites). No `setup_netns`. `drivers/cxl/` present. `CONFIG_NUMA=y` in
net selftest config. `-lnuma` already in Makefile.
- [Phase 6] `v6.12..HEAD -- tools/testing/selftests/net/`: 100 commits,
including false-fail/skip fixes.
- [Phase 8] Failure: selftest abort `failed to pin to node: Invalid
argument`; not a kernel oops.
- UNVERIFIED: lore.kernel.org full thread; stable@ discussion; mainline
SHA.
**YES**
.../selftests/net/reuseport_bpf_numa.c | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/tools/testing/selftests/net/reuseport_bpf_numa.c b/tools/testing/selftests/net/reuseport_bpf_numa.c
index c9ba36aa688e2..b04b511809ad2 100644
--- a/tools/testing/selftests/net/reuseport_bpf_numa.c
+++ b/tools/testing/selftests/net/reuseport_bpf_numa.c
@@ -104,6 +104,26 @@ static void attach_bpf(int fd)
close(bpf_fd);
}
+/*
+ * Return true if it is a cpuless node. Return false if it isn't or any
+ * error (very unlikely) happens during the libnuma calls.
+ */
+static bool is_cpuless_node(int node_id)
+{
+ struct bitmask *cpumask;
+ bool ret = false;
+
+ cpumask = numa_allocate_cpumask();
+ if (!cpumask)
+ return ret;
+
+ if (!numa_node_to_cpus(node_id, cpumask) && !numa_bitmask_weight(cpumask))
+ ret = true;
+
+ numa_bitmask_free(cpumask);
+ return ret;
+}
+
static void send_from_node(int node_id, int family, int proto)
{
struct sockaddr_storage saddr, daddr;
@@ -213,6 +233,8 @@ static void test(int *rcv_fd, int len, int family, int proto)
for (node = 0; node < len; ++node) {
if (!numa_bitmask_isbitset(numa_nodes_ptr, node))
continue;
+ if (is_cpuless_node(node))
+ continue;
send_from_node(node, family, proto);
receive_on_node(rcv_fd, len, epfd, node, proto);
}
@@ -221,6 +243,8 @@ static void test(int *rcv_fd, int len, int family, int proto)
for (node = len - 1; node >= 0; --node) {
if (!numa_bitmask_isbitset(numa_nodes_ptr, node))
continue;
+ if (is_cpuless_node(node))
+ continue;
send_from_node(node, family, proto);
receive_on_node(rcv_fd, len, epfd, node, proto);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] nvme: zns: cap zone report nr_zones by DMA buffer size
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (13 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] selftests: net: reuseport_bpf_numa: consider cpuless numa node Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: usb-audio: Add MIN_MUTE quirk for Creative Sound Blaster Play! 3 Sasha Levin
` (501 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Xixin Liu, Christoph Hellwig, Keith Busch, Sasha Levin, axboe,
sagi, linux-nvme, linux-kernel
From: Xixin Liu <liuxixin@kylinos.cn>
[ Upstream commit 09c9062d4f62199a634a45e2bb9e6e8e572cc78c ]
With Partial Report (PR=1), the Number of Zones (NZ) field in the report
header must equal the number of zone descriptors fully transferred in the
DMA buffer (ZNS Command Set Specification Rev 1.2, section 3.4.2).
nvme_ns_report_zones() does not cap the parse loop by max_in_buf derived
from buflen. Cap nz with min3() over the device-reported count, nr_zones -
zone_idx, and max_in_buf.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
candidate is `09c9062d4f621` (“nvme: zns: cap zone report nr_zones by
DMA buffer size”). The ZNS report path has been here since v5.9; this is
a small host-side bounds cap against a device-controlled zone count.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[nvme: zns:] [cap] [limit zone-report parse count by DMA
buffer size]**
- Subsystem: NVMe host Zoned Namespace (ZNS) driver
- Verb “cap” is a bounds/safety fix, not a feature
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected for manual review)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** Christoph Hellwig `<hch@lst.de>` (NVMe/block
maintainer)
- **Acked-by:** none
- **Link:** none
- **Cc: stable:** none (expected; not a negative)
- **Signed-off-by:** Xixin Liu `<liuxixin@kylinos.cn>` (author); Keith
Busch `<kbusch@kernel.org>` (NVMe maintainer)
- Ignore any Sasha Levin SOB / “Upstream commit” markers — none present
on the real commit
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `nvme_ns_report_zones()` trusts `report->nr_zones` from the
device and caps only by the caller’s `nr_zones`, not by how many
`nvme_zone_descriptor`s fit in the allocated DMA/vmalloc buffer
(`buflen`).
- **Spec:** With Partial Report (PR=1), NZ must equal descriptors fully
transferred (ZNS Command Set Spec Rev 1.2 §3.4.2).
- **Symptom/failure mode:** parse loop `report->entries[i]` can walk
past `buflen` → kernel out-of-bounds read (crash / KASAN / info leak).
`sector += zsze * nz` can also advance by an inflated `nz`.
- **Version info in message:** none
- **Root cause:** missing cap derived from `buflen`
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not disguised.** Explicit bounds-cap of a device-provided
count. Real memory-safety fix, not cleanup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/nvme/host/zns.c` — **+6 / −2** (8 lines in the commit)
- Function: `nvme_ns_report_zones()` only
- Scope: **single-file surgical fix**
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** after `nvme_zns_alloc_report_buffer()` and
`nvme_submit_sync_cmd()`, `nz = min(le64_to_cpu(report->nr_zones),
nr_zones)` then `for (i = 0; i < nz && zone_idx < nr_zones; i++)`
reads `report->entries[i]`.
- **After:** `max_in_buf = (buflen - sizeof(nvme_zone_report)) /
sizeof(nvme_zone_descriptor)`; `nz = min3(device NZ, nr_zones -
zone_idx, max_in_buf)`.
- Path: normal ZNS zone-report (probe/revalidate, `BLKREPORTZONE` ioctl,
filesystems using `blkdev_report_zones()`).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Memory safety / OOB] [device-controlled length not capped by
allocation]**
- `nvme_zone_report` is 64 bytes + flexible `entries[]`; each descriptor
is 64 bytes (verified in `include/linux/nvme.h`).
- Buffer is often **smaller** than `nr_zones` descriptors:
`nvme_zns_alloc_report_buffer()` min()s against
`queue_max_hw_sectors`, `queue_max_segments << PAGE_SHIFT`, and halves
`bufsize` on vmalloc failure.
- Callers pass `BLK_ALL_ZONES` (`(unsigned int)-1` / `UINT_MAX`) — e.g.
`disk->fops->report_zones(disk, 0, UINT_MAX, ...)` in `block/blk-
zoned.c` during zone revalidate. Then `min(device_nz, UINT_MAX) ==
device_nz`.
- If firmware reports total zones (or a huge NZ) instead of the partial-
transfer count, the loop indexes past the allocation.
- Secondary: `nr_zones - zone_idx` keeps `nz` as remaining requested
zones for `sector += zsze * nz`.
- Same buffer-derived cap already exists in the NVMe **target**:
`get_nr_zones_from_buf()` in `drivers/nvme/target/zns.c`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Obviously correct:** `min3` of device count, remaining request, and
descriptors that fit in `buflen`.
- **Minimal:** two small hunks, no API/struct change.
- **Regression risk: very low.** Only **lowers** `nz`. Compliant PR=1
devices already set NZ ≤ `max_in_buf`, so behavior is unchanged on
good hardware.
- `min3()` exists in `include/linux/minmax.h` in this tree.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Buggy pattern introduced in **`240e6ee272c07`** (“nvme: support for
zoned namespaces”, Keith Busch, 2020-06-29).
- First contained in **`v5.9-rc1`**.
- Present for many years; not a recent-only bug.
- `nz = min(device NZ, nr_zones)` form after **`936fab503ff4a`** (“nvme:
fix error handling in nvme_ns_report_zones”), which still did not cap
by buffer size.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Introduced by `240e6ee272c07` (v5.9). That
commit **is** an ancestor of this tree (`git merge-base --is-ancestor
240e6ee272c07 HEAD` succeeded). Candidate **`09c9062d4f621` is also
already an ancestor of HEAD** (landed in **v7.3-rc1**). No later
overlapping fix of the same `nz` cap.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Related: `936fab503ff4a` (error handling), `8b4fb0f968ffe` (split
report_zones), `fdb9aed869f34` (`disk_report_zone()` args).
- **Standalone:** this hunk does not need those refactors; it only
changes how `nz` is computed.
- Sibling **`3456b52552896`** (v2 2/2) only adds zone index to an error
log — **not a prerequisite**.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record:
- Author Xixin Liu: several NVMe patches (`09c9062d4f621`,
`3456b52552896`, plus tcp/rdma/auth). Not the subsystem maintainer.
- Applied by **Keith Busch**; reviewed by **Christoph Hellwig**. High
maintainer weight.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: **No functional prerequisites.** Uses existing `min3`, `buflen`,
`nvme_zone_report` / `nvme_zone_descriptor`. Can apply standalone on any
tree with this parse loop (since v5.9).
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 09c9062d4f621` → https://patch.msgid.link/8ed1b6a33454.v2.1
782280600.git.liuxixin@kylinos.cn
- Full thread saved via `b4 dig -m /tmp/nvme-zns-thread.mbox`
- **v1** (2026-06-24): combined bounds cap + log message change
- **v2** (2026-06-25): split per review; **1/2 is this fix**, 2/2 is
logging
- Christoph on v1: log change “unrelated, please split”; **“The rest
looks good as well.”**
- Christoph on v2 1/2: **“Looks good: Reviewed-by: Christoph Hellwig”**
- Keith Busch: **“Thanks, applied to nvme-7.3.”**
- **No NAK, no stable objection, no risk flags.** No explicit Cc: stable
in the thread.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc linux-nvme, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-kernel. Appropriate NVMe/block
maintainers.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: **No syzbot, bugzilla, or user crash report.** Spec-driven host-
side hardening. Still a real OOB if NZ exceeds the buffer
(buggy/malicious NVMe, including fabrics/USB).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: v2 is 2/2. **1/2 is self-contained.** 2/2 is optional logging,
not required for the bounds fix.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: Web search of lore.kernel.org/stable for this subject found **no
relevant discussion** (unrelated historical hits only). Not previously
rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: **`nvme_ns_report_zones()`** (uses
`nvme_zns_alloc_report_buffer()`, `nvme_zone_parse_entry()`,
`nvme_submit_sync_cmd()`).
**Step 5.2: TRACE CALLERS**
Record:
- `nvme_report_zones()` in `drivers/nvme/host/core.c` — `gendisk`
`.report_zones` (`nvme_bdev_ops`)
- `nvme_ns_head_report_zones()` in `drivers/nvme/host/multipath.c` —
multipath head ops
Both under `CONFIG_BLK_DEV_ZONED` (`zns.o` is `nvme-
core-$(CONFIG_BLK_DEV_ZONED)`).
Upper layer: `blkdev_do_report_zones()` → ioctl,
`blkdev_report_zones()`, and **revalidate with `UINT_MAX`** (`block/blk-
zoned.c` ~2354). Filesystems: zonefs, f2fs, btrfs, xfs zoned.
**Step 5.3: TRACE CALLEES**
Record: alloc buffer (vmalloc, queue limits), Zone Management Receive
with `NVME_REPORT_ZONE_PARTIAL`, parse entries, `disk_report_zone()`,
`kvfree`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace `BLKREPORTZONE` / zoned FS mount / disk revalidate →
`disk->fops->report_zones` → `nvme_ns_report_zones`. **Reachable from
userspace and from device probe.** Unprivileged trigger depends on
device node permissions; probe path is admin/boot. Malicious NVMe-over-
Fabrics still in scope for some deployments.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: NVMe target already caps with `get_nr_zones_from_buf()`. SCSI
`sd_zbc.c` uses report-length/`nr_zones` differently. Host ZNS was the
missing cap.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Tree: **Linux 7.3.0-rc4** (`git describe HEAD` =
`v7.3-rc4-27-gf0100363d8c37`).
- File and function exist; current `zns.c` **already contains this cap**
(commit is in HEAD).
- Bug introduced **v5.9** (`240e6ee272c07`); not after this branch
point.
- This checkout is **mainline 7.3-rc**, not an older LTS cut, but the
**same `nvme_ns_report_zones` loop** is what older stables still have
without the cap.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** on this tree (already applied). Context around
`nz = min(...)` is stable since the 2020 error-handling fix. No
conflicting later rewrite of that assignment. Expected **clean or
trivial** cherry-pick onto trees that still have
`nvme_ns_report_zones()`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This is the fix. No alternate `max_in_buf` cap. Sibling logging
commit is independent.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **`drivers/nvme/host/` ZNS** — **IMPORTANT** (storage; not core
mm/VFS, but NVMe zoned devices used by zonefs/f2fs/btrfs/xfs). Config-
gated by `CONFIG_BLK_DEV_ZONED`.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: NVMe host is actively maintained; `zns.c` itself is **mature**
(ZNS since 2020). Long-lived bug, not churn from a new subsystem.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver/config-specific:** NVMe ZNS namespaces
(`CONFIG_BLK_DEV_ZONED`). Not all NVMe users; all ZNS users on
report/revalidate/ioctl/FS mount.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Common path: zone report / revalidate (`UINT_MAX` zones).
- Harmless on spec-compliant PR=1 devices (NZ already ≤ buffer).
- Harmful if firmware reports NZ larger than transferred descriptors
(ignore PR, report total count, or malicious controller).
- Not a timing race. Device-controlled integer.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Out-of-bounds kernel read** of `report->entries[i]` past
`buflen` → oops/KASAN, possible infoleak. **Severity: HIGH** (memory
safety from device-provided length). Inflated `nz` can also skip zones
in `sector +=` if the loop continues; the OOB is the primary issue.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** HIGH for ZNS — prevents OOB on buggy/malicious
controllers; correct remaining-count; matches target-side logic.
- **Risk:** VERY LOW — 6 insertions, only tightens a min(); no
lock/API/hot-path change.
- **Ratio:** strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB: parse count from device NZ not limited by DMA/vmalloc buffer
- Buffer is routinely smaller than requested `nr_zones` (queue limits,
vmalloc backoff)
- Revalidate uses `UINT_MAX`, so `min(NZ, nr_zones)` does not cap
- Small (+6/−2), obviously correct `min3`
- Reviewed by Christoph Hellwig; applied by Keith Busch
- Same cap already in NVMe target
- Bug in tree since v5.9; no extra deps
- No new API/feature
AGAINST:
- No public crash/syzbot report (spec-compliant devices already set NZ)
- ZNS is a subset of NVMe users
- No Fixes:/Cc: stable (ignored per rules)
UNRESOLVED:
- Could not fetch lore.kernel.org HTML (403); thread recovered via `b4
dig -m`
- No stable-list discussion found
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — maintainer Reviewed-by;
applied to nvme-7.3
2. Fixes a real bug that affects users? **PASS** — OOB if NZ exceeds
buffer; reachable zone-report path
3. Important issue? **PASS** — HIGH memory-safety (OOB read), not
cosmetic
4. Small and contained? **PASS** — 8 lines, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — code present; patch already
applies here
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Not** a device-ID/quirk/DT/build/docs exception. Ordinary
**memory-safety bug fix**.
**Step 9.4: MAKE YOUR DECISION**
This should be backported: it is a small, maintainer-acked cap that
stops the ZNS host from walking off the report buffer when the device’s
NZ is larger than what `buflen` can hold. On this 7.3-rc4 tree the ZNS
report path exists and the same bug has been in `nvme_ns_report_zones()`
since v5.9.
What it solves for stable users: kernel OOB on NVMe ZNS zone reports
(ioctl, FS mount, disk revalidate), especially with `BLK_ALL_ZONES` and
firmware that does not honor Partial Report.
Risk vs benefit: benefit is memory safety on a real I/O path; risk is a
tighter min that is a no-op on compliant devices.
Concerns: none material. Sibling logging patch is not required. No
missing prerequisites on this tree.
Verification:
- [Phase 1] Parsed subject/tags: Reviewed-by Christoph Hellwig; SOB
Keith Busch; no Fixes/Reported-by/Cc:stable
- [Phase 1] Body: PR=1 / NZ vs DMA buffer; missing `max_in_buf` cap
- [Phase 2] Diff: `drivers/nvme/host/zns.c` +6/−2 in
`nvme_ns_report_zones()`; `min3(device NZ, nr_zones - zone_idx,
max_in_buf)`
- [Phase 2] Struct sizes: `nvme_zone_report` 64B, descriptor 64B
(`include/linux/nvme.h`)
- [Phase 2] Alloc can shrink buffer: `nvme_zns_alloc_report_buffer()`
hw_sectors/segments/vmalloc halving
- [Phase 3] `git blame`: loop from `240e6ee272c07` (v5.9-rc1)
- [Phase 3] `git describe --contains 240e6ee272c07` → v5.9-rc1;
`09c9062d4f621` → v7.3-rc1
- [Phase 3] `git merge-base --is-ancestor` both SHAs vs HEAD: success
- [Phase 3] No Fixes: tag; sibling `3456b52552896` is logging-only
- [Phase 4] `b4 dig -c`: msgid
`8ed1b6a33454.v2.1782280600.git.liuxixin@kylinos.cn`
- [Phase 4] `b4 dig -a`: v1 then v2 (split log change)
- [Phase 4] `b4 dig -w`: linux-nvme, kbusch, axboe, hch, sagi
- [Phase 4] mbox: Christoph “Looks good” + R-b; Keith “applied to
nvme-7.3”; no NAK
- [Phase 4] lore HTTP 403; used b4 mbox instead
- [Phase 4] stable list search: no relevant thread
- [Phase 5] Callers: `core.c` `nvme_report_zones`, `multipath.c`
`nvme_ns_head_report_zones`; `blk-zoned.c` `UINT_MAX` revalidate
- [Phase 5] `BLK_ALL_ZONES` = `(unsigned int)-1` in
`include/linux/blkdev.h`
- [Phase 5] Target already has `get_nr_zones_from_buf()`
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-g…; `make kernelversion`:
7.3.0-rc4
- [Phase 6] Current `zns.c` already has `max_in_buf` / `min3`
- [Phase 8] Failure: OOB read of `report->entries[]`; severity HIGH
- UNVERIFIED: live crash on specific firmware (no public repro); does
not override code-level OOB
The patch is small, correct, and fixes a real device-controlled bounds
bug in NVMe ZNS zone reporting.
**YES**
drivers/nvme/host/zns.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c
index cce4c5b55aa9c..f067185920451 100644
--- a/drivers/nvme/host/zns.c
+++ b/drivers/nvme/host/zns.c
@@ -178,7 +178,7 @@ int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector,
struct nvme_zone_report *report;
struct nvme_command c = { };
int ret, zone_idx = 0;
- unsigned int nz, i;
+ unsigned int max_in_buf, nz, i;
size_t buflen;
if (ns->head->ids.csi != NVME_CSI_ZNS)
@@ -188,6 +188,9 @@ int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector,
if (!report)
return -ENOMEM;
+ max_in_buf = (buflen - sizeof(struct nvme_zone_report)) /
+ sizeof(struct nvme_zone_descriptor);
+
c.zmr.opcode = nvme_cmd_zone_mgmt_recv;
c.zmr.nsid = cpu_to_le32(ns->head->ns_id);
c.zmr.numd = cpu_to_le32(nvme_bytes_to_numd(buflen));
@@ -207,7 +210,8 @@ int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector,
goto out_free;
}
- nz = min((unsigned int)le64_to_cpu(report->nr_zones), nr_zones);
+ nz = min3((unsigned int)le64_to_cpu(report->nr_zones),
+ nr_zones - zone_idx, max_in_buf);
if (!nz)
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] ALSA: usb-audio: Add MIN_MUTE quirk for Creative Sound Blaster Play! 3
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (14 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] nvme: zns: cap zone report nr_zones by DMA buffer size Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] ALSA: hda/realtek: Fix speakers on ASUS ROG Zephyrus G14 GA403UM Sasha Levin
` (500 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Chad Talbott, Takashi Iwai, Sasha Levin, perex, tiwai,
linux-sound, linux-kernel
From: Chad Talbott <chad.talbott@gmail.com>
[ Upstream commit 352cef030f9036a658e6eb03d6bb85fa19c7c103 ]
The Creative Sound Blaster Play! 3 (041e:324d) exposes a Feature Unit
volume control with a range of -44.00 dB .. 0.00 dB over raw values
0..88, but raw value 0 is in fact a hard mute rather than -44.00 dB.
Tested on hardware.
Signed-off-by: Chad Talbott <chad.talbott@gmail.com>
Link: https://patch.msgid.link/20260819003237.452807-1-chad.talbott@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a hardware quirk for an existing USB-audio device. The local
tree is **6.12.111** (`p-6.12-3-gc504cf0baa3d8`). The MIN_MUTE machinery
is already here; only the device ID is missing.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[ALSA: usb-audio:] [Add] [MIN_MUTE quirk for Creative Sound
Blaster Play! 3 (041e:324d)]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Chad Talbott <chad.talbott@gmail.com>` (author)
- `Link: https://patch.msgid.link/20260819003237.452807-1-
chad.talbott@gmail.com`
- `Signed-off-by: Takashi Iwai <tiwai@suse.de>` (ALSA maintainer applied
it)
- No `Fixes:`, no `Reported-by:`, no `Cc: stable` (absence is expected)
- Ignore any pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit
...]` markers
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: Play! 3 reports Feature Unit volume as -44.00 dB .. 0.00 dB over
raw 0..88, but raw 0 is a **hard mute**, not -44 dB.
- Symptom: userspace (PulseAudio/PipeWire) treats the bottom of the
slider as a quiet but audible level. Volume mapping is wrong; audio
stays silent until the slider is raised well above 0.
- Version info: none in the message. The device is existing USB audio
hardware, not a new kernel-era device.
- Root cause: device firmware lies about the meaning of the minimum
volume value. The kernel must advertise `DB_MINMAX_MUTE` via TLV.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. This is an explicit hardware quirk. Same class as
the C-Media min-mute fix (`0f174b3525a43`, 2017, originally `Cc:
stable`) and later MIN_MUTE device-ID additions already in this tree.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `sound/usb/quirks.c` only (`+2` lines)
- Function/table: `quirk_flags_table[]`
- Scope: single-file, two-line table entry
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: `041e:324d` has no quirk-flag match. Probe still binds the
generic USB-audio driver.
- After: `snd_usb_init_quirk_flags()` sets
`QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE` (mainline name) /
`QUIRK_FLAG_MIXER_MIN_MUTE` (this tree).
- Path: mixer Feature Unit setup, playback volume TLV. Not an error
path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- Category: **hardware workaround** (quirk table entry)
- Mechanism: `snd_usb_mixer_fu_apply_quirk()` sees the flag and, for
controls whose name contains `"Playback"`, sets `cval->min_mute = 1`.
`snd_usb_mixer_vol_tlv()` then reports `SNDRV_CTL_TLVT_DB_MINMAX_MUTE`
instead of a plain dB min/max.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: one VID:PID added next to other Creative `0x041e`
entries, using an existing flag.
- Minimal: no API, no data-structure, no locking changes.
- Regression risk: very low; the flag is scoped to this ID and only
changes TLV metadata for playback volume. Other devices are untouched.
- Backport note: this tree uses `QUIRK_FLAG_MIXER_MIN_MUTE`, not
`QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE`. Same effect: the local handler
already limits the flag to Playback controls.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Insertion is between existing Creative entries:
- `DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */)` —
`3c69dc9134130d` (Takashi Iwai, 2021)
- `DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */)` —
`4d4dee0aefec36` (Takashi Iwai, 2021)
The table and adjacent IDs have been stable for years. The Play! 3 ID is
simply missing.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Not applicable. The “bug” is device firmware
behavior, not a kernel regression.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Related commits already in this tree:
- `c2564438d30a8` — “move mixer_quirks' min_mute into common quirk”
(upstream `2c3ca8cc55a3`)
- `2368ce440dfbc` — “Add mute TLV for playback volumes on more devices”
(same pattern: extra `QUIRK_FLAG_MIXER_MIN_MUTE` IDs)
- `0f174b3525a43` — original C-Media min-mute (2017, `Cc: stable`)
Standalone device-ID addition, not part of a series.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: No other `Chad Talbott` / `chad.talbott` commits under
`sound/usb/` in this tree. One-off hardware report, applied by the ALSA
maintainer.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Prerequisite is the MIN_MUTE flag. Confirmed present: `git
merge-base --is-ancestor c2564438d30a8 HEAD` succeeds.
`QUIRK_FLAG_MIXER_MIN_MUTE` is defined in `sound/usb/usbaudio.h` as `(1U
<< 24)`. Can apply standalone after renaming the flag.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 mbox` on msgid `20260819003237.452807-1-chad.talbott@gmail.com`
saved `/tmp/sbplay3` (2 messages).
- Original submission: 18 Aug 2026, To: Takashi Iwai, Jaroslav Kysela;
Cc: linux-sound, linux-kernel. Single patch, not a series.
- Reply from Takashi Iwai (`87cxvenu39.wl-tiwai@suse.de`, 19 Aug 2026):
**“Applied now. Thanks.”** No NAK, no requested revisions, no stable
discussion.
- `b4 dig -c` was not usable: the commit is not in this checkout.
- Direct lore WebFetch returned HTTP 403; the mbox from `b4` is the
source of truth.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Recipients were the ALSA maintainers and linux-sound. Maintainer
applied v1 as-is.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot link. Evidence is the author’s “Tested on
hardware” and the concrete VID:PID plus measured dB range.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone `[PATCH]`, not `X/Y`. Thread has only the patch and
the apply ack.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable WebFetch returned 403. No stable-list
discussion found via `git log --grep` on `sound/usb/`. No evidence this
was rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: No function body changed. Data consumed by
`snd_usb_init_quirk_flags()` and `snd_usb_mixer_fu_apply_quirk()`.
**Step 5.2: TRACE CALLERS**
Record:
- `snd_usb_init_quirk_flags()` called from `sound/usb/card.c:666` during
USB-audio probe.
- `snd_usb_mixer_fu_apply_quirk()` called from `sound/usb/mixer.c:1818`
while building Feature Unit controls.
- `snd_usb_mixer_vol_tlv()` is the TLV callback userspace reads.
**Step 5.3: TRACE CALLEES**
Record: The new row only sets `chip->quirk_flags`. Later, `min_mute`
changes TLV type to `SNDRV_CTL_TLVT_DB_MINMAX_MUTE`
(`include/uapi/sound/tlv.h`).
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Plug in Play! 3 → USB-audio probe → mixer create → userspace
reads volume TLV. Reachable from normal device use, not a rare config.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same `QUIRK_FLAG_MIXER_MIN_MUTE` already used for Conexant,
C-Media, Realtek, OnePlus, HECATE, HONOR, etc. in this tree’s
`quirk_flags_table`. This is another instance of a known, already-
backported pattern.
Semcode MCP tools: not available; used grep/read.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. USB-audio mixer + MIN_MUTE flag exist. `041e:324d` is
**not** in `sound/usb/quirks.c` (or elsewhere under `sound/usb/`). The
device will enumerate as generic USB audio with the wrong mute TLV. Bug
introduced by hardware, not by a post-6.12 kernel change.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Expected difficulty: **minor** (one-token rename).
- Insertion context `0x041e, 0x3000` then `0x041e, 0x4080` is present at
`quirks.c:2154-2157`.
- `QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE` is **not** defined here.
- Use `QUIRK_FLAG_MIXER_MIN_MUTE` instead; local
`snd_usb_mixer_fu_apply_quirk()` already gates on `"Playback"`.
- Nearby mainline-only entries (`0x040b:0x0897`, `0x045e:0x070f`) are
not required.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: MIN_MUTE infrastructure and other device IDs are here. No Play!
3 entry. No alternate fix for `041e:324d`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `sound/usb/` ALSA USB-audio. **IMPORTANT** for USB
DACs/headsets; not core mm/fs. Play! 3 is a real consumer USB DAC.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained; this 6.12 tree already carries later USB-
audio quirk backports (JBL FIXED_RATE, AB13X reset, DSD IDs, extra
MIN_MUTE IDs). Quirk-table additions are routine here.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific: owners of Creative Sound Blaster Play! 3
(`041e:324d`). Zero effect on other hardware.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every time the device is used with a dB-aware mixer
(PulseAudio/PipeWire). Not a race. Unprivileged users hit it via the
volume slider. Very likely for this hardware.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Incorrect volume/mute mapping: silence at “low” volume, min
position not treated as mute. Not a panic or corruption. **MEDIUM**
functionally, but it is the standard USB-audio min-mute hardware bug.
Original 2017 fix was stable-bound; later MIN_MUTE ID lists are already
in 6.12.y.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: high for Play! 3 users (usable volume curve).
- Risk: very low (2 lines, ID-matched, TLV only).
- Ratio: strongly favors backport with the flag-name tweak.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Classic USB-audio hardware quirk (stable exception category).
- Real, tested-on-hardware volume/mute lie from the device.
- Two-line table add; no new APIs.
- MIN_MUTE flag and handler already in this 6.12.111 tree.
- Same pattern already backported (`c2564438d30a8`, `2368ce440dfbc`).
- ALSA maintainer applied v1 with no concerns.
- Insertion point exists next to other Creative IDs.
AGAINST:
- Original patch uses `QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE` (needs rename
to `QUIRK_FLAG_MIXER_MIN_MUTE`).
- Not a crash/UAF/security issue.
- Affects one consumer DAC.
UNRESOLVED:
- Could not query lore.kernel.org/stable (HTTP 403). No indication of a
prior reject.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — hardware-tested; maintainer
applied.
2. Fixes a real bug that affects users? **PASS** — wrong mute/volume
mapping on a real DAC.
3. Important issue? **PASS** under the hardware-quirk exception (not a
crash).
4. Small and contained? **PASS** — +2 lines, one file.
5. No new features or APIs? **PASS** — existing quirk flag, new device
ID only.
6. Can apply to the local tree? **PASS** with trivial backport
(`MIXER_PLAYBACK_MIN_MUTE` → `MIXER_MIN_MUTE`).
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk/workaround** (USB-audio mixer min-mute),
equivalent in spirit to USB/PCI quirk table additions.
**Step 9.4: MAKE YOUR DECISION**
Backport. The local tree already has the quirk flag; this only adds the
Play! 3 ID. Rename the flag during apply.
------------------------------------------------
What problem it solves, and why it matters here
------------------------------------------------
Play! 3 reports -44 dB at raw 0, but raw 0 is mute. Without the TLV mute
bit, PulseAudio/PipeWire keep the device “silent until ~30% volume.”
That is the same class of bug already documented in this tree’s MIN_MUTE
commit (PipeWire MR / Arch wiki). 6.12 users with this DAC still hit it.
Risk vs benefit: two-line, ID-scoped TLV change vs broken volume on a
supported USB-audio device. Benefit wins.
Concerns: mechanical apply of the mainline diff will not compile until
the flag is renamed. That is a one-token stable backport, not a missing-
prerequisite situation.
Verification:
- [Phase 1] Parsed tags: author SOB, Link msgid, Takashi Iwai SOB; no
Fixes/Reported-by/Cc:stable
- [Phase 1] Body: 041e:324d, -44 dB vs hard mute at raw 0, tested on
hardware
- [Phase 2] Diff: +2 lines in `sound/usb/quirks.c` `quirk_flags_table[]`
- [Phase 2] Handler in this tree: `mixer_quirks.c:4504-4506` sets
`cval->min_mute` for Playback when `QUIRK_FLAG_MIXER_MIN_MUTE` is set
- [Phase 2] TLV: `mixer.c:555-556` uses `SNDRV_CTL_TLVT_DB_MINMAX_MUTE`
- [Phase 3] Blame: Creative neighbors from 2021 (`3c69dc9134130d`,
`4d4dee0aefec36`)
- [Phase 3] `git merge-base --is-ancestor c2564438d30a8 HEAD`: MIN_MUTE
infra **is** in this tree
- [Phase 3] `2368ce440dfbc` already added more MIN_MUTE IDs to this tree
- [Phase 3] No `Fixes:` tag (N/A)
- [Phase 3] `git log --author='Chad Talbott' -- sound/usb/`: no other
commits
- [Phase 4] `b4 mbox` msgid
`20260819003237.452807-1-chad.talbott@gmail.com`: 2-message thread;
Iwai “Applied now”
- [Phase 4] lore WebFetch 403; stable-list search 403
- [Phase 5] Callers: `snd_usb_init_quirk_flags` from `card.c:666`;
`snd_usb_mixer_fu_apply_quirk` from `mixer.c:1818`
- [Phase 5] semcode unavailable
- [Phase 6] `git describe HEAD` → `p-6.12-3-gc504cf0baa3d8`; `make
kernelversion` → 6.12.111
- [Phase 6] `0x324d` absent; `QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE`
absent; `QUIRK_FLAG_MIXER_MIN_MUTE` present; sandwich context present
- [Phase 8] Failure mode: wrong volume/mute TLV on one USB DAC; not a
kernel oops
- UNVERIFIED: full lore.kernel.org HTML thread (403); whether a later
mainline commit renamed MIN_MUTE → PLAYBACK_MIN_MUTE (flag absent
here; local Playback filter makes the names equivalent)
**YES**
sound/usb/quirks.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index b08e07324f830..8dcba375bd4a3 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2152,6 +2152,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x041e, 0x324d, /* Creative Sound Blaster Play! 3 */
+ QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x045e, 0x083c, /* MS USB Link headset */
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ALSA: hda/realtek: Fix speakers on ASUS ROG Zephyrus G14 GA403UM
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (15 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: usb-audio: Add MIN_MUTE quirk for Creative Sound Blaster Play! 3 Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.15] perf/x86/intel/uncore: Fix PCI PMU cleanup on setup failure Sasha Levin
` (499 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Garrett Blackmon, Takashi Iwai, Sasha Levin, perex, tiwai,
linux-sound, linux-kernel
From: Garrett Blackmon <garrett@blackmon.dev>
[ Upstream commit 140fe610af607fd70da95c447943fc2690855519 ]
The GA403UM (SSID 1043:1044) uses the same ALC285 codec + dual CS35L56
I2C amplifier topology as the GA403U and GA403W variants, which already
have quirk entries (1043:1b13, 1043:1024). Without the quirk, the
woofers sit on a separate DAC from the tweeters, so the hardware volume
control only scales part of the speaker system and the headset
microphone pins are not configured.
Apply the existing ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC fixup to the
GA403UM as well.
Signed-off-by: Garrett Blackmon <garrett@blackmon.dev>
Link: https://patch.msgid.link/20260807150708.33785-1-garrett@blackmon.dev
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line PCI SSID quirk for an existing Realtek fixup. The
local tree is **6.12.111** (`pending-6.12`, `p-6.12-3-g710455e2077bb`).
The GA403U fixup chain is already here; SSID `1043:1044` is not.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[ALSA: hda/realtek] [Fix] speakers on ASUS ROG Zephyrus G14
GA403UM`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Garrett Blackmon <garrett@blackmon.dev>` (author)
- `Link:
https://patch.msgid.link/20260807150708.33785-1-garrett@blackmon.dev`
- `Signed-off-by: Takashi Iwai <tiwai@suse.de>` (ALSA maintainer)
- No `Fixes:` tag (expected)
- No `Cc: stable` (expected; not a negative)
- No `Reported-by:` / `Tested-by:` / `Reviewed-by:` / `Acked-by:`
- Ignore pipeline `Signed-off-by: Sasha Levin` if present; it is not on
the mainline commit `140fe610af607`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** GA403UM (SSID `1043:1044`) has ALC285 + dual CS35L56 I2C
amps, same topology as GA403U (`1043:1b13`) and GA403W (`1043:1024`).
- **Symptom:** Without the quirk, woofers are on a different DAC from
tweeters, so hardware volume only scales part of the speaker system;
headset-mic pins are not configured.
- **Root cause:** Missing `SND_PCI_QUIRK` entry; the machine never gets
`ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC`.
- **Version info:** None in the message. Commit date is 2026-08-07
(after v6.12, 2024-11-17).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. It is an explicit hardware-quirk fix for broken
speakers/headset mic.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- Mainline file: `sound/hda/codecs/realtek/alc269.c` (`+1` / `-0`)
- Function/table: `alc269_fixup_tbl[]`
- Scope: single-file, one-line PCI quirk addition
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** SSID `1043:1044` does not match; generic auto-parse leaves
bass speaker NID `0x17` on a separate DAC and does not set headset-mic
pins `0x19`/`0x1b`.
- **After:** That SSID selects `ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC`,
which:
1. Sets pins `{0x19, 0x03a11050}` and `{0x1b, 0x03a11c30}`
2. Chains to `ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1`
(`alc285_fixup_speaker2_to_dac1` forces NID `0x17` onto
DAC1/`0x02`)
3. Chains to `ALC285_FIXUP_ASUS_GA403U` (inv-dmic only if codec is not
ALC285, for SSID reuse)
- Path: HDA probe / `patch_alc269()`, not an error path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Hardware workaround (PCI SSID quirk).** Missing table entry
for a shipped laptop SKU. Not UAF/race/leak.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: reuse of an existing, already-shipped fixup.
- Minimal: one `SND_PCI_QUIRK` line.
- Regression risk: very low; the entry matches only `vendor 0x1043, SSID
0x1044`. `0x1044` is unused in this tree’s Realtek quirk table.
- SSID-reuse note: `alc285_fixup_asus_ga403u` already guards non-ALC285
hardware that reused `0x1b13`. This new ID is a distinct SSID, not
that reuse case.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Insertion sits between existing ASUS entries `0x103f` (TX300, 2013)
and `0x1054` (G614, 2025 backport).
- Buggy “code” is absence of `1043:1044`, not a later regression in
shared logic.
- The fixup being applied was introduced by `0672b017324b1` (“Fixes for
Asus GU605M and GA403U sound”, 2024-04-18) and is in this tree.
- Earlier `c33f0d4fcfe07` (2024-03-30) added CS35L56 laptop quirks and
the GA403U SSID-reuse comment; also in this tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The functional prerequisite is `0672b017324b1`,
present here (`git merge-base --is-ancestor` → yes).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Related in this tree: `c33f0d4fcfe07`, `0672b017324b1`.
- Sibling mainline quirk `cbd46cbc5470f` (GA403W `1043:1024`, 2026-01)
is **not** in this tree. It is a parallel SKU entry, not a
prerequisite for `1043:1044`.
- Candidate `140fe610af607` is **not** an ancestor of HEAD.
- This 6.12 tree already backports many similar one-line Realtek quirks
(recent log is almost entirely `Add quirk for …`).
- Standalone: one table line; no series (`patch X/Y`).
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Garrett Blackmon has this single Realtek commit on
`origin/master`. Takashi Iwai applied it the same day. Author is a
hardware user, not the subsystem maintainer; maintainer acked by
applying.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Needs `ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC` and
`alc285_fixup_speaker2_to_dac1` — both exist in
`sound/pci/hda/patch_realtek.c`.
- Needs CS35L56 HDA I2C sidecar — `sound/pci/hda/cs35l56_hda_i2c.c` is
present.
- Does **not** need the GA403W `0x1024` entry.
- Cannot apply the mainline diff as-is: mainline file is
`sound/hda/codecs/realtek/alc269.c` (split ~2025-07). This tree still
has `sound/pci/hda/patch_realtek.c`. Backport is the same one line at
the same SSID sort position (after `0x103f`, before `0x1054`).
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 140fe610af607` →
https://patch.msgid.link/20260807150708.33785-1-garrett@blackmon.dev
- `b4 dig -a`: **v1 only** (2026-08-07), no later revisions.
- Thread: author submission + Takashi Iwai “Applied to for-next branch
now. Thanks.”
- No NAK, no stable nomination in-thread, no risk discussion.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc `tiwai@suse.com`, `perex@perex.cz`, `linux-
sound@vger.kernel.org`. ALSA maintainers were on the patch; Iwai applied
it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot link. The commit itself is the user report
(author is fixing their GA403UM). Severity from the text: partial
speaker volume + unconfigured headset mic.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone v1. Related sibling is GA403W `cbd46cbc5470f` (not
required). No follow-up on `origin/master` that changes `1043:1044`.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned HTTP 403. **UNVERIFIED**
whether it was discussed on stable@. Not used for the verdict.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: No function body change. Adds one entry to `alc269_fixup_tbl[]`.
Consumed fixups: `ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC` →
`alc285_fixup_speaker2_to_dac1` → `alc285_fixup_asus_ga403u`.
**Step 5.2: TRACE CALLERS**
Record:
- `patch_alc269()` calls `snd_hda_pick_fixup(..., alc269_fixup_tbl,
alc269_fixups)` at probe (`sound/pci/hda/patch_realtek.c`).
- `patch_alc269` covers the ALC269 family, including ALC285
(`0x10ec0285`).
- Trigger: HD-audio codec probe on this laptop, not interrupt/hot path.
**Step 5.3: TRACE CALLEES**
Record: `snd_hda_pick_fixup` matches PCI SSID, then pin overrides +
`snd_hda_override_conn_list(codec, 0x17, …)` so bass/woofer shares DAC1
with the main speakers.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: PCI/HDA enumeration → Realtek codec probe → `patch_alc269` →
quirk table. Reachable on every boot of a GA403UM. Not a syscall attack
path; it is the normal audio device path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same fixup already used for `0x1043, 0x1b13` (“ASUS
U41SV/GA403U”). This commit extends that pattern to another SKU. This
tree regularly takes the same class of one-line quirk.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes, as a missing SSID.
- Tree: 6.12.111 / `pending-6.12`.
- File: `sound/pci/hda/patch_realtek.c`.
- Fixup IDs and implementations are present (lines ~7529, ~6831,
~10586–10618).
- `0x1b13` is present (line 11257). `0x1044` is **not**.
- Candidate `140fe610af607` is not an ancestor of HEAD.
- Hardware is a 2026 G14 SKU; 6.12 is LTS, so users can run this kernel
on that laptop.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Raw mainline patch does not apply (file was split to
`sound/hda/codecs/realtek/alc269.c` after 6.12). Functional backport is
trivial: insert the same `SND_PCI_QUIRK` between `0x103f` and `0x1054`
in `patch_realtek.c` (lines 11185–11186). No data-structure or API gap.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: GA403U fixup yes; this SSID no. No alternate GA403UM fix. `git
grep 0x1044` in `patch_realtek.c` is empty.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `sound/pci/hda` Realtek HD-audio. **IMPORTANT** (laptop audio),
not core mm/fs. Maintainers: Takashi Iwai, Jaroslav Kysela
(`MAINTAINERS` SOUND). Config: `SND_HDA_CODEC_REALTEK`.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Very active quirk table; recent 6.12 backports are mostly
device-specific `SND_PCI_QUIRK` additions. Mature pattern, low novelty.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver/platform-specific: ASUS ROG Zephyrus G14 GA403UM, SSID
`1043:1044`, ALC285 + CS35L56. No effect on other machines.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every boot / any speaker volume or headset-mic use on that
model. Unprivileged user using audio. Not a race.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Failure: woofers do not follow master volume (split DAC); headset mic
pins unconfigured.
- **Severity: MEDIUM–HIGH** for that hardware (laptop audio effectively
broken), not a kernel oops. This is the class of “device doesn’t work
correctly without a quirk.”
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** High for GA403UM owners on 6.12.y (working speakers +
headset pins).
- **Risk:** Very low (one SSID line, existing fixup, SSID unused).
- **Ratio:** Strongly favors backport. Matches the documented hardware-
quirk exception.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real user-visible bug: incomplete speaker volume and unconfigured
headset mic.
- One-line `SND_PCI_QUIRK` using a fixup already in 6.12.
- Prerequisite `0672b017324b1` is in this tree; CS35L56 HDA I2C is in
this tree.
- ALSA maintainer applied v1 the same day; no NAK.
- Classic stable exception: PCI ID / hardware quirk for an existing
driver.
- This tree already carries the same fixup for GA403U (`0x1b13`).
- Insertion point exists; `0x1044` is free.
AGAINST:
- Mainline patch path differs (`alc269.c` vs `patch_realtek.c`); needs a
one-line backport, not a raw apply.
- No `Reported-by` besides the author; no syzbot/CVE.
- Not a crash/security bug.
- Sibling `0x1024` (GA403W) is absent — irrelevant; that SKU is
independent.
UNRESOLVED:
- Stable@ lore search (HTTP 403).
- WebFetch of lore also 403; thread recovered via `b4 dig -m`.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — reuse of in-tree fixup;
maintainer applied.
2. Fixes a real bug that affects users? **PASS** — broken volume/headset
on GA403UM.
3. Important issue? **PASS** — hardware-quirk exception; audio broken on
that laptop, not a panic.
4. Small and contained? **PASS** — 1 line.
5. No new features or APIs? **PASS** — existing quirk ID only.
6. Can apply to the local tree? **PASS** with trivial path adjustment
(`patch_realtek.c`, same context).
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk / PCI SSID addition to an existing driver.**
Automatic YES class.
**Step 9.4: MAKE YOUR DECISION**
The missing SSID is present as a gap in this 6.12 tree, the target fixup
chain is complete, and the change cannot affect any other device.
Backport it.
------------------------------------------------
What the commit solves for this tree
------------------------------------------------
On GA403UM, Linux never applies the GA403U speaker/mic fixup. Master
volume then moves only tweeters (woofers stay on another DAC), and
headset-mic pins stay wrong. Adding `SND_PCI_QUIRK(0x1043, 0x1044, "ASUS
GA403UM", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC)` to `alc269_fixup_tbl`
in `sound/pci/hda/patch_realtek.c` is the whole fix.
Risk vs benefit: benefit is working audio on that LTS laptop; risk is a
single unused-SSID match. File-split means the mainline diff needs a
one-line rewrite, which is normal for Realtek quirks on 6.12.
Verification:
- [Phase 1] Parsed tags on `140fe610af607`: SOB Blackmon, Link msgid,
SOB Iwai; no Fixes/stable/Reported-by
- [Phase 2] Diff: +1 line `SND_PCI_QUIRK(0x1043, 0x1044, …
ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC)`
- [Phase 3] `git describe HEAD` / `make kernelversion`:
`p-6.12-3-g710455e2077bb`, 6.12.111, branch `pending-6.12`
- [Phase 3] `git merge-base --is-ancestor 140fe610af607 HEAD` → not in
tree
- [Phase 3] `git merge-base --is-ancestor 0672b017324b1 HEAD` → yes
(GA403U fixup)
- [Phase 3] `git merge-base --is-ancestor cbd46cbc5470f HEAD` → no
(GA403W 0x1024; not required)
- [Phase 3] Confirmed fixup chain and `0x1b13` in
`sound/pci/hda/patch_realtek.c`; `0x1044` absent
- [Phase 4] `b4 dig -c 140fe610af607` / `-a` / `-w` / `-m`: v1 only;
Iwai applied; To linux-sound + maintainers
- [Phase 4] UNVERIFIED: lore.kernel.org WebFetch and stable@ search
(HTTP 403)
- [Phase 5] `patch_alc269()` → `snd_hda_pick_fixup(...,
alc269_fixup_tbl, …)` at codec probe
- [Phase 5] `alc285_fixup_speaker2_to_dac1` overrides NID 0x17 to DAC
0x02
- [Phase 6] Insertion context `0x103f` then `0x1054` present at lines
11185–11186
- [Phase 6] `cs35l56_hda_i2c.c` present
- [Phase 8] Failure mode: partial speaker volume + unconfigured headset
mic on one laptop SSID
- UNVERIFIED: whether this SSID was already requested on stable@
**YES**
sound/hda/codecs/realtek/alc269.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 8fdfe1bbe7aff..05e7fcc2f67e6 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -7094,6 +7094,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1034, "ASUS GU605C", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
+ SND_PCI_QUIRK(0x1043, 0x1044, "ASUS GA403UM", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1054, "ASUS G614FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x106f, "ASUS VivoBook X515UA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] perf/x86/intel/uncore: Fix PCI PMU cleanup on setup failure
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (16 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] ALSA: hda/realtek: Fix speakers on ASUS ROG Zephyrus G14 GA403UM Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:02 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] perf/x86: Free hybrid state on PMU init failure Sasha Levin
` (498 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Zide Chen, Peter Zijlstra (Intel), Dapeng Mi, Sasha Levin, mingo,
acme, namhyung, tglx, bp, dave.hansen, x86, linux-perf-users,
linux-kernel
From: Zide Chen <zide.chen@intel.com>
[ Upstream commit 003267cb94e21d762eb72d6977d84f44f1705bb7 ]
When uncore_pci_pmu_register() fails, pmu->boxes[die] is set to NULL
before returning. In the uncore_pci_remove() path, this causes
uncore_pci_pmu_unregister() to be skipped entirely, leaking
pmu->activeboxes. In the uncore_bus_notify() path,
uncore_pci_pmu_unregister() may still be called and must exit early
when pmu->boxes[die] is NULL to avoid a NULL pointer dereference, and
to ensure activeboxes is only decremented for a previously active box.
Additionally, since pci_get_drvdata() returns NULL on registration
failure, uncore_pci_remove() can no longer treat NULL drvdata as an
indicator of an auxiliary PCI device. Remove the associated
WARN_ON_ONCE().
Signed-off-by: Zide Chen <zide.chen@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://sashiko.dev/#/patchset/20260512233048.9577-1-zide.chen@intel.com?part=1
Link: https://patch.msgid.link/20260611160033.66760-2-zide.chen@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The 6.18.53 file matches the pre-fix code exactly, so this is a clean,
self-contained error-path leak and NULL-deref fix. Full phase
walkthrough follows.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [perf/x86/intel/uncore] [fix] [PCI PMU cleanup on setup failure]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Zide Chen (author)
- Signed-off-by: Peter Zijlstra (Intel) (perf/x86 maintainer)
- Reviewed-by: Dapeng Mi (Intel uncore reviewer)
- Link: https://sashiko.dev/#/patchset/20260512233048.9577-1-
zide.chen@intel.com?part=1
- Link:
https://patch.msgid.link/20260611160033.66760-2-zide.chen@intel.com
- No Fixes: tag (expected)
- No Reported-by / Tested-by / syzbot
- No Cc: stable (expected)
- Ignore: [Upstream commit 003267cb94e21d762eb72d6977d84f44f1705bb7] and
Sasha Levin SOB (pipeline)
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: when `uncore_pci_pmu_register()` fails, `pmu->boxes[die]` is
NULLed and the box is freed, but `pmu->activeboxes` stays incremented.
- Symptoms: (1) `uncore_pci_remove()` skips unregister because drvdata
is NULL → `activeboxes` leak; (2) `uncore_bus_notify()` still calls
unregister → NULL deref of `box`; (3) false `WARN_ON_ONCE()` because
NULL drvdata is no longer uniquely “extra PCI device”.
- Version info: none in the message. Code dates to 2020.
- Root cause: incomplete error-path rollback in
`uncore_pci_pmu_register()`, and unregister not tolerating a NULL box.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not hidden. Explicit leak + NULL-deref + false-WARN fix. The
“remove WARN_ON” piece is diagnostic, not a new feature.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `arch/x86/events/intel/uncore.c` (+4 / −1)
- Functions: `uncore_pci_pmu_register()`, `uncore_pci_pmu_unregister()`,
`uncore_pci_remove()`
- Scope: single-file surgical fix (5 lines)
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Hunk 1 (`uncore_pci_pmu_register`): first-box `uncore_pmu_register()`
failure already NULLed `boxes[die]`, exited and freed the box, but
left `activeboxes` incremented. After: `atomic_dec(&pmu->activeboxes)`
on that path.
- Hunk 2 (`uncore_pci_pmu_unregister`): previously always used `box` and
decremented `activeboxes`. After: return immediately if `box` is NULL
(no deref, no bogus decrement).
- Hunk 3 (`uncore_pci_remove`): drop `WARN_ON_ONCE(i >=
UNCORE_EXTRA_PCI_DEV_MAX)` when drvdata is NULL.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: error-path resource leak + NULL pointer dereference (and a
false WARN).
- Mechanism: `atomic_inc_return(&pmu->activeboxes)` runs before
`uncore_pmu_register()`. On failure the box is torn down but the
counter is not. Discovery/`bus_notify` still looks up the PMU by PCI
identity and calls unregister, which does `uncore_box_exit(box)` on
NULL (`box->flags`).
- Leak consequence: the next box of the same PMU sees `activeboxes > 1`
and skips `uncore_pmu_register()`, so the PMU never appears in perf.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Quality: obviously correct. Decrement matches the increment; NULL
guard is the standard pattern; no API/data-structure change.
- Regression risk: very low. Sashiko noted that PCI probe failure does
not call `remove()`, so the WARN removal is not strictly required for
that path. That only drops a diagnostic; it does not create a crash.
The NULL check is required for `uncore_bus_notify()`, which is
independent of `remove()`.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Buggy register error path: `16fa64315c1bd` (“Factor out
uncore_pci_pmu_register()”), Kan Liang, 2020-09-14. First mainline:
v5.10-rc1.
- Unregister without NULL check: `cdcce92a3a03bc` (2020).
- WARN_ON_ONCE: `899396cf7b4b31` (Yan Zheng, 2013).
- Long-lived code, present in this 6.18 tree.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Introducer is `16fa64315c1bd`, which **is** an
ancestor of v6.18.53.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- This is v3 1/8 of “PMU setup robustness fixes”.
- Series: 1/8 this fix; 2/8 refcnt cleanup; 3/8 init_box errors; 4/8
keep PCI PMUs if MMIO/MSR alloc fails; 5/8 factor box setup; 6–8
flags/lazy setup.
- 4/8 (`d623e292c6a4c`) is already in v6.18.53. 2/8 and 5/8 are not.
- This patch does not depend on 2/8+; later patches build on it.
Standalone.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Zide Chen is an active Intel uncore contributor on this tree
(die-id, discovery, IMC events, etc.). Maintainer path: Peter Zijlstra
SOB. Dapeng Mi Reviewed-by.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: No missing helpers or types. Parent of the candidate and
`v6.18.53:arch/x86/events/intel/uncore.c` are byte-identical (same
sha256). Applies standalone. Dry-run `patch -p1` against the v6.18.53
file succeeded.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 540120722e9bf`: `[PATCH V3 1/8] perf/x86/intel/uncore: Fix
PCI PMU cleanup on setup failure`
- URL:
https://patch.msgid.link/20260611160033.66760-2-zide.chen@intel.com
- lore.kernel.org WebFetch returned 403; full thread saved via `b4 dig
-m` (26 messages).
- V1/V2 existed; this patch was **new in v2** after Sashiko review of
v1. v3 only added Reviewed-by. Applied version is latest.
- Cover letter: “PCI PMU cleanup on setup failure has activeboxes leaks
and potential NULL pointer dereference in error paths.”
- No NAK. tip-bot applied it to perf/core (2026-06-30).
- Sashiko on v3: questioned WARN_ON removal (Medium); two High notes
were pre-existing UAF/races, not introduced by this patch. No stable
NAK.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: `b4 dig -w` recipients: Peter Zijlstra, Ingo Molnar, Arnaldo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin, Andi Kleen,
Stephane Eranian, linux-kernel, linux-perf-users, Dapeng Mi. Dapeng
Reviewed-by on the committed patch; Peter Zijlstra SOB.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Found by code review (Sashiko on v1 → new
patch 1 in v2). Still a real, reachable error path, not a theoretical
rewrite.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: 8-patch robustness series. This 1/8 is self-contained. 4/8
already landed in this 6.18.53 tree. Later patches are larger (broken-
state, lazy MSR/MMIO) and are not required for this leak/NULL-deref fix.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable WebFetch returned 403. UNVERIFIED whether
stable@ discussed it. Not used as a NO signal (absence of Cc: stable is
expected).
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `uncore_pci_pmu_register`, `uncore_pci_pmu_unregister`,
`uncore_pci_remove`. Related: `uncore_pci_probe`, `uncore_bus_notify`,
`uncore_pci_pmus_register`, `uncore_pci_sub_driver_init`.
Step 5.2: TRACE CALLERS
Record:
- `uncore_pci_pmu_register`: `uncore_pci_probe` (legacy
`uncore_pci_driver`), `uncore_pci_sub_driver_init` (PCI sub-devices),
`uncore_pci_pmus_register` (discovery; return value ignored).
- `uncore_pci_pmu_unregister`: `uncore_pci_remove`, `uncore_bus_notify`.
- `uncore_bus_notify`: PCI `BUS_NOTIFY_DEL_DEVICE`. Discovery always
registers this notifier.
- Context: driver init / PCI probe / PCI device deletion. Not a syscall
hot path, but boot and hot-unplug on Intel systems with uncore
(default `y`).
Step 5.3: TRACE CALLEES
Record:
- `uncore_pmu_register()` → `perf_pmu_register()` (can fail: ENOMEM,
sysfs/device_add, name collision).
- `uncore_box_exit()` at v6.18.53: `test_and_clear_bit(...,
&box->flags)` — NULL `box` is a hard oops.
- `kfree(NULL)` is safe; the crash is `uncore_box_exit`.
Step 5.4: FOLLOW THE CALL CHAIN
Record:
- Modern Intel (no `uncore_pci_driver`): `uncore_pci_init` →
`uncore_pci_pmus_register` → register (retval ignored) →
`bus_register_notifier`. Failed first-box `perf_pmu_register` + later
`BUS_NOTIFY_DEL_DEVICE` → `uncore_pci_find_dev_pmu_from_types` still
finds the PMU → unregister(NULL) → oops.
- Same PMU, later boxes: `activeboxes > 1` skips `uncore_pmu_register` →
uncore PMU missing from perf.
- Reachable without a special debug option.
`CONFIG_PERF_EVENTS_INTEL_UNCORE` defaults to y on Intel+PCI.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: MSR/MMIO setup is a different model; this series later factors
PCI lazy registration for those paths. No duplicate of this exact PCI
error-path bug in-tree. 2/8 adds refcnt decrement in unregister and is a
follow-up cleanup, not a prerequisite.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Local tree: `v6.18.53-5049-g0f0bdc2b0dffb`, `make kernelversion`
6.18.53.
- At v6.18.53, `uncore_pci_pmu_register` still omits `atomic_dec` on
`uncore_pmu_register()` failure; unregister has no NULL check;
`WARN_ON_ONCE` is present. Bug exists here.
- Introduced v5.10-rc1; not after 6.18 branched.
- `git merge-base --is-ancestor 16fa64315c1bd v6.18.53` → yes.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Expected apply: **clean**. Candidate parent `uncore.c` sha256
equals v6.18.53 `uncore.c`. Dry-run apply succeeded.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No other “PCI PMU cleanup” fix in v6.18.53. 4/8 of the same
series is already in 6.18.53 (`d623e292c6a4c`). That does not fix this
leak/NULL deref.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [arch/x86/events/intel uncore PMU] [IMPORTANT — default-on Intel
server/workstation perf, not core mm/sched, but widely enabled]
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature (2012+) with ongoing platform adds (PTL, WCL, etc.). This
bug is old incomplete error handling, not a brand-new driver.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Intel x86 with `CONFIG_PERF_EVENTS_INTEL_UNCORE` (default y).
Driver-specific / config-default-on. Discovery platforms (newer Xeon)
hit the bus-notify NULL deref path.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Trigger: first box of a PCI uncore PMU fails `perf_pmu_register()`
(ENOMEM, sysfs failure, name clash).
- Not every boot, but a real error path. Discovery ignores register
failure and still installs the notifier.
- Unprivileged users do not trigger it directly; PCI unbind/hotplug and
boot setup do. Missing PMU is user-visible to perf.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- NULL deref in `uncore_box_exit(NULL)` on device delete → oops.
**HIGH** (crash on error + unplug).
- `activeboxes` leak → later boxes skip PMU registration → uncore events
absent. **MEDIUM–HIGH**.
- False WARN_ON. **LOW**.
- Overall: **HIGH** (crash on a reachable error path).
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: high — prevents oops and silently missing uncore PMUs after a
failed first-box register.
- Risk: very low — 5 lines, no locking/API change, WARN removal is the
only nit.
- Ratio: strongly favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR backporting:
- Real leak of `pmu->activeboxes` on `uncore_pmu_register()` failure
(code at v6.18.53 matches).
- Real NULL deref: discovery `uncore_pci_pmus_register()` ignores
failure, `uncore_bus_notify` still unregisters,
`uncore_box_exit(NULL)` oopses.
- Same leak causes later boxes to skip `uncore_pmu_register()`, so the
PMU never shows up in perf.
- 5-line, obviously correct, no new API.
- Applies cleanly; file is identical to the pre-fix version.
- Bug present since v5.10; this 6.18 tree has it.
- Reviewed by Dapeng Mi; SOB Peter Zijlstra.
- Patch 1/8 is standalone; later series members not required.
- Same series 4/8 already in this 6.18.53 tree.
AGAINST:
- Trigger is an error path (`perf_pmu_register` failure), not a always-
on boot crash.
- No user/syzbot report.
- Sashiko: WARN_ON removal is weakly justified for the `pci_driver`
probe/remove model (probe failure does not call remove). Diagnostic-
only concern.
- Later 2/8 refcnt cleanup is related but separate; not a blocker.
UNRESOLVED:
- Stable mailing list search via lore HTTP was 403 (mbox/review still
obtained via b4).
- How often `perf_pmu_register` actually fails in production:
unverified, but ENOMEM/sysfs failure is a standard, reachable errno
path.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — counter rollback + NULL
guard; maintainer SOB; Dapeng review; in mainline perf/core.
2. Fixes a real bug that affects users? **PASS** — leak, skipped PMU
registration, oops on device delete.
3. Important issue? **PASS** — NULL deref oops; missing uncore PMU.
Severity HIGH.
4. Small and contained? **PASS** — 5 lines, one file.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — clean apply to v6.18.53
`uncore.c`.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary small
bugfix; does not need an exception.
Step 9.4: MAKE YOUR DECISION
This belongs in 6.18.y: the buggy rollback is in this tree, the fix is
surgical, and the failure mode is a kernel oops plus a stuck/missing PCI
uncore PMU. WARN_ON removal is a minor diagnostic tradeoff, not a reason
to reject the leak and NULL-deref fix.
What the commit solves for stable users: Intel uncore PCI PMU setup
failure currently leaks `activeboxes` and can oops in
`uncore_bus_notify` when the device goes away. Backporting restores
counter balance, skips unregister when there is no box, and avoids a
false WARN.
Risk vs benefit: benefit is crash/functional correctness on a default-on
Intel perf driver; risk is a 5-line error-path change that applies with
no prerequisites.
Verification:
- [Phase 1] Parsed tags: SOB Zide Chen, SOB Peter Zijlstra, Reviewed-by
Dapeng Mi; Links to sashiko and patch.msgid.link; no Fixes/syzbot.
- [Phase 2] Diff: +`atomic_dec` on register failure; +`if (!box) return`
in unregister; −`WARN_ON_ONCE` in remove. 4+/1− in `uncore.c`.
- [Phase 2] `uncore_box_exit` at v6.18.53 dereferences `box->flags` —
NULL box is an oops.
- [Phase 3] blame: register failure path from `16fa64315c1bd`
(v5.10-rc1); present in v6.18.53.
- [Phase 3] `git merge-base --is-ancestor 16fa64315c1bd v6.18.53` → yes.
Candidate itself is not an ancestor of v6.18.53.
- [Phase 3] Parent `uncore.c` sha256 == v6.18.53 `uncore.c`; `patch -p1
--dry-run` succeeded.
- [Phase 3] Series 1/8 standalone; 4/8 `d623e292c6a4c` already in
v6.18.53; 2/8 and 5/8 not in v6.18.53 and not required.
- [Phase 4] `b4 dig -c 540120722e9bf`: V3 1/8,
https://patch.msgid.link/20260611160033.66760-2-zide.chen@intel.com
- [Phase 4] `b4 dig -a`: v1→v3; this patch added in v2 after Sashiko; v3
is what landed.
- [Phase 4] `b4 dig -w`: perf maintainers CC’d; Dapeng Reviewed-by; no
NAK.
- [Phase 4] mbox cover letter explicitly calls out activeboxes leak and
NULL deref.
- [Phase 4] lore HTTP 403; discussion recovered from b4 mbox. Stable-
list search UNVERIFIED (403).
- [Phase 5] Callers: probe, sub-driver init, discovery
`uncore_pci_pmus_register` (ignores retval, always registers bus
notifier).
- [Phase 5] `uncore_pmu_register` → `perf_pmu_register` can fail.
- [Phase 6] `git describe HEAD` = v6.18.53-5049-g0f0bdc2b0dffb;
`Makefile` 6.18.53; buggy code at v6.18.53 lines 1166–1172 / 1229–1238
/ 1257.
- [Phase 7] `CONFIG_PERF_EVENTS_INTEL_UNCORE` default y.
- [Phase 8] Failure mode: NULL deref oops + skipped PMU registration;
severity HIGH.
- UNVERIFIED: production frequency of `perf_pmu_register` failure;
stable@ lore thread (HTTP 403).
**YES**
arch/x86/events/intel/uncore.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index a5793847ed5a9..3d9973c416ecf 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -1165,6 +1165,7 @@ static int uncore_pci_pmu_register(struct pci_dev *pdev,
/* First active box registers the pmu */
ret = uncore_pmu_register(pmu);
if (ret) {
+ atomic_dec(&pmu->activeboxes);
pmu->boxes[die] = NULL;
uncore_box_exit(box);
kfree(box);
@@ -1230,6 +1231,9 @@ static void uncore_pci_pmu_unregister(struct intel_uncore_pmu *pmu, int die)
{
struct intel_uncore_box *box = pmu->boxes[die];
+ if (!box)
+ return;
+
pmu->boxes[die] = NULL;
if (atomic_dec_return(&pmu->activeboxes) == 0)
uncore_pmu_unregister(pmu);
@@ -1254,7 +1258,6 @@ static void uncore_pci_remove(struct pci_dev *pdev)
break;
}
}
- WARN_ON_ONCE(i >= UNCORE_EXTRA_PCI_DEV_MAX);
return;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] perf/x86: Free hybrid state on PMU init failure
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (17 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.15] perf/x86/intel/uncore: Fix PCI PMU cleanup on setup failure Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/amdgpu: validate XCP topology counts before division Sasha Levin
` (497 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Dapeng Mi, Peter Zijlstra (Intel), Thomas Falcon, Zide Chen,
Sasha Levin, mingo, acme, namhyung, tglx, bp, dave.hansen, x86,
linux-perf-users, linux-kernel
From: Dapeng Mi <dapeng1.mi@linux.intel.com>
[ Upstream commit 96746e731e1626545e343974ca4673739dceb31b ]
If PMU initialization fails, for example in check_hw_exists(), hybrid
state can be left partially initialized: x86_pmu.hybrid_pmu is not freed
and perf_is_hybrid remains set. This can leak memory and leave stale
hybrid state reachable after a failed init path.
Add x86_pmu_free_hybrid() and use it on PMU init failure paths so all
hybrid-related state is consistently reset.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Thomas Falcon <thomas.falcon@intel.com>
Reviewed-by: Zide Chen <zide.chen@intel.com>
Link: https://patch.msgid.link/20260717080342.1879573-3-dapeng1.mi@linux.intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111** (`pending-6.12`). The hybrid PMU
init/error path exists here, and this commit is a real error-path
UAF/leak fix that belongs in this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[perf/x86] [Free] [release hybrid PMU state when PMU init
fails]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- No `Fixes:` tag (expected for this review pipeline)
- No `Reported-by:` / syzbot
- No `Tested-by:`
- `Reviewed-by: Thomas Falcon <thomas.falcon@intel.com>`
- `Reviewed-by: Zide Chen <zide.chen@intel.com>`
- `Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>` (author)
- `Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>` (perf
maintainer)
- `Link: https://patch.msgid.link/20260717080342.1879573-3-
dapeng1.mi@linux.intel.com`
- No `Cc: stable` (not a negative signal)
SHA on `origin/master`: `96746e731e1626545e343974ca4673739dceb31b` (not
an ancestor of HEAD).
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** On hybrid Intel PMU init failure (example:
`check_hw_exists()`), `x86_pmu.hybrid_pmu` is not freed and
`perf_is_hybrid` stays enabled.
- **Symptom:** Memory leak plus leftover hybrid state after a failed
init.
- **Root cause:** `intel_pmu_init_hybrid()` allocates `hybrid_pmu` and
enables the static key; `init_hw_perf_events()` error paths
`memset(&x86_pmu, 0, ...)` without freeing or disabling that key. The
hybrid `perf_pmu_register` fail path kfree's too early and still
leaves the static key set.
- **Version:** Hybrid PMUs exist since 2021; this tree has them.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. It is an explicit error-path leak/stale-state
fix. The delayed `kfree` also removes a use-after-free on the hybrid
register-fail path (see Phase 2/5).
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `arch/x86/events/core.c` (+12 / −3)
- New helper: `x86_pmu_free_hybrid()`
- Modified: `init_hw_perf_events()` (hybrid register-fail block and
`out_bad_pmu`)
- Scope: single-file surgical error-path fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Hunk 1:** Add `x86_pmu_free_hybrid()`: if `hybrid_pmu` is set,
disable `perf_is_hybrid`, `kfree` the array, NULL it, set
`num_hybrid_pmus = 0`.
- **Hunk 2 (before):** Hybrid `perf_pmu_register` failure kfree's the
array, NULLs it, zeros the count, then `goto out2` (cpuhp teardown,
then `memset`).
- **Hunk 2 (after):** Only unregister already-registered PMUs and `goto
out2`; free/reset happens later in `out_bad_pmu`.
- **Hunk 3:** `out_bad_pmu` calls `x86_pmu_free_hybrid()` **before**
`memset(&x86_pmu, 0, ...)`.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Error-path resource leak + UAF + stale static key**
Verified in this tree (`init_hw_perf_events`, `intel_pmu_init_hybrid`,
`intel_pmu_cpu_dead`):
1. **Leak on early failure:** `intel_pmu_init_hybrid()` does `kcalloc` +
`static_branch_enable(&perf_is_hybrid)`. If `check_hw_exists()` then
fails, 6.12 jumps to `out_bad_pmu` and only `memset`s `x86_pmu`,
dropping the pointer without `kfree`. `perf_is_hybrid` stays enabled.
2. **UAF on hybrid register failure:** By the time `perf_pmu_register`
runs, `CPUHP_AP_PERF_X86_STARTING` has already run
`intel_pmu_cpu_starting()` → `init_hybrid_pmu()`, which sets
`cpuc->pmu` into the `hybrid_pmu` array. Current 6.12 code `kfree`s
that array **then** `goto out2` →
`cpuhp_remove_state(CPUHP_PERF_X86_PREPARE)` → `x86_pmu_dead_cpu()` →
`intel_pmu_cpu_dead()`:
```5209:5210:arch/x86/events/intel/core.c
if (is_hybrid() && cpuc->pmu)
cpumask_clear_cpu(cpu,
&hybrid_pmu(cpuc->pmu)->supported_cpus);
```
`is_hybrid()` is still true and `cpuc->pmu` still points at freed
memory. That is a use-after-free. Moving the free to after cpuhp
teardown fixes it.
3. **Stale static key:** The old register-fail path never called
`static_branch_disable(&perf_is_hybrid)`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct and minimal. `static_branch_disable` + `kfree`
+ NULL during `__init` teardown is low risk. Free-after-cpuhp is the
right order. No API change. Regression risk is low.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Hybrid register/kfree block: `d9977c43bff89` (“perf/x86: Register
hybrid PMUs”, 2021-04-19) — present in 6.12.
- `intel_pmu_init_hybrid()` alloc/static key: `97588df87b56e2` (Kan
Liang, 2023-08-29) — present in 6.12.
- `out_bad_pmu` memset: `916e3a4f950eac` (Paolo Bonzini, 2022) — present
in 6.12.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Bug was introduced with hybrid PMU support
(2021/2023), well before 6.12.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: This is v3 **2/8** of Dapeng Mi’s “Miscellaneous PMU bug fixes
and optimizations”.
- Parent: `91787047b1dc5` “Unregister PMI handler on PMU init failure”
(adds `pmi_unregister:`) — **not** in this tree.
- Next: `278a3731c9d08` “Guard intel_pmu_cpu_dead() against invalid
hybrid PMU casts” — separate OOB/`container_of` bug; not required for
this leak/UAF fix.
This patch is standalone: the helper only needs to run before `memset`
at `out_bad_pmu`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Dapeng Mi is an Intel perf contributor. Same series has several
hybrid/error-path fixes. Applied by Peter Zijlstra.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Patch 1 is **not** a functional prerequisite. It only changes
nearby labels (`pmi_unregister`, `goto pmi_unregister` instead of
`return err`). `x86_pmu_free_hybrid()` can be added to 6.12’s existing
`out_bad_pmu`. No new helpers or structs.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 96746e731e162` → https://patch.msgid.link/20260717080342.18
79573-3-dapeng1.mi@linux.intel.com
- Revisions: v1 (2026-07-10, 2/7), v2 (2026-07-13, 2/7), v3 (2026-07-17,
2/8). This hunk did not change across revisions.
- Cover letter: bugs found in review (Sashiko) of a later SIMD/eGPR
sampling series, not from a production crash.
- Zide Chen: `Reviewed-by` for the whole series. Author called the
series “low risky”. No NAKs found.
- Merged to tip perf/core 2026-08-12, then Linus.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de
Melo, Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin, Andi
Kleen, Stephane Eranian, linux-kernel, linux-perf-users, Zide Chen,
Thomas Falcon. Maintainer applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. Found by code review of hybrid init error
paths.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone among 8 patches. Patch 1 (NMI unregister) and patch 3
(cpu_dead hybrid cast) are related but independent.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No stable-list discussion found for this subject. Not a reason
to skip it.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: KEY FUNCTIONS**
Record: `x86_pmu_free_hybrid()` (new), `init_hw_perf_events()`
(modified). Related existing: `intel_pmu_init_hybrid()`,
`intel_pmu_cpu_dead()`, `x86_pmu_dead_cpu()`.
**Step 5.2: TRACE CALLERS**
Record:
- `init_hw_perf_events()`: `early_initcall`, once at boot.
- `x86_pmu_free_hybrid()`: only `out_bad_pmu`.
- `intel_pmu_cpu_dead()`: `x86_pmu.cpu_dead` from `x86_pmu_dead_cpu` on
CPUHP_PERF_X86_PREPARE teardown (init rollback and later CPU down).
- `is_hybrid()` used in `get_possible_counter_mask()`, `is_x86_event()`,
`allocate_fake_cpuc()`, `x86_pmu_event_init()`,
`intel_pmu_cpu_starting()`, `intel_pmu_cpu_dead()`, and `hybrid()`
macros.
**Step 5.3: TRACE CALLEES**
Record: `static_branch_disable()`, `kfree()`. No locks, no I/O.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Boot-time hybrid Intel PMU init (Alder/Raptor/Meteor/Lunar/Arrow
Lake in this tree). Triggered by `check_hw_exists()` failure (broken
PMU, hypervisor without PMU) or `perf_pmu_register()` failure. Not a
normal syscall path; it is a boot/error path. Register-fail UAF runs in
cpuhp teardown while the array is already freed.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same series cleans other hybrid error paths (NMI leak, invalid
`hybrid_pmu()` cast). `01c153956b443` (“Validate the return value of
intel_pmu_init_hybrid()”) is a related NULL-deref fix and is **not** in
this tree; not required here.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.**
- Tree: `p-6.12-3-gc504cf0baa3d8`, `VERSION=6 PATCHLEVEL=12
SUBLEVEL=111`
- `git merge-base --is-ancestor 96746e731e162 HEAD` → not an ancestor
- 6.12 `init_hw_perf_events()` still kfree's on register fail, then
`memset`s at `out_bad_pmu` with no `x86_pmu_free_hybrid()` and no
`static_branch_disable`
- `intel_pmu_init_hybrid()` still allocates and enables `perf_is_hybrid`
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Minor conflicts, easy backport.**
- `git apply --check` of the raw diff fails: `x86_pmu_show_pmu_cap()`
log strings differ, and mainline has `pmi_unregister:` from patch 1.
- The real change is still: add the helper after
`x86_pmu_show_pmu_cap()`, drop the three-line kfree in the register-
fail block, call the helper just before `memset` at `out_bad_pmu`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No `x86_pmu_free_hybrid`, no “Free hybrid state” commit.
Register-fail still does the early `kfree`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: **arch/x86/events (x86 perf PMU)** — **IMPORTANT**. Hybrid Intel
CPUs are common (ADL/RPL/MTL/LNL/ARL). Not core mm/VFS, but production
x86 hardware.
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Mature PMU core with ongoing hybrid work. Bug has been in hybrid
support since it landed, not a last-month feature.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: WHO IS AFFECTED**
Record: Intel hybrid x86 systems where PMU init fails (VMs without a
usable PMU, broken BIOS/MSRs, or `perf_pmu_register` failure). Not
universal; config `PERF_EVENTS` + hybrid CPU models.
**Step 8.2: TRIGGER CONDITIONS**
Record:
- `check_hw_exists()` false after `intel_pmu_init_hybrid()` — leak +
leftover `perf_is_hybrid`. Common-ish in hypervisors; uncommon on
healthy bare metal.
- Hybrid `perf_pmu_register` failure after cpuhp STARTING — **UAF** in
`intel_pmu_cpu_dead()`. Rare (ENOMEM/name clash) but a real error
path.
Not unprivileged-syscall triggered.
**Step 8.3: FAILURE MODE SEVERITY**
Record:
- Register-fail + early kfree: **UAF** → crash/KASAN — **HIGH**
- Early `check_hw_exists` fail: small one-time leak of `num_hybrid_pmus
* sizeof(struct x86_hybrid_pmu)` plus leftover `is_hybrid()` —
**MEDIUM** (leak) / **MEDIUM-HIGH** if later `hybrid()` users run with
a NULL/zeroed `x86_pmu`
Overall: **HIGH** because of the UAF, not only the leak.
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- Benefit: closes UAF + leak + stale static key on hybrid init failure.
High for those systems, zero for others.
- Risk: ~12 lines, `__init` error path only, no locking/API change.
**Low**.
- Ratio: **favor backport**.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Buggy code is in this 6.12 tree (hybrid since 2021).
- Fixes a real leak (`memset` drops `hybrid_pmu` without `kfree`).
- Fixes a real UAF: kfree of `hybrid_pmu` before `cpuhp_remove_state` →
`intel_pmu_cpu_dead()` → `hybrid_pmu(cpuc->pmu)`.
- Also clears `perf_is_hybrid`, which the register-fail path never did.
- Small (12/−3), obviously correct, reviewed by Intel and applied by
Peter Zijlstra.
- Standalone; patch 1 is only context.
AGAINST:
- No production/syzbot report; found in review.
- Register-fail UAF is a rare path.
- Raw mainline diff does not apply cleanly (log text +
`pmi_unregister`).
- One-time init leak alone would be weak; the UAF is what makes it
important.
UNRESOLVED:
- Could not fetch lore HTML (403); used `b4 dig` + Patchew instead.
Reviews/NAKs still verified.
- Exact `sizeof(struct x86_hybrid_pmu)` not measured; leak is still a
bounded boot-time allocation.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — reviewed, tested (`perf
test` on Diamond Rapids/Nova Lake), merged via tip.
2. Fixes a real bug that affects users? **PASS** — leak + UAF + stale
hybrid key on hybrid init failure.
3. Important (crash/security/corruption/deadlock)? **PASS** — UAF on
cpuhp rollback after hybrid register failure; leftover hybrid key
after failed init.
4. Small and contained? **PASS** — one file, ~15 lines.
5. No new features or APIs? **PASS** — static helper on the existing
error path.
6. Can apply to the local tree? **PASS** — needs a trivial backport
(insert helper, drop 3 lines, call before `memset`); no missing APIs.
**Step 9.3: EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/docs exception. Ordinary error-path
memory-safety fix.
**Step 9.4: DECISION**
This tree has the hybrid init bug. The patch is small, correct, and
fixes UAF plus leak on failure. Context from later mainline
(`pmi_unregister`) is not required. It should be backported to this 6.12
tree.
Verification:
- [Phase 1] Tags: Reviewed-by Falcon/Chen; SOB Zijlstra; Link msgid
`...-3-dapeng1.mi@linux.intel.com`; no Fixes/syzbot
- [Phase 1] SHA `96746e731e162` on origin/master; `merge-base --is-
ancestor` vs HEAD = not present
- [Phase 2] Diff: +12/−3 in `arch/x86/events/core.c`; helper + delayed
free + `out_bad_pmu` call
- [Phase 2] 6.12 `init_hw_perf_events` still early-kfrees at lines
2184–2186, then memset at 2200 with no static-key disable
- [Phase 2/5] `intel_pmu_cpu_dead()` uses `hybrid_pmu(cpuc->pmu)` when
`is_hybrid()`; `x86_pmu_dead_cpu` is the PREPARE teardown
- [Phase 3] Hybrid register path blamed to `d9977c43bff89` (2021);
alloc/key to `97588df87b56e2` (2023)
- [Phase 3] Parent `91787047b1dc5` (NMI unregister) not in HEAD; not
required
- [Phase 4] `b4 dig -c 96746e731e162` matched v3 2/8; v1→v3 hunk
unchanged; no NAK
- [Phase 4] Cover letter: review-found bugs; Zide Chen Reviewed-by for
series
- [Phase 4] lore.kernel.org HTTP 403; Patchew used instead
- [Phase 5] `intel_pmu_init_hybrid()` enables `perf_is_hybrid` after
`kcalloc` (this tree, ~6360)
- [Phase 6] `git describe HEAD` = p-6.12-3-gc504cf0baa3d8; `make
kernelversion` = 6.12.111
- [Phase 6] `git apply --check` of raw commit fails on
`x86_pmu_show_pmu_cap` context; logic still maps onto 6.12
`out_bad_pmu`
- [Phase 8] Failure mode: UAF in `intel_pmu_cpu_dead` after hybrid
register fail; leak on `check_hw_exists` fail
- UNVERIFIED: live reproduction of `perf_pmu_register` failure; exact
leaked byte count
The fix is small, matches this tree’s hybrid init code, and closes a
real UAF/leak on PMU init failure.
**YES**
arch/x86/events/core.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 2aa9270446634..7c37c228a88a4 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2087,6 +2087,17 @@ void x86_pmu_show_pmu_cap(struct pmu *pmu)
pr_info("... global_ctrl mask: %016llx\n", hybrid(pmu, intel_ctrl));
}
+static void x86_pmu_free_hybrid(void)
+{
+ if (!x86_pmu.hybrid_pmu)
+ return;
+
+ static_branch_disable(&perf_is_hybrid);
+ kfree(x86_pmu.hybrid_pmu);
+ x86_pmu.hybrid_pmu = NULL;
+ x86_pmu.num_hybrid_pmus = 0;
+}
+
static int __init init_hw_perf_events(void)
{
struct x86_pmu_quirk *quirk;
@@ -2214,9 +2225,6 @@ static int __init init_hw_perf_events(void)
for (j = 0; j < i; j++)
perf_pmu_unregister(&x86_pmu.hybrid_pmu[j].pmu);
pr_warn("Failed to register hybrid PMUs\n");
- kfree(x86_pmu.hybrid_pmu);
- x86_pmu.hybrid_pmu = NULL;
- x86_pmu.num_hybrid_pmus = 0;
goto out2;
}
}
@@ -2232,6 +2240,7 @@ static int __init init_hw_perf_events(void)
pmi_unregister:
unregister_nmi_handler(NMI_LOCAL, "PMI");
out_bad_pmu:
+ x86_pmu_free_hybrid();
memset(&x86_pmu, 0, sizeof(x86_pmu));
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: validate XCP topology counts before division
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (18 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] perf/x86: Free hybrid state on PMU init failure Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] ALSA: hda/realtek: Add quirk for Lenovo IdeaPad Slim 3 15ABR8 Sasha Levin
` (496 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Asad Kamal, Lijo Lazar, Hawking Zhang, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Asad Kamal <asad.kamal@amd.com>
[ Upstream commit 0eda57ee303b4392057b7d4c32e8fda9d14cffad ]
In aqua_vanjaram_get_xcp_res_info(), max_res[i] can be zero.
When res_lt_xcp is true the code divides num_xcp by max_res[i],
causing a divide fault.
Skip the loop body for absent resources.
v2: Remove redundant checks (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a divide-by-zero oops in MI300 XCP sysfs init. The buggy loop is
in this 6.18.y tree; the fix is a 3-line skip for a zero resource count.
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Subsystem: `drm/amdgpu`
- Action verb: `validate` (defensive correctness; body is an explicit
divide-fault fix)
- Claimed intent: do not divide XCP topology counts when a resource
count is zero
Record: `[drm/amdgpu] [validate] [skip XCP resource loop when
max_res[i]==0 to avoid divide-by-zero]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- No `Fixes:` tag (expected for this review pipeline)
- No `Reported-by:`, `Tested-by:`, `Link:`, or `Cc: stable@`
- `Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>` — original author of
this function
- `Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>`
- `Signed-off-by: Asad Kamal <asad.kamal@amd.com>` (author)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (amdgpu
maintainer)
- Ignored pipeline tags: `[Upstream commit 0eda57ee…]`, `Signed-off-by:
Sasha Levin`
Record: Author + two AMD reviewers + maintainer SOB. No syzbot/user
report tag.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Bug: in `aqua_vanjaram_get_xcp_res_info()`, `max_res[i]` can be 0.
When `res_lt_xcp` is true the code does `num_xcp / max_res[i]`.
- Symptom: kernel divide fault (oops/exception).
- Fix: skip the loop body for absent resources.
- `v2: Remove redundant checks (Lijo)` — review-driven simplification.
Record: `[Bug: division by zero on zero resource counts] [Failure:
divide fault] [No version range stated] [Root cause: max_res[i]==0 with
res_lt_xcp true]`
**Step 1.4: DETECT HIDDEN BUG FIXES**
Not hidden. The message names the divide fault and the skip.
Record: `[Not a disguised cleanup; explicit divide-by-zero fix]`
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- File: `drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c` (+3/−1)
- Function: `aqua_vanjaram_get_xcp_res_info()`
- Scope: single-file, surgical
Record: `[1 file, +3/-1, one function, surgical]`
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Before (v6.18.53):
```
for each resource:
res_lt_xcp = max_res[i] < num_xcp;
set id;
num_inst = res_lt_xcp ? 1 : max_res[i] / num_xcp;
num_shared = res_lt_xcp ? num_xcp / max_res[i] : 1;
```
After:
```
for each resource:
set id;
if (!max_res[i]) continue; // leave num_inst/num_shared at 0
... same arithmetic ...
```
The `continue` is on the per-resource fill path used at sysfs init and
on partition-mode store.
Record: `[zero count: divide -> skip and keep zeros]`
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Category: logic / memory-safety adjacent (integer divide-by-zero).
`max_res[]` is `= {}` then filled from:
- XCC: `NUM_XCC(adev->gfx.xcc_mask)`
- DMA: `adev->sdma.num_instances`
- DEC: `adev->vcn.num_vcn_inst`
- JPEG: `adev->jpeg.num_jpeg_inst`
`aqua_vanjaram_init_soc_config()` sets VCN/JPEG counts from
`hweight32(inst_mask)`. Discovery starts `vcn.inst_mask` /
`jpeg.inst_mask` at 0 and only sets bits when VCN IPs exist; harvest can
clear those bits. If a count is 0 and `num_xcp > 0` (SPX=1, DPX=2,
TPX=3, QPX=4, CPX=XCC count), then `res_lt_xcp` is true and `num_xcp /
max_res[i]` is a divide fault.
Record: `[divide-by-zero] [absent VCN/JPEG/SDMA/XCC count vs non-zero
partition count]`
**Step 2.4: ASSESS THE FIX QUALITY**
Obviously correct: skip the division when the divisor is 0. `xcp_cfg` is
`kzalloc`’d in `amdgpu_xcp_cfg_sysfs_init()`, so skipped entries keep
`num_inst`/`num_shared` = 0, which matches “absent”. Sysfs still creates
the `dec`/`jpeg` kobjects (id is still set); they report 0 instead of
oopsing.
Regression risk is very low. No API/locking/refcount change. v2 dropped
extra checks at Lijo’s request.
Record: `[minimal, correct] [very low regression risk]`
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
On v6.18.53, the loop is from `f501057aff3357` (`drm/amdgpu: Add
callback get xcp resource info`, Lijo Lazar, 2024-09-09). Present in
v6.13; not in v6.12. Wrapper/NPS split later in `3aa37922c66a63` /
`e5ad71779df6f4`; the divide itself is original.
Record: `[f501057aff3357, first in v6.13; in this 6.18.y tree]`
**Step 3.2: FOLLOW THE FIXES: TAG**
No `Fixes:` tag.
Record: `[N/A — no Fixes tag; buggy commit identified by blame]`
**Step 3.3: CHECK FILE HISTORY**
Recent v6.18.53 history on this file is XCP/NPS/partition work. No prior
zero-divisor guard in this loop. Later autosel commit `9bd596d9e90da`
(`Guard reads in pcie state readout`) is unrelated.
Record: `[standalone; no prerequisite series for this skip]`
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Asad Kamal is an AMD amdgpu contributor. Lijo Lazar has 20 commits on
this file in 6.18.y and wrote the function; his Reviewed-by is strong.
Record: `[AMD author; reviewed by function author and amdgpu
maintainer]`
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Uses existing `max_res[]` loop only. Sibling mainline patch `guard zero
divisors in soc_v1_0 partition code` is a different ASIC file;
`soc_v1_0` is **not** in this tree. This patch is self-contained.
Record: `[no local dependencies; applies standalone]`
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
`b4 dig -c 0eda57ee…` failed: lore.kernel.org returned an error.
Fallback: amd-gfx archives.
- v2 submission: https://lists.freedesktop.org/archives/amd-
gfx/2026-June/146963.html
- Hawking Reviewed-by: https://lists.freedesktop.org/archives/amd-
gfx/2026-June/146976.html
- May–July 2026 archives: only v2, no public v1 (v1 likely internal;
message says Lijo asked to drop redundant checks)
- No NAK
Record: `[amd-gfx v2 + Hawking RB; no NAK; v1 not on the public list]`
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
v2 To/Cc: amd-gfx, Lijo Lazar, Hawking Zhang, Le Ma, Morris Zhang, Alex
Deucher, Yang Wang. Right maintainers.
Record: `[Lijo + Hawking reviewed; Deucher merged]`
**Step 4.3: SEARCH FOR THE BUG REPORT**
No bugzilla/syzbot/Link. Hardware-path analysis by AMD, not a fuzzer ID.
Record: `[no public crash dump; AMD-described divide fault]`
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Standalone `[PATCH v2]`, not `n/N`. Related only as the same round of
divisor guards (`soc_v1_0` not in 6.18.y).
Record: `[standalone; soc_v1_0 sibling N/A here]`
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
lore.kernel.org/stable/?q=… returned 403. No evidence this was rejected
for stable.
Record: `[UNVERIFIED: stable list discussion (HTTP 403)]`
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `[aqua_vanjaram_get_xcp_res_info]`
**Step 5.2: TRACE CALLERS**
Callback `.get_xcp_res_info` in `aqua_vanjaram_xcp_funcs`. Only call
sites of `amdgpu_xcp_get_res_info()`:
1. `amdgpu_xcp_cfg_sysfs_init()` — `amdgpu_xcp_sysfs_init()` ←
`amdgpu_device.c` during device init
2. `xcp_config_store()` — sysfs `xcp_config` (`__ATTR_RW_MODE(...,
0644)`), typically CAP_SYS_ADMIN/root
Record: `[GPU probe sysfs init + privileged sysfs store]`
**Step 5.3: TRACE CALLEES**
`__aqua_vanjaram_get_px_mode_info()` sets `num_xcp` to 1/2/3/4 or
`NUM_XCC`. No alloc/lock in the changed loop.
Record: `[fills xcp_cfg for sysfs; no new side effects]`
**Step 5.4: FOLLOW THE CALL CHAIN**
Probe: discovery → `aqua_vanjaram_init_soc_config()` (GC 9.4.3 / 9.4.4 /
9.5.0) → later `amdgpu_xcp_sysfs_init()` → this function. Userspace can
also write `compute_partition_config/xcp_config`.
Record: `[reachable on MI300-class probe and partition sysfs; not a dead
path]`
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Only implementation of `get_xcp_res_info` in this tree. Mainline
`soc_v1_0` guard is a sibling, not present here.
Record: `[no other local copy of this loop]`
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Local tree: **v6.18.53** (`VERSION=6 PATCHLEVEL=18 SUBLEVEL=53`, `git
describe HEAD` = `v6.18.53-5049-g0f0bdc2b0dffb`, branch `autosel`).
v6.18.53 `aqua_vanjaram_get_xcp_res_info()` still does `num_xcp /
max_res[i]` with no zero check. Upstream `0eda57ee` is **not** an
ancestor of HEAD. Introducing commit `f501057aff3357` **is** an ancestor
of v6.18.53.
Record: `[YES, buggy loop is in v6.18.53] [bug from v6.13 /
f501057aff3357]`
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
v6.18.53 loop matches the patch preimage exactly. Clean apply; no
refactor in the way.
Record: `[clean apply]`
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
No other zero-divisor fix for this loop in v6.18.53.
Record: `[no substitute fix in this tree]`
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
`drivers/gpu/drm/amd/amdgpu` — AMD GPU driver, Aqua Vanjaram XCP
(MI300/MI325/MI350-class, GC 9.4.3/9.4.4/9.5.0).
Record: `[amdgpu XCP] [IMPORTANT — datacenter Instinct GPUs, not core
mm/fs]`
**Step 7.2: SUBSYSTEM ACTIVITY**
File is actively maintained (partition/NPS/XCP changes). The divide is
old (6.13), not a last-week feature.
Record: `[active driver; bug has been in-tree since v6.13]`
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Users of amdgpu on Aqua Vanjaram ASICs (MI300A/X, MI325, GC 9.5.0) with
XCP sysfs. Not universal.
Record: `[driver-specific / platform-specific (MI300-class)]`
**Step 8.2: TRIGGER CONDITIONS**
Always runs at XCP sysfs init if `xcp_mgr` exists. Faults when any
`max_res[i]` is 0 — verified possible for VCN/JPEG via `inst_mask==0`
after discovery/harvest. Also on writing partition mode. Unprivileged
users do not normally write that sysfs node (0400 resource attrs; store
is 0644 on a root-owned kobject). Probe path does not need a user
trigger.
Record: `[probe + partition sysfs] [likely on harvested/no-VCN configs]
[unprivileged write not required]`
**Step 8.3: FAILURE MODE SEVERITY**
x86 `#DE` in kernel → oops. During device init this can fail GPU bring-
up or panic if `panic_on_oops`. Not silent corruption.
Record: `[kernel oops / GPU init crash] [CRITICAL/HIGH]`
**Step 8.4: RISK-BENEFIT RATIO**
Benefit: stop a real divide oops on MI300-class XCP sysfs. Risk: 3
lines, skip-only, zeros already from kzalloc.
Record: `[high benefit for affected GPUs] [very low risk] [favorable]`
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real divide-by-zero; oops on XCP sysfs init / partition store
- Buggy code is in this v6.18.53 tree
- Counts can be 0 (VCN/JPEG `inst_mask` from discovery/harvest)
- 3-line skip; obviously correct; v2 reviewed by the function author and
Hawking; merged by Deucher
- Clean apply; no new API; no series dependency
AGAINST:
- Affects only MI300-class XCP, not all machines
- No public reproducer/syzbot
- v1 mailing-list text not found
UNRESOLVED:
- Stable-list discussion (lore 403)
- Exact public v1 diff
- How often production MI300 SKUs have `num_vcn_inst==0` (AMD still
treated it as real)
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — skip on zero divisor; two
AMD R-b, maintainer SOB
2. Real bug that affects users? **PASS** — divide fault in driver
init/sysfs
3. Important (crash/security/corruption/deadlock)? **PASS** — kernel
oops
4. Small and contained? **PASS** — +3/−1, one function
5. No new features or APIs? **PASS**
6. Can apply to local tree? **PASS** — v6.18.53 preimage matches
**Step 9.3: EXCEPTION CATEGORIES**
Not ID/quirk/DT/docs. Direct crash fix.
**Step 9.4: DECISION**
Backport. It is a small, obviously correct oops fix for code this tree
actually runs.
### Why this matters for this tree
v6.18.y ships Aqua Vanjaram XCP resource sysfs. If VCN/JPEG/SDMA/XCC
count is 0, `num_xcp / max_res[i]` oopses during
`amdgpu_xcp_cfg_sysfs_init()` or a partition-mode store. Skipping empty
resources stops the fault and reports 0 instances.
### Risk vs benefit
Benefit is avoiding a GPU-init oops on MI300-class systems. Risk is a
continue that leaves kzalloc zeros. No locking or ABI change.
### Concerns
None material. `soc_v1_0` sibling is not needed here. No follow-up on
this loop in this tree.
Verification:
- [Phase 1] Tags: Reviewed-by Lijo Lazar, Hawking Zhang; SOB Alex
Deucher; no Fixes/syzbot
- [Phase 2] Diff: +3/−1 in `aqua_vanjaram_get_xcp_res_info()`; `if
(!max_res[i]) continue` before `num_xcp / max_res[i]`
- [Phase 3] `git blame` v6.18.53: loop from `f501057aff3357` (in v6.13;
not v6.12); `git merge-base --is-ancestor f501057aff3357 v6.18.53`
succeeded
- [Phase 3] No Fixes tag; no later related fix on this loop in v6.18.53
- [Phase 4] `b4 dig -c 0eda57ee…`: lore error; found v2 at
lists.freedesktop.org/amd-gfx/2026-June/146963.html; Hawking RB
146976.html; no NAK
- [Phase 4] UNVERIFIED: stable@ thread (lore 403); public v1 body
- [Phase 5] Callers: `amdgpu_xcp_cfg_sysfs_init` (device init) and
`xcp_config_store` (sysfs)
- [Phase 5] `adev->vcn.inst_mask` starts 0 in `amdgpu_discovery.c`;
harvest can clear bits; `aqua_vanjaram_init_soc_config` sets
`num_vcn_inst = hweight32(inst_mask)`
- [Phase 6] `git describe HEAD`: v6.18.53-5049-g0f0bdc2b0dffb; `make
kernelversion`: 6.18.53
- [Phase 6] v6.18.53 file has the unfixed loop (`has skip? False`);
`0eda57ee` is not an ancestor of HEAD
- [Phase 8] Failure mode: kernel divide fault / oops on XCP sysfs init,
severity HIGH/CRITICAL
- UNVERIFIED: frequency of zero VCN/JPEG on shipping MI300 SKUs (does
not override the verified divide path)
**YES**
drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
index f9e2edf5260bc..15e70415c35b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
+++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
@@ -295,8 +295,10 @@ static int aqua_vanjaram_get_xcp_res_info(struct amdgpu_xcp_mgr *xcp_mgr,
xcp_cfg->num_res = ARRAY_SIZE(max_res);
for (i = 0; i < xcp_cfg->num_res; i++) {
- res_lt_xcp = max_res[i] < num_xcp;
xcp_cfg->xcp_res[i].id = i;
+ if (!max_res[i])
+ continue;
+ res_lt_xcp = max_res[i] < num_xcp;
xcp_cfg->xcp_res[i].num_inst =
res_lt_xcp ? 1 : max_res[i] / num_xcp;
xcp_cfg->xcp_res[i].num_inst =
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] ALSA: hda/realtek: Add quirk for Lenovo IdeaPad Slim 3 15ABR8
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (19 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/amdgpu: validate XCP topology counts before division Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] i2c: qup: Propagate clock enable failures Sasha Levin
` (495 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Zhang Heng, Takashi Iwai, Sasha Levin, perex, tiwai, linux-sound,
linux-kernel
From: Zhang Heng <zhangheng@kylinos.cn>
[ Upstream commit be79a45e2ec289eb9fad519e8f5a3d4fc3789dd0 ]
The internal microphone on Lenovo IdeaPad Slim 3 15ABR8 (subsystem
17aa:3862) exhibits severe distortion at default gain levels. The
Capture Volume is fixed at 63 (max) and cannot be lowered without
explicit userspace intervention. The existing fixup
ALC269_FIXUP_LIMIT_INT_MIC_BOOST limits the gain range and resolves
the issue.
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221891
Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
Link: https://patch.msgid.link/20260824123752.525173-1-zhangheng@kylinos.cn
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line Realtek HDA hardware quirk for a specific Lenovo
laptop. The local tree is **6.12.111** (`pending-6.12`). The Realtek
quirk table and `ALC269_FIXUP_LIMIT_INT_MIC_BOOST` already exist here;
SSID `17aa:3862` does not.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: **[ALSA/hda/realtek] [Add] [quirk for Lenovo IdeaPad Slim 3
15ABR8]**
- Subsystem prefix: `ALSA: hda/realtek`
- Action verb: **Add** (hardware quirk table entry, not a new feature)
- Claimed intent: map PCI subsystem `17aa:3862` to an existing internal-
mic boost limit fixup
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- `Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221891` — user-
filed kernel.org bug
- `Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>` — author
- `Link: https://patch.msgid.link/20260824123752.525173-1-
zhangheng@kylinos.cn` — original submission msgid
- `Signed-off-by: Takashi Iwai <tiwai@suse.de>` — ALSA HDA maintainer
applied it
- No `Fixes:`, no `Cc: stable`, no `Reported-by`, no `Tested-by`, no
`Reviewed-by` (absence of `Fixes:`/`Cc: stable` is expected for this
review)
- Notable: maintainer SOB plus a `Closes:` bugzilla link
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record:
- **Bug:** Internal mic on IdeaPad Slim 3 15ABR8 (`17aa:3862`) has
severe distortion at default gain
- **Symptom:** Capture Volume stuck at 63 (max); cannot be lowered
without explicit userspace intervention; captured audio is badly
distorted
- **Root cause (author):** default amp/boost range is too high for
this hardware
- **Fix:** reuse existing `ALC269_FIXUP_LIMIT_INT_MIC_BOOST`
- **Version info:** none in the message; laptop is a 2023 AMD IdeaPad,
so 6.12 users are in the affected population
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: Not a hidden fix. It is an explicit hardware quirk. The “Add”
verb is the standard form for `SND_PCI_QUIRK` table entries that make
existing hardware usable.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
- Record:
- File in the commit: `sound/hda/codecs/realtek/alc269.c` (**+1 /
−0**)
- Function/table: `alc269_fixup_tbl[]`
- Scope: **single-file surgical** — one `SND_PCI_QUIRK` line
- Local tree equivalent file: `sound/pci/hda/patch_realtek.c` (HDA
codecs were not yet split out of `sound/pci/hda/` in 6.12)
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record: **Before** — SSID `17aa:3862` matches no quirk; probe uses
generic auto-config; internal mic boost stays at the default wide
range, Capture Volume sits at max, audio is distorted.
**After** — `snd_hda_pick_fixup()` matches
`ALC269_FIXUP_LIMIT_INT_MIC_BOOST`. At `HDA_FIXUP_ACT_PROBE`,
`alc269_fixup_limit_int_mic_boost()` walks auto-config inputs, and for
internal mic pins overrides amp caps to 0 offset, 1 step, step size
`0x2f` (boost limited to 0 or 1). Only the probe path for this SSID is
affected.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record: **[Hardware workaround / audio codec quirk]**
- Mechanism: Realtek codec exposes boost steps 2 and 3 that are too
noisy on this chassis. The existing helper comments: “The mic boosts
on level 2 and 3 are too noisy on the internal mic input. Therefore
limit the boost to 0 or 1.”
- The new line only *selects* that already-present helper for one PCI
subsystem ID.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record: Obviously correct and minimal. Same pattern already used for
ThinkPad T480, Positivo ARN50/N14AP7, several Asus/VAIO machines, etc.
- Regression risk: **very low**. Match is vendor+device SSID
`17aa:3862` only. `ALC269_FIXUP_LIMIT_INT_MIC_BOOST` also chains to
`ALC269_FIXUP_THINKPAD_ACPI`, but `hda_fixup_thinkpad_acpi()`
returns immediately unless ACPI IDs `LEN0068`/`LEN0268`/`IBM0068`
exist, so LED binding does not run on an IdeaPad.
`alc_fixup_no_shutup()` still runs (reduces click noise); that same
chain is already used by other non-ThinkPad LIMIT_INT_MIC_BOOST
quirks in this tree.
- No public API, no new fixup enum, no new module parameter.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
- Record: There is no “buggy line” in the table; the bug is a
**missing** entry. Neighboring rows in this tree:
- `0x3855` Legion 7 16ITHG6 — `1e24881d8b2a7c` (2022)
- `0x3865` Lenovo 13X — `25f46354dca912` (2024)
- Insertion sits in a long-stable Lenovo SSID block. The helper
`alc269_fixup_limit_int_mic_boost()` was introduced in
`3e0d611b2045b` (2013-04-22, “Limit internal mic boost for a few
Asus machines”) and has been in-tree for years.
**Step 3.2: FOLLOW THE FIXES: TAG**
- Record: No `Fixes:` tag. Not applicable. The “bug” is hardware that
never had a quirk, not a regression from a prior commit.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
- Record: Recent `patch_realtek.c` history is almost entirely other
`SND_PCI_QUIRK` additions (HP mute LED, Legion, Yoga, etc.). Same-
fixup examples already in this 6.12 tree:
- `85981dfd6b0a0` Limit mic boost on T480 (`Cc: stable`)
- `86a433862912f` Limit mic boost on N14AP7 (`Cc: stable`)
- `d44418f5024f6` Limit mic boost on Positivo ARN50 (already
backported here as `[ Upstream commit 76b0a22d4cf7... ]`)
- Standalone. Not patch X/Y.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
- Record: Zhang Heng has other sound quirks in this tree (ASUS UM6702RC,
Inspur S14-G1, Samsung 750XBE, AMD YC DMI quirks). Regular hardware-
quirk contributor, not the subsystem maintainer. Maintainer Takashi
Iwai applied it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
- Record: None. Depends only on `SND_PCI_QUIRK`,
`ALC269_FIXUP_LIMIT_INT_MIC_BOOST`, and `alc269_fixup_tbl[]`, all
present in 6.12. Can apply standalone with a path remap (`alc269.c` →
`patch_realtek.c`).
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record: `b4 dig -c` could not be used: this SHA is not in the local
tree. Recovered via msgid
`20260824123752.525173-1-zhangheng@kylinos.cn`.
- Submission: https://lists.openwall.net/linux-kernel/2026/08/24/1126
(also lkml.iu.edu/2608.3/00949.html)
- Single-patch v1 only; diff is the same one-line quirk as committed
- To: `tiwai@suse.de`; Cc: `linux-sound`, `linux-kernel`
- Maintainer reply (Takashi Iwai, 2026-08-25): **“Applied now.
Thanks.”** (lkml.iu.edu/2608.3/02564.html)
- No NAK, no requested respin, no stable discussion in the thread
- Lore.kernel.org itself returned Anubis/403 to automated fetch
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
- Record: Sent directly to Takashi Iwai (ALSA HDA maintainer) and linux-
sound. Maintainer applied v1 as-is. No other reviewer comments found.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: Bugzilla 221891 was 403/Anubis; full comments **UNVERIFIED**.
The `Closes:` tag plus the commit body (SSID, Capture Volume 63,
distortion) are the verified description.
- Related real-world report: Ask Ubuntu “Audio issues on Lenovo
Ideapad Slim 3 **16ABR8** — microphone distortion” (sibling ABR8
chassis, same symptom class). That report is 16ABR8, not
15ABR8/`17aa:3862`, so it does **not** prove this SSID, only that
the product family has this class of mic problem.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
- Record: Standalone 1/1. No series. No extra Realtek patches required.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
- Record: lore.kernel.org/stable search blocked (Anubis). No evidence in
this tree that this SSID was already requested or rejected. Identical
LIMIT_INT_MIC_BOOST quirks have been accepted into this 6.12 tree
before.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
- Record: No function body changed. New table entry in
`alc269_fixup_tbl[]`. Runtime functions involved:
`snd_hda_pick_fixup()` → `alc269_fixup_limit_int_mic_boost()` (and
chained `alc_fixup_thinkpad_acpi()`).
**Step 5.2: TRACE CALLERS**
- Record: `alc269_fixup_tbl` is passed from the ALC269-family probe
path:
```12583:12584:sound/pci/hda/patch_realtek.c
snd_hda_pick_fixup(codec, alc269_fixup_models,
alc269_fixup_tbl, alc269_fixups);
```
That runs during codec probe (device enumeration / module load), not a
syscall hot path. Reachable on every boot for machines with a Realtek
ALC269-family HDA codec.
**Step 5.3: TRACE CALLEES**
- Record: `alc269_fixup_limit_int_mic_boost()` uses
`snd_hda_codec_get_pincfg()`, `snd_hda_get_input_pin_attr()`,
`snd_hda_override_amp_caps()`. Probe-time mixer cap override only; no
allocation, no new locks.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: Userspace does not need a special trigger. Opening the capture
device at default volume is enough. Unprivileged users of this laptop
hit it (PulseAudio/PipeWire default capture). High user visibility,
hardware-specific.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
- Record: Many `SND_PCI_QUIRK(..., ALC269_FIXUP_LIMIT_INT_MIC_BOOST)`
entries already in this file (ThinkPads
`0x2215`/`0x225d`/`0x5013`/`0x5026`/`0x5109`, Asus
`0x106d`/`0x115d`/`0x1c23`, Positivo, VAIO). This is a systematic,
well-worn workaround, not a one-off invention.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
- Record: **Yes, as a missing quirk.** Local tree:
`p-6.12-3-gc504cf0baa3d8`, `VERSION=6 PATCHLEVEL=12 SUBLEVEL=111`.
- `sound/hda/codecs/realtek/` does **not** exist (split is post-6.12).
- `sound/pci/hda/patch_realtek.c` **does** exist; `alc269_fixup_tbl[]`
at line 10675; LIMIT_INT_MIC_BOOST at 8711–8716 and function at
6661–6691.
- `git grep 0x3862 -- sound/pci/hda/` : **no match**. Between 0x3855
and 0x3865 there is a hole exactly where the new line goes (lines
11565–11566).
- Bug “introduced”: never fixed here; hardware existed well before
v6.12 (released 2024-11-17).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
- Record: **Minor path remap, otherwise clean.** Neighboring context in
this tree is identical to the mainline hunk (`0x3855` Legion then
`0x3865` Lenovo 13X). Need to apply to `sound/pci/hda/patch_realtek.c`
instead of `sound/hda/codecs/realtek/alc269.c`. No conflicting SSID,
no missing helper.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
- Record: No `IdeaPad Slim 3 15ABR8` and no `17aa:3862` in
`sound/pci/hda/`. Sibling IdeaPad Slim 9i 14ITL5 is a different
SSID/fixup. No earlier version of this fix.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
- Record: **[sound/pci/hda Realtek codec] [IMPORTANT]** — not core
mm/vfs, but the default laptop audio stack.
`CONFIG_SND_HDA_CODEC_REALTEK` is a standard distro config.
Criticality is hardware-specific, not peripheral/staging.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
- Record: Very active: recent history is a stream of model quirks.
Mature table, mature helper (2013). Quirk additions are the normal
stable-friendly change in this file.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
- Record: **driver-specific / hardware-specific** — only PCI SSID
`17aa:3862` (Lenovo IdeaPad Slim 3 15ABR8). Everyone else unchanged.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
- Record: Trigger is default capture on this laptop (every
VoIP/recording session). Common for owners of this model. Unprivileged
users can trigger it. Not a race.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
- Record: **[Internal mic unusable / severe distortion] [MEDIUM
functionally; HIGH for that hardware]**
- Not panic, UAF, or data corruption
- Internal microphone is effectively broken at default settings;
userspace volume workarounds are the only current escape
- This is the documented audio-codec quirk class, routinely taken into
stable
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
- Record:
- **Benefit:** High for 15ABR8 owners on 6.12; mic works without mixer
hacks
- **Risk:** Very low — 1 line, SSID-gated, helper used for a decade,
same pattern already backported here
- **Ratio:** strongly in favor of backport
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real hardware bug with a kernel.org bugzilla `Closes:` (221891)
- Severe mic distortion; capture stuck at max gain
- Classic `SND_PCI_QUIRK` exception (explicitly stable-appropriate)
- 1 line, existing fixup from 2013
- Helper and table present in 6.12; SSID absent
- Maintainer (Takashi Iwai) applied v1 with no objections
- Identical LIMIT_INT_MIC_BOOST quirks already in this 6.12 tree (T480,
N14AP7, Positivo ARN50)
AGAINST:
- Not a crash/security/deadlock (strict reading of “important issue”)
- Mainline path differs (`alc269.c` vs `patch_realtek.c`) — trivial
remap
- Full bugzilla text could not be fetched (403)
- `b4 dig` could not run without a local SHA
UNRESOLVED:
- Full bugzilla 221891 comments
- Whether any other chassis silently shares SSID `17aa:3862` (no in-tree
collision)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one SSID line to a long-used
helper; maintainer applied; same pattern proven in this tree
2. Fixes a real bug that affects users? **PASS** — unusable/distorted
internal mic; bugzilla + concrete SSID
3. Important issue? **PASS via hardware-quirk exception** — not a kernel
oops, but a device-breaking audio defect of the class stable already
takes (`SND_PCI_QUIRK` in `patch_realtek.c`)
4. Small and contained? **PASS** — +1 line
5. No new features or APIs? **PASS** — table entry only
6. Can apply to the local tree? **PASS** — remap path to
`sound/pci/hda/patch_realtek.c`; context around 0x3855/0x3865 matches
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
- Record: **AUDIO CODEC QUIRK / hardware workaround** — `SND_PCI_QUIRK`
in the Realtek HDA table. This is an automatic YES category.
**Step 9.4: MAKE YOUR DECISION**
Backport. The bug exists on 6.12 for this laptop, the fix is the
standard one-line quirk, and the only adjustment is the post-6.12
filename change.
------------------------------------------------
What the commit solves and why it matters here
------------------------------------------------
On IdeaPad Slim 3 15ABR8 the Realtek internal mic boost range is too
high, so Capture Volume sits at 63 and recordings are badly distorted.
6.12 already has `alc269_fixup_limit_int_mic_boost()`; it just never
binds it to `17aa:3862`. Adding that binding restores usable capture for
that model without touching any other machine.
Risk vs benefit: one SSID-gated line vs a broken laptop microphone.
Benefit dominates. Backport applies to `patch_realtek.c` between the
existing `0x3855` and `0x3865` rows.
------------------------------------------------
Verification
------------------------------------------------
- [Phase 1] Parsed tags: `Closes: bugzilla 221891`, msgid link, SOB
Zhang Heng + Takashi Iwai; no Fixes/Cc-stable
- [Phase 2] Diff: +1 `SND_PCI_QUIRK(0x17aa, 0x3862, ...,
ALC269_FIXUP_LIMIT_INT_MIC_BOOST)` in `alc269_fixup_tbl`
- [Phase 2] Read `alc269_fixup_limit_int_mic_boost()` at
`patch_realtek.c:6661-6691` — probe-time amp-cap override for internal
mic pins
- [Phase 2] Read `ALC269_FIXUP_LIMIT_INT_MIC_BOOST` at 8711-8716 —
chains to THINKPAD_ACPI
- [Phase 2] Read `hda_fixup_thinkpad_acpi()` / `is_thinkpad()` in
`thinkpad_helper.c` — LED path skipped without ThinkPad ACPI IDs
- [Phase 3] `git log -S ALC269_FIXUP_LIMIT_INT_MIC_BOOST --
sound/pci/hda/patch_realtek.c`: introduced `3e0d611b2045b` (2013)
- [Phase 3] Similar quirks already in this tree: T480 `85981dfd6b0a0`,
N14AP7 `86a433862912f`, Positivo ARN50 `d44418f5024f6`
- [Phase 3] `git log --grep='IdeaPad Slim 3 15ABR8' -- sound/pci/hda/`:
empty
- [Phase 4] Openwall + IU LKML: v1 patch identical to commit; Takashi
“Applied now. Thanks.”
- [Phase 4] lore.kernel.org and bugzilla HTML/REST: 403 Anubis — full
bugzilla body UNVERIFIED
- [Phase 4] `b4 dig -c`: not run; commit SHA not in this checkout
- [Phase 5] Caller: `snd_hda_pick_fixup(..., alc269_fixup_tbl, ...)` at
probe (`patch_realtek.c:12583`)
- [Phase 6] `git describe HEAD` → `p-6.12-3-gc504cf0baa3d8`; `make
kernelversion` → 6.12.111
- [Phase 6] `sound/hda/codecs/realtek` missing;
`sound/pci/hda/patch_realtek.c` present
- [Phase 6] `git grep 0x3862 -- sound/pci/hda/`: no hits; hole between
0x3855 and 0x3865 at lines 11565-11566
- [Phase 8] Failure mode: distorted/unusable internal mic, SSID-
specific; severity medium globally, high for that laptop
- UNVERIFIED: full text of bugzilla 221891; whether any other product
silently uses SSID 17aa:3862
**YES**
sound/hda/codecs/realtek/alc269.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 8196235c31d2b..bc87062f86da7 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -7515,6 +7515,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
+ SND_PCI_QUIRK(0x17aa, 0x3862, "Lenovo IdeaPad Slim 3 15ABR8", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x17aa, 0x3865, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3866, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] i2c: qup: Propagate clock enable failures
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (20 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] ALSA: hda/realtek: Add quirk for Lenovo IdeaPad Slim 3 15ABR8 Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] sched_ext/scx_flatcg: expire cached hweights on weight changes Sasha Levin
` (494 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Konrad Dybcio, Andi Shyti, Sasha Levin,
linux-arm-msm, linux-i2c, linux-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit a477626332800942f463d76aa48db0c47f1dfd18 ]
The QUP I2C driver treats the core and iface clocks as required
resources, but qup_i2c_enable_clocks() ignores clk_prepare_enable()
failures. Probe can then continue to register the I2C adapter, and
runtime/system resume can return success, even when a required clock
transition failed.
Make the helper return an error, unwind a partially enabled clock, and
propagate failures from probe and resume paths.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260624055237.29977-1-pengpeng@iscas.ac.cn
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is **v7.3-rc4**. The driver and the ignored-clock-
enable bug exist in this lineage (since v3.15); the fix is a small,
self-contained error-path change that belongs in this tree.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[i2c: qup]** **[Propagate]** — make `clk_prepare_enable()`
failures visible instead of swallowing them.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** Konrad Dybcio (Qualcomm / linux-arm-msm)
- **Acked-by:** none
- **Link:**
https://lore.kernel.org/r/20260624055237.29977-1-pengpeng@iscas.ac.cn
- **Cc: stable:** none (expected)
- **Signed-off-by:** Pengpeng Hou (author); Andi Shyti (I2C maintainer)
- No syzbot / kernel test robot tags
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `qup_i2c_enable_clocks()` treats core and iface clocks as
required, but ignores `clk_prepare_enable()` return values.
- **Symptoms:** probe still registers the I2C adapter; runtime/system
resume still return success after a required clock failed.
- **Version info:** none in the message. Git shows the ignore-return
pattern since the driver was added.
- **Root cause:** void helper with unchecked clock enables; callers
cannot fail.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. It is an explicit error-path fix: check returns,
unwind a half-enabled clock, propagate from probe and resume.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/i2c/busses/i2c-qup.c` — **+24 / −7** (31 lines)
- **Functions:** `qup_i2c_enable_clocks`, `qup_i2c_probe`,
`qup_i2c_pm_resume_runtime`, `qup_i2c_resume`
- **Scope:** single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
1. **Helper:** void, two unchecked `clk_prepare_enable()` → `int`, abort
on first failure, disable core clk if iface enable fails.
2. **Probe (DT path only):** ignore enable → `ret = …; if (ret) goto
fail_dma`. ACPI path still skips this helper.
3. **Runtime resume:** always `return 0` → return the helper’s error.
4. **System resume:** always `pm_request_autosuspend()` after resume →
skip autosuspend request if clocks failed.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Error-path / ignored-return + resource leak.**
- Broken: required clocks can fail; driver still MMIO-resets the QUP
(`writel` to `QUP_SW_RESET` immediately after enable in probe) and
later runs I2C with clocks off; iface-fail leaves core clk enabled.
- Fix: fail probe/resume, unwind partial enable.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct and matches other I2C host drivers. `goto
fail_dma` is the right label: `fail:` would call
`qup_i2c_disable_clocks()` and MMIO/unprepare clocks that were never (or
no longer) enabled. Regression risk is low: a real clock failure now
fails probe/resume instead of continuing on dead hardware.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: Ignored enables introduced in **`10c5a8425968`** (“i2c: qup: New
bus driver…”, Bjorn Andersson, 2014). First contained in **v3.15-rc1**.
`git log -L :qup_i2c_enable_clocks:` shows only that commit and this
fix.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Original driver commit is an ancestor of HEAD.
**Step 3.3: CHECK FILE HISTORY**
Record: Recent related work is unrelated (`pm_runtime_mark_last_busy`,
timeout loop, interconnect vote). Older related fix **`3cf357dfb40b`**
already routed some probe errors to `fail` so clocks get released — this
patch fills the missing enable-check. Standalone, not `X/Y`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Pengpeng Hou has only this commit under `drivers/i2c/`. Reviewer
is a Qualcomm platform maintainer; committer is the I2C maintainer.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: No new APIs or structs. Applies standalone on this tree. No
follow-ups on `i2c-qup.c` after `a477626332800`.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig:**
https://patch.msgid.link/20260624055237.29977-1-pengpeng@iscas.ac.cn
- **Revisions:** v1 only (no v2/v3)
- **Review:** Konrad Dybcio `Reviewed-by` the same day; Andi Shyti
merged to `i2c/i2c` (~2026-07-28). No NAK, no stable nomination in-
thread.
- lore.kernel.org fetch returned 403; thread confirmed via gnuweeb,
patchew, and openwall mirrors.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To Andi Shyti; Cc linux-arm-msm, linux-i2c, linux-
kernel. Konrad was not in the original To/Cc but reviewed from linux-
arm-msm.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot/user report. Issue is from code review of
ignored returns.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Single standalone patch, not a series.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No discussion of this subject on stable@ found
(lore.kernel.org/stable 403; web search did not hit this patch).
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `qup_i2c_enable_clocks`, `qup_i2c_probe`,
`qup_i2c_pm_resume_runtime`, `qup_i2c_resume`. (semcode MCP not
available.)
**Step 5.2: TRACE CALLERS**
Record: Only three call sites in this file:
- `qup_i2c_probe` (DT/clk path, boot / module load)
- `qup_i2c_pm_resume_runtime` (runtime PM; also used as `RUNTIME_PM_OPS`
resume)
- `qup_i2c_resume` → that runtime helper (system sleep)
Not interrupt context. Reachable on every QUP I2C device probe and every
resume.
**Step 5.3: TRACE CALLEES**
Record: `clk_prepare_enable` / `clk_disable_unprepare` only. Probe then
`clk_get_rate` and `writel(QUP_SW_RESET)`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Platform probe / PM resume. Userspace does not call this
directly, but every Qualcomm QUP I2C bus (touch, sensors, PMICs, cameras
on many phones and boards) goes through it. Unclocked MMIO after a
failed enable is a hang path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Most I2C hosts already check `clk_prepare_enable`
(`i2c-designware-common.c`, `i2c-exynos5.c`, `i2c-img-scb.c`, etc.). A
few still ignore it (`i2c-mv64xxx.c`, `i2c-hix5hd2.c`). This brings QUP
in line with the common pattern.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Tree is **v7.3-rc4** (`7.3.0-rc4`, `f0100363d8c37`).
Introducer `10c5a8425968` and fix `a477626332800` are both ancestors of
HEAD. Pre-fix helper in the parent of the fix is still the 2014 void
ignore-return version. Driver: `drivers/i2c/busses/i2c-qup.c`.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply on this tree (same file, same functions). No extra
prerequisites.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No alternate fix for ignored enable. `3cf357dfb40b` only fixes a
later probe unwind, not enable checking. No post-fix regressions on this
file.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: **I2C host driver** (`drivers/i2c/busses/i2c-qup.c`),
`CONFIG_I2C_QUP` (`ARCH_QCOM || COMPILE_TEST`). **IMPORTANT** for
Qualcomm platforms (common on phones, boards, IoT); not core mm/VFS.
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Mature driver (2014), still getting occasional correctness
fixes. Not a new subsystem.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: Qualcomm SoC users with QUP I2C (`qcom,i2c-qup-v1.1.1` /
`v2.1.1` / `v2.2.1`). Driver- and config-specific, but a large device
population.
**Step 8.2: TRIGGER CONDITIONS**
Record: `clk_prepare_enable()` failure on core or iface (probe, runtime
resume, or system resume). Unprivileged users cannot poke the helper,
but resume is a normal path. Failures are uncommon on healthy clocks;
they do happen with power-domain / RPM / -ENOMEM issues. No public
reproducer.
**Step 8.3: FAILURE MODE SEVERITY**
Record: Continuing after a failed enable then `writel`/`readl` on the
QUP can hang the interconnect; resume success with clocks off breaks
later transfers; iface-fail leaks a prepared core clk. **HIGH** when it
triggers (hang / stuck I2C), **MEDIUM** overall because triggers are
rare. Not a demonstrated CVE.
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit:** avoid unclocked MMIO and false-success resume on QUP I2C.
- **Risk:** very low (~24 insertions, error paths only, standard clk
unwind).
- **Ratio:** favorable.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: EVIDENCE**
**For:**
- Real ignored-error bug on required clocks.
- Probe immediately MMIO-resets the block; clocks-off access can hang.
- Resume used to report success with clocks still off.
- Partial enable leaked the core clock.
- 24 insertions in one file; obviously correct; no new API.
- Reviewed by Konrad Dybcio, merged by Andi Shyti.
- Bug present since v3.15; no extra dependencies.
- Matches the usual I2C host-driver pattern.
**Against:**
- No user/syzbot report in ~12 years.
- Clock enable rarely fails on working hardware.
- No in-thread `Cc: stable`.
**Unresolved:** Direct lore.kernel.org/stable search 403; no evidence
this was rejected for stable.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — standard clk check/unwind;
maintainer review/merge. No extra Tested-by.
2. Fixes a real bug that affects users? **PASS** — ignored required-
clock failure on probe/resume.
3. Important issue? **PASS** — hang / dead I2C / clock leak on that
path, not a style cleanup.
4. Small and contained? **PASS** — +24/−7, one file.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — driver and call sites match.
**Step 9.3: EXCEPTION CATEGORIES**
Record: None (not a device ID, quirk, DT, build, or doc fix). Qualifies
as a normal error-path bugfix.
**Step 9.4: DECISION**
This is a small, correct fix for ignored required-clock errors. On this
v7.3-rc4 tree the buggy helper and the QUP probe/resume paths are
present; the change prevents probe/resume from continuing into unclocked
MMIO. That is enough for stable, even without a field report.
---
### What it solves for this tree
`qup_i2c_enable_clocks()` used to ignore `clk_prepare_enable()`. Probe
still registered the adapter and then `writel`’d `QUP_SW_RESET`; resume
returned 0. If enable actually failed, that is unclocked MMIO (possible
SoC hang) plus a clock leak when only the iface clock failed. The patch
fails those paths and unwinds.
### Stable rules / risk
Meets the rules: real bug, small, no features, applies here. Benefit is
avoiding hangs and false-success PM on Qualcomm QUP I2C; risk is low.
### Concerns
No `Fixes:` / user report (not a reason to reject). `fail_dma` on enable
failure is correct. No follow-up fix found.
---
### Verification
- **[Phase 1]** Tags: Reviewed-by Konrad Dybcio; SOB Andi Shyti; Link
lore msgid `20260624055237.29977-1`; no Fixes/Reported-by/Cc:stable.
- **[Phase 2]** Diff: +24/−7 in `i2c-qup.c`; helper becomes `int`;
probe/resume propagate; partial unwind on iface fail.
- **[Phase 2]** Pre-fix parent: void helper, probe
`qup_i2c_enable_clocks(qup)` then `writel(QUP_SW_RESET)`; resume
always 0.
- **[Phase 2]** Post-fix probe uses `goto fail_dma` (not `fail`), so
`qup_i2c_disable_clocks()` is not run on a failed enable.
- **[Phase 3]** `git log -L :qup_i2c_enable_clocks:` → `10c5a8425968`
(v3.15-rc1) then `a477626332800`.
- **[Phase 3]** `git merge-base --is-ancestor` both SHAs vs HEAD: both
in this tree.
- **[Phase 3]** Author: only this I2C commit; no later commits on this
file after the fix.
- **[Phase 4]** `b4 dig -c a477626332800`: matched msgid; `-a`: v1 only;
`-w`: Andi + linux-i2c/arm-msm.
- **[Phase 4]** Review: Konrad Reviewed-by; Andi “merged to i2c/i2c”; no
NAK.
- **[Phase 4]** lore.kernel.org 403; gnuweeb/patchew/openwall used
instead. Stable-list search: no hits for this subject.
- **[Phase 5]** Callers: probe, runtime resume, system resume only.
Other I2C hosts already check `clk_prepare_enable`.
- **[Phase 6]** `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`;
`make kernelversion` → `7.3.0-rc4`. Buggy code existed; driver
present.
- **[Phase 7]** `CONFIG_I2C_QUP` depends on `ARCH_QCOM`; I2C maintainer
Andi Shyti.
- **[Phase 8]** Failure mode: unclocked MMIO / false resume success;
severity HIGH if triggered, uncommon trigger.
- **UNVERIFIED:** Could not fetch lore.kernel.org HTML directly (403).
Thread content verified via b4 + mirrors.
**YES**
drivers/i2c/busses/i2c-qup.c | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index a0e076fc5f363..ee7915ee2ba2f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1657,10 +1657,21 @@ static const struct i2c_adapter_quirks qup_i2c_quirks_v2 = {
.flags = I2C_AQ_NO_ZERO_LEN,
};
-static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
+static int qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
{
- clk_prepare_enable(qup->clk);
- clk_prepare_enable(qup->pclk);
+ int ret;
+
+ ret = clk_prepare_enable(qup->clk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(qup->pclk);
+ if (ret) {
+ clk_disable_unprepare(qup->clk);
+ return ret;
+ }
+
+ return 0;
}
static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
@@ -1823,7 +1834,9 @@ static int qup_i2c_probe(struct platform_device *pdev)
ret = PTR_ERR(qup->pclk);
goto fail_dma;
}
- qup_i2c_enable_clocks(qup);
+ ret = qup_i2c_enable_clocks(qup);
+ if (ret)
+ goto fail_dma;
src_clk_freq = clk_get_rate(qup->clk);
}
qup->src_clk_freq = src_clk_freq;
@@ -1975,8 +1988,7 @@ static int qup_i2c_pm_resume_runtime(struct device *device)
struct qup_i2c_dev *qup = dev_get_drvdata(device);
dev_dbg(device, "pm_runtime: resuming...\n");
- qup_i2c_enable_clocks(qup);
- return 0;
+ return qup_i2c_enable_clocks(qup);
}
static int qup_i2c_suspend(struct device *device)
@@ -1988,7 +2000,12 @@ static int qup_i2c_suspend(struct device *device)
static int qup_i2c_resume(struct device *device)
{
- qup_i2c_pm_resume_runtime(device);
+ int ret;
+
+ ret = qup_i2c_pm_resume_runtime(device);
+ if (ret)
+ return ret;
+
pm_request_autosuspend(device);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] sched_ext/scx_flatcg: expire cached hweights on weight changes
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (21 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] i2c: qup: Propagate clock enable failures Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] usb_string_copy: Use kzalloc() to avoid leaking old data Sasha Levin
` (493 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable; +Cc: Tao Cui, Tejun Heo, Sasha Levin, sched-ext, linux-kernel
From: Tao Cui <cuitao@kylinos.cn>
[ Upstream commit 94c20e1fb334c2082b443c4470a86ad982f67282 ]
fcg_cgroup_set_weight() updates cgc->weight and the parent's
child_weight_sum but doesn't bump hweight_gen, so the hweights cached by
cgrp_refresh_hweight() stay stale until some task activation bumps the
generation. For cgroups whose tasks never go through a 0->n runnable
transition (e.g. persistently busy ones), a cpu.weight change never
propagates to scheduling at all.
Bump hweight_gen on weight changes so the next refresh recomputes with
the new weight.
Verified on a flatcg VM: a live cpu.weight 100->800 change on a busy
cgroup leaves HWT update at 0 and the distribution unchanged; with it,
hweight_gen increments and the refresh recomputes.
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: the buggy path is in this 6.12 tree, the patch
is a three-line cache-invalidation fix, and it applies here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [sched_ext/scx_flatcg] [expire] [invalidate cached hierarchical
weights when cpu.weight changes]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Tao Cui <cuitao@kylinos.cn> (author)
- Signed-off-by: Tejun Heo <tj@kernel.org> (sched_ext maintainer;
applied the patch)
- No Fixes: tag on the committed version (expected for this review
pipeline)
- No Reported-by, Tested-by, Reviewed-by, Acked-by, Link, or Cc: stable
- BPF CI bot later suggested Fixes: a4103eacc2ab4 ("sched_ext: Add a
cgroup scheduler which uses flattened hierarchy")
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: `fcg_cgroup_set_weight()` writes `cgc->weight` and the parent's
`child_weight_sum` but does not bump `hweight_gen`. Cached hweights in
`cgrp_refresh_hweight()` stay valid until some task activation changes
the active set.
- Symptom: for cgroups that never go through a 0→n runnable transition
(persistently busy ones), a live `cpu.weight` write never affects
scheduling.
- Author verification: on a flatcg VM, `cpu.weight` 100→800 on a busy
cgroup left HWT updates at 0 and the distribution unchanged; with the
bump, `hweight_gen` increments and refresh recomputes.
- Root cause: generation counter used as a cache key is not invalidated
on the weight-change path, even though the file comment says it "gets
inc'd on weight tree changes".
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not hidden. This is an explicit correctness fix: a control knob
is updated but the derived cached state is not expired.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `tools/sched_ext/scx_flatcg.bpf.c` (+3 / -0)
- Function: `fcg_cgroup_set_weight()`
- Scope: single-file surgical fix (blank line, comment, one atomic
increment)
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: lock; if the cgroup is active, adjust parent
`child_weight_sum`; store new `cgc->weight`; unlock; return. Cached
`cgc->hweight` is left tagged with the old `hweight_gen`.
- After: same updates, then `__sync_fetch_and_add(&hweight_gen, 1)` so
the next `cgrp_refresh_hweight()` (called from
`try_pick_next_cgroup()` / dispatch) misses the cache and recomputes
`hweight` from the new weight.
- Path affected: cgroup `cpu.weight` write while scx_flatcg is loaded.
Normal (not error) path.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: logic / correctness (stale cache)
- Mechanism: `cgrp_refresh_hweight()` returns early when
`cgc->hweight_gen == hweight_gen`. `hweight_gen` is only bumped in
`update_active_weight_sums()` when a cgroup's active membership
actually changes. A weight write on an already-active cgroup never
does that, so dispatch keeps charging with the old hierarchical share.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: it reuses the exact invalidation already used on
the active-set path (`__sync_fetch_and_add(&hweight_gen, 1)` at the
existing line 504).
- Minimal; no unrelated edits.
- Regression risk is very low: extra generation bumps only force more
hweight refreshes, which the code already treats as the slow-but-
correct path. No new locks, no API change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: The whole of `fcg_cgroup_set_weight()`,
`cgrp_refresh_hweight()`, `hweight_gen`, and the existing bump in
`update_active_weight_sums()` come from a4103eacc2ab4 (Tejun Heo,
2024-09-04), first contained in v6.12-rc1. The bug is as old as the
example scheduler itself.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag on the commit. The introducing commit is
a4103eacc2ab4, which is an ancestor of this tree (`git merge-base --is-
ancestor` exit 0). No later in-tree commit already expires hweights on
set_weight.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record (this tree, `tools/sched_ext/scx_flatcg.bpf.c`):
- 65e72372d5282 sched_ext/scx_flatcg: Fix cvtime true-up on slice expiry
(already here; same author/thread)
- ab3d9439475a2 sched_ext/scx_flatcg: Fix cvtime_delta race and add
hweight scaling to bypass charging
- c9c809f4137c3 scx_flatcg: Use a user DSQ for fallback instead of
SCX_DSQ_GLOBAL
- a4103eacc2ab4 original addition
Standalone: one-line generation bump. Not patch N/M. The related cvtime
true-up was discovered in the same mailing-list thread but is already in
this tree.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Tao Cui has two origin/master commits on this file (this one and
the cvtime true-up). Tejun Heo is the sched_ext maintainer and applied
both. This tree already contains the cvtime true-up (65e72372d5282).
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None. `hweight_gen`, `__sync_fetch_and_add`, and
`fcg_cgroup_set_weight()` all exist unchanged in this checkout. `git
apply --check` of 94c20e1fb334c succeeded (hunk offset 1 line from the
already-backported cvtime fix).
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 94c20e1fb334c`:
https://patch.msgid.link/20260814144116.2767304-1-cui.tao@linux.dev
- `b4 dig -a`: single v1 series; no later unapplied revision
- lore.kernel.org fetches returned 403; discussion recovered from
patchew and openwall mirrors
- Tejun Heo: "Applied to sched_ext/for-7.3." No NAK
- BPF CI bot: "This looks like a bug fix. Should this include a Fixes:
tag..." suggesting a4103eacc2ab4
- No reviewer asked to keep it out of stable; no Cc: stable either
(expected)
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc included tj@kernel.org, void@manifault.com,
arighi@nvidia.com, changwoo@igalia.com, sched-ext@lists.linux.dev,
linux-kernel@vger.kernel.org, bpf@vger.kernel.org. Maintainer Tejun
applied it.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Author follow-up: VM with A(100)→A1/A2(100)
and D(varying weight), 3 busy tasks per leaf, 4 vCPUs. D=200 ≈ 47% CPU,
D=800 ≈ 46% — weight changes did nothing. That is how the missing
`hweight_gen` bump was found.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone v1. Same thread spawned the cvtime true-up fix
(already in this tree as 65e72372d5282). Tejun noted that even after
this cache fix, runnable-task limits still cap shares; that is a
documented example-scheduler limitation, not a dependency of this patch.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search returned 403. Local `git log
--grep='expire cached hweights'` on this file is empty — not already in
this tree. No local evidence of a prior rejection.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `fcg_cgroup_set_weight()` (modified). Related:
`cgrp_refresh_hweight()`, `update_active_weight_sums()`,
`try_pick_next_cgroup()`.
Step 5.2: TRACE CALLERS
Record:
- `fcg_cgroup_set_weight` is registered as `.cgroup_set_weight` in the
BPF struct_ops (line 959).
- Kernel calls it from `scx_group_set_weight()` in `kernel/sched/ext.c`
when `cpu.weight` / `cpu.weight.nice` changes and scx_flatcg is loaded
(`SCX_CALL_OP(..., cgroup_set_weight, ...)`).
- Reachable from a privileged cgroupfs write, not from an unprivileged
syscall.
Step 5.3: TRACE CALLEES
Record: `find_cgrp_ctx`, `find_ancestor_cgrp_ctx`,
`bpf_spin_lock/unlock(&cgv_tree_lock)`, and after the patch
`__sync_fetch_and_add(&hweight_gen, 1)`. No allocation.
Step 5.4: FOLLOW THE CALL CHAIN
Record: userspace writes `cpu.weight` → `cpu_weight_write_u64` →
`scx_group_set_weight` → BPF `fcg_cgroup_set_weight`. Dispatch later
calls `try_pick_next_cgroup()` → `cgrp_refresh_hweight()`. If
`hweight_gen` was not bumped, that refresh hits `FCG_STAT_HWT_CACHE` and
keeps the old share. Users who load scx_flatcg and change cgroup weights
can trigger this; busy cgroups are the common case where weights matter.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: The only other `hweight_gen` bump is in
`update_active_weight_sums()` when `nr_active` crosses 0. That is the
missing counterpart this patch adds on the weight-write path. No other
copy of the same omission in this file.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Local tree is pending-6.12, `make kernelversion` =
6.12.111, `git describe HEAD` = p-6.12-3-gc504cf0baa3d8.
`fcg_cgroup_set_weight()` at lines 590–609 has the weight update and no
`hweight_gen` bump. Introduced by a4103eacc2ab4 (in this tree).
94c20e1fb334c is not an ancestor (`merge-base --is-ancestor` exit 1).
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. `git show 94c20e1fb334c | git apply --check`
succeeded with hunk offset 1 (from the already-present cvtime true-up).
No refactor of this function here.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No alternate hweight-expiry fix. Related accounting fixes
(cvtime true-up, cvtime_delta race) are present and independent.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: tools/sched_ext example BPF scheduler (scx_flatcg), used only
when `CONFIG_SCHED_CLASS_EXT` is enabled and this program is loaded.
Criticality: PERIPHERAL relative to core CFS, but IMPORTANT for anyone
actually running this shipped scheduler — its whole job is hierarchical
weight control. Not staging.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: sched_ext was new in 6.12; this file has a handful of later
correctness backports in this tree. Mature enough that the bug is
original, not from post-branch churn.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Config- and userspace-specific: `CONFIG_SCHED_CLASS_EXT=y` plus
loading `scx_flatcg`. Not universal. This tree already ships that
example and has been taking its correctness fixes.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Write `cpu.weight` on a cgroup whose tasks stay runnable. Common
for exactly the workload the scheduler is meant to manage (competing
busy cgroups). Requires privilege to write the cgroup knob. Not a race;
it fails every time until some sibling goes idle.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Failure mode = live cgroup CPU shares do not follow `cpu.weight`
for busy groups (author: 100→800 left HWT updates at 0). No oops,
deadlock, or corruption. Severity: MEDIUM–HIGH functional/fairness bug
for that scheduler; LOW for the rest of the kernel.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: makes the primary fairness knob work for persistently busy
cgroups on a scheduler this tree already ships and already patches.
- Risk: very low (3 lines, existing atomic, no lock/API change).
- Ratio: strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real, reproduced bug: busy-cgroup `cpu.weight` changes never reach
scheduling.
- Matches the file's own cache-invalidation design; the set_weight path
simply omitted the bump.
- 3-line, obviously correct, same primitive as the existing active-set
path.
- Bug present since v6.12-rc1 in this tree; patch not yet here; applies
cleanly.
- Maintainer applied it; author and maintainer both tested.
- Companion scx_flatcg correctness fixes are already in this 6.12 tree.
AGAINST:
- Example BPF scheduler in `tools/`, not CFS/core.
- No crash, UAF, deadlock, or CVE.
- Optional config; production SCX users often load schedulers from the
out-of-tree scx repo.
- Residual share compression from window granting remains even after
this fix (separate example-scheduler limit).
UNRESOLVED:
- lore.kernel.org and lore stable search returned 403; discussion taken
from patchew/openwall. No evidence of a stable NAK.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — same generation bump as the
other path; author + maintainer verified on a VM.
2. Fixes a real bug that affects users? PASS — `cpu.weight` ignored for
busy cgroups; measured.
3. Important issue? PASS — fairness/control-knob failure of this
scheduler (not a panic, but the feature is broken in the case that
matters).
4. Small and contained? PASS — +3 lines, one function.
5. No new features or APIs? PASS.
6. Can apply to the local tree? PASS — `--check` succeeded.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID, quirk, DT, build, or docs fix). Qualifies
as a normal small correctness fix.
Step 9.4: MAKE YOUR DECISION
This tree is 6.12.y. The buggy example scheduler is here, the one-line
invalidation is the intended cache protocol, and the only cost is extra
hweight refreshes. That is a YES for this checkout.
What the commit solves for stable users:
Anyone on this 6.12 tree who loads the shipped `scx_flatcg` scheduler
currently cannot change CPU shares of persistently busy cgroups through
`cpu.weight`. That is the main knob the scheduler advertises. The patch
expires the hweight cache so the next dispatch refresh uses the new
weights.
Risk vs benefit:
Benefit is restoring advertised cgroup fairness for that scheduler; risk
is a generation bump that already exists on another path. No
prerequisites beyond code already in this tree.
Verification:
- [Phase 1] Parsed subject/body/tags from `git log origin/master` / `git
show 94c20e1fb334c`; no Fixes:/Reported-by; Tejun SOB
- [Phase 2] Diff is +3 lines in `fcg_cgroup_set_weight()`; local
function at lines 590–609 lacks the bump
- [Phase 2] Confirmed `cgrp_refresh_hweight()` cache test at lines
206–208 and existing bump at 503–504
- [Phase 3] `git blame -L 590,609`: a4103eacc2ab4; `git describe
--contains a4103eacc2ab4` = v6.12-rc1~111^2~20
- [Phase 3] `git merge-base --is-ancestor a4103eacc2ab4 HEAD` → 0 (bug
in this tree)
- [Phase 3] `git merge-base --is-ancestor 94c20e1fb334c HEAD` → 1 (fix
not in this tree)
- [Phase 3] `git apply --check` of 94c20e1fb334c succeeded (offset 1)
- [Phase 3] Author history on path: this commit + cvtime true-up
(already 65e72372d5282 here)
- [Phase 4] `b4 dig -c 94c20e1fb334c`: msgid
20260814144116.2767304-1-cui.tao@linux.dev; v1 only
- [Phase 4] `b4 dig -w`: Tejun and sched-ext/bpf lists on CC
- [Phase 4] patchew: Tejun applied to sched_ext/for-7.3; BPF CI asked
for Fixes: a4103eacc2ab4
- [Phase 4] Author measurements: D=200 ~47% vs D=800 ~46% before the
bump
- [Phase 4] lore.kernel.org 403 — UNVERIFIED on lore itself; recovered
from patchew/openwall
- [Phase 5] Call path: `scx_group_set_weight()` in
kernel/sched/ext.c:4113 → BPF `cgroup_set_weight`; refresh from
`try_pick_next_cgroup()` line 677
- [Phase 6] `git describe HEAD` = p-6.12-3-gc504cf0baa3d8; `make
kernelversion` = 6.12.111
- [Phase 7] README: scx_flatcg is the flattened hierarchical weight
example
- [Phase 8] Failure: stale hweights → cpu.weight ignored for busy
cgroups; severity MEDIUM–HIGH for that scheduler
- UNVERIFIED: whether this SHA was discussed on lore.kernel.org/stable
(HTTP 403)
**YES**
tools/sched_ext/scx_flatcg.bpf.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/sched_ext/scx_flatcg.bpf.c b/tools/sched_ext/scx_flatcg.bpf.c
index d1fc6cb8206c0..3f01441731b7e 100644
--- a/tools/sched_ext/scx_flatcg.bpf.c
+++ b/tools/sched_ext/scx_flatcg.bpf.c
@@ -605,6 +605,9 @@ void BPF_STRUCT_OPS(fcg_cgroup_set_weight, struct cgroup *cgrp, u32 weight)
pcgc->child_weight_sum += (s64)weight - cgc->weight;
cgc->weight = weight;
bpf_spin_unlock(&cgv_tree_lock);
+
+ /* expire cached hweights so the new weight propagates */
+ __sync_fetch_and_add(&hweight_gen, 1);
}
static bool try_pick_next_cgroup(u64 *cgidp)
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] usb_string_copy: Use kzalloc() to avoid leaking old data
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (22 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] sched_ext/scx_flatcg: expire cached hweights on weight changes Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:02 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/panel-edp: Add BOE NE140QDM-NX2 Sasha Levin
` (492 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: David Laight, Greg Kroah-Hartman, Sasha Levin, linux-usb,
linux-kernel
From: David Laight <david.laight.linux@gmail.com>
[ Upstream commit 057df423bf4747091cf942af57307627e941e1fb ]
If the string is read while being updated (which is why the copy is done
in place) and the new string is longer than the old one, then the reader
can read memory that isnt part of either string.
Use memcpy() to copy the known length string instead of strcpy.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
Link: https://patch.msgid.link/20260608095523.2606-37-david.laight.linux@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable backport analysis: `usb_string_copy: Use kzalloc() to avoid
leaking old data`
Local tree: **v7.3-rc4** (`7.3.0-rc4`, HEAD `f0100363d8c37`). The commit
under review is `057df423bf474`. The buggy `kmalloc` + in-place `strcpy`
path has been in this lineage since **v5.12** (`98f153a10da403`).
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Subsystem: USB gadget configfs (`usb_string_copy` in
`drivers/usb/gadget/configfs.c`)
- Action verb: **Use** (kzalloc) / implied **avoid leaking**
- Claimed intent: stop readers from observing memory that is not part of
either the old or new string when an in-place update lengthens the
buffer
Record: `[usb/gadget/configfs] [use/avoid] [zero the string buffer and
copy a known length to prevent leaking heap bytes during in-place
updates]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- `Signed-off-by: David Laight <david.laight.linux@gmail.com>` (author)
- `Link: https://patch.msgid.link/20260608095523.2606-37-
david.laight.linux@gmail.com`
- `Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>` (USB
maintainer applied it)
- No `Fixes:`, no `Reported-by:`, no `Tested-by:`, no `Reviewed-by:`, no
`Acked-by:`, no `Cc: stable` (absence is expected)
- Message-Id `2606-37` = patch 37 of a large series
Record: Author SOB + Greg SOB + lore Link. No reporters. Hardening/USB
lists were the original audience (confirmed in Phase 4).
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
The body describes a concurrent-read hole in the in-place update path:
if a reader walks the buffer while a longer string is being copied, it
can pass the old NUL and consume bytes that belong to neither string. It
also switches `strcpy` to `memcpy` of the already-computed length.
Record:
- Bug: kernel heap contents can be observed by a concurrent reader of a
gadget string during an in-place lengthening update
- Symptom: leaked uninitialized `kmalloc` bytes (via configfs show or
USB string descriptors)
- Version info: none in the message
- Root cause: first allocation used `kmalloc` (unzeroed tail); in-place
`strcpy` of a longer string temporarily removes the old NUL before the
new one is written
**Step 1.4: DETECT HIDDEN BUG FIXES**
This is not disguised cleanup. The subject states the leak. It *is* one
patch in a treewide `strcpy` sweep, and `memcpy` is that sweep;
`kzalloc` is the actual leak fix.
Record: `[Not hidden. Real infoleak fix, bundled with strcpy-
elimination.]`
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- File: `drivers/usb/gadget/configfs.c` (+2 / −2)
- Function: `usb_string_copy()`
- Scope: single-file, two-line surgical change
Record: `[configfs.c +2/-2] [usb_string_copy] [single-file surgical]`
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Before:
- First call: `kmalloc(USB_MAX_STRING_WITH_NULL_LEN)` then `strcpy`
- Later calls: reuse the same buffer (`str = copy`) and `strcpy` over it
(the 2021 UAF workaround)
After:
- First call: `kzalloc` so the unused tail is zeros
- Copy: `memcpy(str, s, ret + 1)` (`ret` is `strlen(s)`, so this
includes the NUL)
Affected path: configfs store of
manufacturer/product/serial/configuration strings (`GS_STRINGS_W`).
Record: `[kmalloc+strcpy -> kzalloc+memcpy of known length; first-alloc
and in-place update paths]`
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Category: **uninitialized data / kernel infoleak** (with a concurrent-
read window created by in-place update).
Mechanism, verified in this tree:
1. `98f153a10da403` (v5.12) stopped `kfree`+`kstrdup` and copies in
place so USB host pointers stay valid.
2. First fill still used `kmalloc`, so bytes after the first NUL are
heap residue.
3. Bind aliases those buffers into USB string tables:
- `stringtab[...].s = language->manufacturer/product/serialnumber`
(`configfs_attach_gadget_strings`)
- `cn->strings.s = cn->configuration` (`configfs_composite_bind`)
4. `usb_gadget_get_string()` does `strlen(s->s)` then converts to
UTF-16.
5. Configfs show is `sprintf(page, "%s\n", gs->__name ?: "")`.
6. `GS_STRINGS_W` calls `usb_string_copy()` with **no** `gi->lock`. Host
`GET_DESCRIPTOR` is not serialized against that store.
7. If a reader is in `strlen`/`sprintf` while `strcpy` lengthens the
string, the old NUL is overwritten first; the walk continues into the
unzeroed tail.
`kzalloc` makes that tail zeros, so a torn read stops instead of leaking
heap. `memcpy` is equivalent to `strcpy` here (`ret` already came from
`strlen`).
Record: `[uninitialized kmalloc tail leaked across a designed
concurrent-read window] [kzalloc zeros the tail; memcpy is strcpy
replacement]`
**Step 2.4: ASSESS THE FIX QUALITY**
Obviously correct. `USB_MAX_STRING_LEN` is 126, so max `ret+1` is 127,
matching `USB_MAX_STRING_WITH_NULL_LEN`. `kzalloc` is strictly safer
than `kmalloc`. `memcpy` of `strlen+1` matches `strcpy` for a C string.
Regression risk: very low. Remaining torn-string reads of *previous
string contents* are the pre-existing in-place design, not introduced
here.
Record: `[minimal, correct] [regression risk very low]`
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Function added: `88af8bbe4ef781` (2012, “the start of the configfs
interface”) — originally `kstrdup` + `kfree(old)`
- In-place `kmalloc` + `strcpy`: `98f153a10da403` (2021-03-17, in v5.12)
— **this is the buggy code**
- Empty-string guard: `6d3c721e686ea` (2024, `Cc: stable`)
- This fix: `057df423bf474` (2026-06-08)
Record: `[98f153a10da403, v5.12] [bug present for years in this
lineage]`
**Step 3.2: FOLLOW THE FIXES: TAG**
No `Fixes:` tag. The semantic Fixes target is `98f153a10da403`, which
**is** in this tree (`git merge-base --is-ancestor` succeeded). That
commit was itself `Cc: stable` and exists because USB host string reads
race with configfs stores.
Record: `[No Fixes tag] [real introducer 98f153a is in this tree since
v5.12]`
**Step 3.3: CHECK FILE HISTORY**
Recent related commits on this file: OOB empty-string fixes
(`6d3c721e686ea`, `3014168731b79`), later `f63edb54d8f73` (qw_sign,
unrelated). No prerequisite refactor is required for these two lines.
`kmalloc_obj` treewide conversion did **not** change this `kmalloc`
call; the pre-image is still `kmalloc(...)`.
Record: `[standalone vs file history] [no blocking prerequisites in this
tree]`
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
David Laight is not the USB gadget maintainer. Around this commit he
posted ~100 compile-tested `strcpy` replacements to linux-hardening /
subsystem lists. Greg applied this one. Sibling leak-style changes exist
(e.g. TIPC pad bytes).
Record: `[regular contributor, hardening series] [Greg applied; not a
maintainer-authored USB patch]`
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Needs the in-place buffer (`98f153a`) to be meaningful; that is in this
tree. Does not need `6d3c721e` (empty-string check) for correctness;
that only appears as nearby context. Applies standalone.
Record: `[standalone on any tree that has the 2021 in-place copy] [can
apply standalone here]`
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
`b4 dig -c 057df423bf474` matched:
https://patch.msgid.link/20260608095523.2606-37-
david.laight.linux@gmail.com
`b4 dig -a`: only **v1**, dated 2026-06-08, subject `[PATCH next]`.
Saved mbox: patch only, **no replies**. Trailer notes:
- one of a group removing unbounded `strcpy()`
- **“all the changes are only compile tested”**
- ~100 patches sent individually
- “Apologies for the terse commit messages”
WebFetch to lore.kernel.org returned **403**. Discussion content was
recovered via `b4 dig -m`.
Record: `[lore msgid 20260608095523.2606-37] [v1 only, no review
comments in thread] [no reviewer Cc: stable] [compile-tested series]`
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
`b4 dig -w` original recipients: Kees Cook, linux-hardening, linux-
kernel, linux-usb, Arnd Bergmann, Greg Kroah-Hartman. Greg’s merge SOB
is the only review signal in git. No `Reviewed-by`/`Acked-by` on the
commit.
Record: `[USB + hardening lists and Greg CC’d; Greg applied; no written
review in the thread]`
**Step 4.3: SEARCH FOR THE BUG REPORT**
No `Reported-by`, no syzbot, no bugzilla. The race is inferred from code
and from `98f153a`’s real KASAN UAF on the same overlapping access.
Record: `[no external bug report] [concurrent access is documented by
the 2021 UAF fix, not by a new user report]`
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Patch 37 of a ~100-patch `strcpy` series aimed at linux-next. This
instance is one of the few that also changes allocation to `kzalloc` and
describes a leak. No other series member is required for this function.
Record: `[strcpy series; this patch is self-contained]`
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
lore.kernel.org/stable search via WebFetch and curl returned **403**.
Cannot confirm a stable-list nomination or rejection.
Record: `[UNVERIFIED: stable@ discussion]`
---
## PHASE 5: CODE SEMANTIC ANALYSIS
semcode MCP is not available. Used grep + file reads.
**Step 5.1: KEY FUNCTIONS**
Record: `[usb_string_copy]`
**Step 5.2: CALLERS**
Direct calls only through `GS_STRINGS_W` in
`include/linux/usb/gadget_configfs.h`, instantiated in `configfs.c` as:
- `gadget_language_{manufacturer,product,serialnumber}_store`
- `gadget_config_name_configuration_store`
Those are configfs attribute stores (privileged gadget setup). Host-side
readers are `usb_gadget_get_string()` → `strlen` on the aliased buffers
after bind.
Record: `[configfs stores write; USB GET_STRING and configfs show read
the same buffers]`
**Step 5.3: CALLEES**
`strlen`, `kzalloc`/`kmalloc`, `memcpy`/`strcpy`. No locks, no I/O.
Record: `[string copy + slab alloc only]`
**Step 5.4: CALL CHAIN / REACHABILITY**
Userspace with configfs gadget access: `write(2)` →
`configfs_write_file` → `GS_STRINGS_W` → `usb_string_copy`.
USB host: `GET_DESCRIPTOR` / string request → `composite_setup` →
`usb_gadget_get_string` → `strlen(s->s)`.
Reachable. Typical writers are root (Android/embedded gadgetd). The
**host** is a different trust domain.
Record: `[reachable from configfs writes and from USB host string reads]
[host path is the security-relevant reader]`
**Step 5.5: SIMILAR PATTERNS**
Same file already has other string-safety fixes (`6d3c721e`,
`3014168731b79`). Author’s series has other “don’t leak leftover bytes”
patches. No second copy of this exact helper.
Record: `[isolated helper; same file has prior stable-bound string
bugs]`
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Yes. Pre-image at `057df423bf474^` still has `kmalloc` + `strcpy`.
Introduced v5.12, present through this 7.3-rc4 lineage until this
commit.
Record: `[yes, usb_string_copy in drivers/usb/gadget/configfs.c] [since
v5.12 / 98f153a]`
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Hunk is two lines inside a long-stable helper. Would apply cleanly here
(and would apply to older trees that still have `kmalloc`+`strcpy`;
empty-string check is only nearby context).
Record: `[clean apply]`
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
`6d3c721e` is a different bug (OOB on zero-length write). No other
kzalloc leak fix for this helper.
Record: `[no substitute fix already present before 057df423]`
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
USB gadget configfs (`CONFIG_USB_CONFIGFS`). Used to compose gadgets
from userspace (Android gadgets, gadgetfs-style gadgets, UDC testing).
Not core mm/VFS, but a common embedded/Android path.
Record: `[USB gadget configfs] [IMPORTANT for gadget/Android; PERIPHERAL
for desktops without UDC]`
**Step 7.2: SUBSYSTEM ACTIVITY**
File still receives security-relevant string fixes in 2024–2026. Mature
interface, not staging.
Record: `[mature, still getting bounded-string fixes]`
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Gadget systems that set manufacturer/product/serial/configuration via
configfs and have the gadget bound so a host can read string
descriptors. Config-specific: `CONFIG_USB_CONFIGFS`.
Record: `[driver/config-specific: USB gadget configfs users]`
**Step 8.2: TRIGGER CONDITIONS**
Concurrent in-place store of a **longer** string while
`strlen`/`sprintf` is walking the buffer. Window is a 127-byte copy —
short, but the overlap is intentional (`98f153a` exists because host
reads and configfs writes do overlap in practice). Unprivileged local
users generally cannot write these attributes; a USB host can read the
leaked bytes.
Record: `[short race during string lengthening while gadget is live]
[USB host can observe the leak]`
**Step 8.3: FAILURE MODE SEVERITY**
Kernel heap infoleak (uninitialized `kmalloc` bytes), not a crash. Can
cross to a USB host via string descriptors. That is a security issue,
not a panic.
Record: `[kernel heap infoleak to USB host / configfs reader] [HIGH for
security, not CRITICAL crash]`
**Step 8.4: RISK-BENEFIT RATIO**
- Benefit: closes a real infoleak on a path already known to race; 2
lines; `kzalloc` is the usual stable-grade fix
- Risk: negligible (`kzalloc`/`memcpy` behavior-preserving for this
helper)
Record: `[benefit high for gadget infoleak] [risk very low] [favorable]`
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real uninitialized-kmalloc leak, not style-only
- Concurrent reader is why in-place copy exists (`98f153a`, KASAN UAF,
`Cc: stable`)
- Host `strlen` on aliased pointers is a verified path
- Two-line, obviously correct change
- No new API/feature
- Bug present since v5.12 in this tree’s history
- Applied by Greg KH
AGAINST:
- Tiny race window; no syzbot/CVE/user report
- Series was compile-tested only, labeled `[PATCH next]`
- No mailing-list review comments
- Not a universal core-kernel path
- `memcpy` half is strcpy-hardening, not the leak fix
UNRESOLVED:
- Whether stable@ ever discussed this (lore 403)
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — correctness is local and
obvious; series is compile-tested only, but the change cannot
reasonably be wrong
2. Fixes a real bug that affects users? **PASS** — heap bytes can be
read on a live gadget string update
3. Important issue? **PASS** — kernel infoleak (security), not a
crash/deadlock
4. Small and contained? **PASS** — 2 lines, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — pre-image matches; no missing
helpers
**Step 9.3: EXCEPTION CATEGORIES**
Not a device-ID/quirk/DT/build/docs exception. It is a small
security/correctness fix.
**Step 9.4: DECISION**
This is a contained infoleak fix on a helper whose in-place update
exists specifically so USB hosts can read strings while configfs writes
them. `kzalloc` is the right, low-risk close of that hole. It meets
stable rules for this tree.
---
## What the commit solves for stable users
After the 2021 UAF fix, gadget strings live in a reused `kmalloc`
buffer. A host (or configfs reader) can walk that buffer while a longer
string is copied in place, skip the old NUL, and return leftover heap
data in a USB string descriptor. Zeroing on first allocation stops that
leak. `memcpy` is a safe `strcpy` substitute given the existing
`strlen`.
Risk vs benefit: two lines, no API change, no lock surgery, benefit is
closing a kernel-memory leak on Android/embedded gadget configs.
---
## Verification
- [Phase 1] Parsed tags: author SOB, Greg SOB, lore Link; no
Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: `kmalloc`→`kzalloc`, `strcpy`→`memcpy(str,s,ret+1)` in
`usb_string_copy`
- [Phase 2] Confirmed `USB_MAX_STRING_LEN` 126 and buffer size 127;
`ret+1` cannot overflow
- [Phase 3] `git blame`: in-place `kmalloc` from `98f153a10da403`
(v5.12); function from `88af8bbe4ef781` (2012)
- [Phase 3] `git merge-base --is-ancestor 98f153a10da403 HEAD` —
introducer is in this tree
- [Phase 3] `git merge-base --is-ancestor 057df423bf474 HEAD` — this
commit is already in HEAD (ignored as “already selected”)
- [Phase 3] `git describe HEAD` / Makefile: local tree is **v7.3-rc4 /
7.3.0-rc4**
- [Phase 3] Pre-commit file still has `kmalloc`+`strcpy`
- [Phase 4] `b4 dig -c 057df423bf474`: msgid `20260608095523.2606-37`,
`[PATCH next]`, v1 only
- [Phase 4] `b4 dig -w`: linux-usb, linux-hardening, Kees, Greg, Arnd
- [Phase 4] `b4 dig -m`: no replies; author said compile-tested only;
~100 strcpy patches
- [Phase 4] WebFetch lore.kernel.org: 403; used b4 instead
- [Phase 5] Callers: `GS_STRINGS_W` →
manufacturer/product/serial/configuration stores
- [Phase 5] Host path: `stringtab[].s` and `cn->strings.s` alias the
same buffers; `usb_gadget_get_string` uses `strlen`
- [Phase 5] `GS_STRINGS_W` does not take `gi->lock`
- [Phase 6] No other leak fix for this helper; `6d3c721e` is a different
OOB bug
- [Phase 6] Backport difficulty: clean 2-line apply
- [Phase 8] Failure mode: uninitialized heap infoleak, severity HIGH
(security), not a crash
- UNVERIFIED: stable@ mailing-list discussion (lore 403)
- UNVERIFIED: no runtime reproduction performed here; race is from code
+ the 2021 UAF report, not a new reproducer
**YES**
drivers/usb/gadget/configfs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index aa0a25efb6aa0..b6237a2e02003 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -125,11 +125,11 @@ static int usb_string_copy(const char *s, char **s_copy)
if (copy) {
str = copy;
} else {
- str = kmalloc(USB_MAX_STRING_WITH_NULL_LEN, GFP_KERNEL);
+ str = kzalloc(USB_MAX_STRING_WITH_NULL_LEN, GFP_KERNEL);
if (!str)
return -ENOMEM;
}
- strcpy(str, s);
+ memcpy(str, s, ret + 1);
if (str[ret - 1] == '\n')
str[ret - 1] = '\0';
*s_copy = str;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] drm/panel-edp: Add BOE NE140QDM-NX2
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (23 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] usb_string_copy: Use kzalloc() to avoid leaking old data Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] misc: genwqe: handle a first DMA address of zero Sasha Levin
` (491 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Weiji Wang, Douglas Anderson, Sasha Levin, neil.armstrong,
maarten.lankhorst, mripard, tzimmermann, airlied, simona,
dri-devel, linux-kernel
From: Weiji Wang <nebclllo0444@gmail.com>
[ Upstream commit 354b9c43d36ce9b41e48b2d67c5d9b953a0e9d64 ]
Add timing from datasheet for BOE NE140QDM-NX2.
edid-decode (hex):
00 ff ff ff ff ff ff 00 09 e5 f2 0a 00 00 00 00
20 1f 01 04 a5 1e 13 78 03 ee 96 a3 54 4c 99 26
0f 4e 51 00 00 00 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 60 d2 00 a0 a0 40 32 60 30 20
35 00 2e bd 10 00 00 18 c8 9d 00 a0 a0 40 32 60
30 20 35 00 2e bd 10 00 00 18 00 00 00 fd 00 30
78 c6 c6 36 01 0a 20 20 20 20 20 20 00 00 00 fe
00 4e 45 31 34 30 51 44 4d 2d 4e 58 32 20 01 f8
70 13 79 00 00 03 01 14 30 69 00 05 ff 09 9f 00
2f 00 1f 00 3f 06 31 00 02 00 04 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 4d 90
Signed-off-by: Weiji Wang <nebclllo0444@gmail.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://patch.msgid.link/82fc6395-3425-4f71-ba58-813856cee61d@gmail.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: `[drm/panel-edp] [Add] [one-line BOE NE140QDM-NX2 panel-id /
delay table entry]`
**Step 1.2: Tags**
Record:
- `Signed-off-by: Weiji Wang <nebclllo0444@gmail.com>` (author)
- `Reviewed-by: Douglas Anderson <dianders@chromium.org>` (listed `R:`
for this driver in MAINTAINERS)
- `Signed-off-by: Douglas Anderson <dianders@chromium.org>` (applied via
drm-misc)
- `Link: https://patch.msgid.link/82fc6395-3425-4f71-ba58-
813856cee61d@gmail.com`
- No `Fixes:`, no `Cc: stable`, no `Reported-by`, no `Tested-by` tag
(author later said they verified on `next-20260726` in the v1 thread)
- Ignore pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit ...]`
if present
**Step 1.3: Body**
Record:
- Claimed intent: add datasheet timing for BOE NE140QDM-NX2.
- Failure mode is not a crash dump; it is missing table data for a real
eDP panel identified by EDID.
- Included raw EDID (base + CTA). Manufacturer `09 e5` is BOE; product
`f2 0a` little-endian is `0x0af2`; ASCII descriptor is `NE140QDM-NX2`.
- Root cause: generic `edp-panel` path looks up power-seq delays by
panel ID; this ID was absent.
**Step 1.4: Hidden bug fix?**
Record: Not a disguised UAF/leak. It is hardware-table enablement.
Without the row, `generic_edp_panel_probe()` hits
`WARN_ON(!panel->detected_panel)` and falls back to conservative delays
(2000 ms unprepare / 200 ms enable). That is a real user-visible issue
for this panel (warning + slow suspend/resume), not style cleanup.
---
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/gpu/drm/panel/panel-edp.c` (+1 / −0)
- Function/data: `edp_panels[]` only
- Scope: single-file, one table row
**Step 2.2: Code flow**
Record:
- Before: BOE IDs jump from `0x0ae8` (NV140WUM-N41) to `0x0b09`
(NV140FHM-NZ). `0x0af2` is unknown.
- After: `EDP_PANEL_ENTRY('B', 'O', 'E', 0x0af2,
&delay_200_500_e50_p2e80, "NE140QDM-NX2")`.
- Path: probe of compatible `"edp-panel"` → `generic_edp_panel_probe()`
→ `find_edp_panel()` → copy `*delay` into `desc`. Modes still come
from EDID (`override_edid_mode` is not set).
**Step 2.3: Bug mechanism**
Record: **Hardware ID / quirk table** (device-ID exception). Not a
memory-safety bug. Missing identity causes:
1. `WARN_ON` splat at probe
2. `panel_edp_set_conservative_timings()`: `unprepare=2000`,
`enable=200`, vs datasheet delays `hpd_absent=200`, `unprepare=500`,
`enable=50`, `prepare_to_enable=80`
**Step 2.4: Fix quality**
Record: Obviously correct one-liner using an existing delay blob. Sorted
by product ID. Regression risk is confined to this panel ID; other
panels are untouched. Commit text says “timing” but the row only sets
**power sequencing**; that matches the driver’s design comment “Update
the delay; everything else comes from EDID”.
---
## Phase 3: Git history
**Step 3.1: Blame**
Record:
- New line is commit `354b9c43d36ce` (Weiji Wang, 2026-07-28).
- Neighbors: `0x0ae8` from `993d36ac99efe` (2024), `0x0b09` from
`c03dd019f0b56` (2025).
- `delay_200_500_e50_p2e80` introduced in `f4ccd9fea2270` (2023-12-14),
present long before this change.
- Driver file from `5f04e7ce392db` (2021-09-20).
**Step 3.2: Fixes: tag**
Record: None. Bug is “this panel ID was never listed”, not a regression
from a specific SHA.
**Step 3.3: File history**
Record: Many similar `drm/panel-edp: Add …` one-liners. Standalone; not
`N/M`. Parent `eb7979f6014a1` already has the delay struct and
surrounding BOE rows. `git grep 0x0af2` on the parent: not present.
**Step 3.4: Author**
Record: Only this commit by Weiji Wang in `drivers/gpu/drm/`. Douglas
Anderson is `R: DRM DRIVER FOR GENERIC EDP PANELS` and both reviewed and
applied it.
**Step 3.5: Prerequisites**
Record: Needs `EDP_PANEL_ENTRY`, `edp_panels[]`, and
`delay_200_500_e50_p2e80`. All exist in this checkout. Applies
standalone.
---
## Phase 4: Mailing list
**Step 4.1: Original discussion**
Record:
- `b4 dig -c 354b9c43d36ce` → https://patch.msgid.link/82fc6395-3425-
4f71-ba58-813856cee61d@gmail.com
- v1: 2026-07-24, https://patch.msgid.link/697e79c2-98a9-4bb3-b5fb-
db327cbe1bce@gmail.com
Used unsorted `0x0af2` with `delay_200_500_e80`.
- v2: 2026-07-28 (applied). Changelog: sort fix +
`delay_200_500_e50_p2e80`.
- Doug on v2: mailer wrapped/tabs-to-spaces; he fixed and pushed to drm-
misc-next as `354b9c43d36ce`. `Reviewed-by` given. No NAK.
- v1 review: sort bug; asked if datasheet vs guess. Author: Panelook
datasheet; T4+T5+T6+T8-min given. Doug recommended
`delay_200_500_e50_p2e80`. Author confirmed T7/T8 match and verified
on `next-20260726`.
- No reviewer `Cc: stable`.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: Weiji Wang, Doug Anderson, `dri-devel@lists.freedesktop.org`,
`linux-kernel@vger.kernel.org`. Right reviewer and list.
**Step 4.3: Bug report**
Record: No syzbot/bugzilla. Hardware addition from someone with the
panel/datasheet. EDID in the message is the identification evidence.
**Step 4.4: Series**
Record: Single patch, v1→v2 only.
**Step 4.5: stable@**
Record: lore HTTP fetch returned 403. `b4` threads have no stable
discussion. Not used as a negative signal.
---
## Phase 5: Semantic analysis
**Step 5.1: Functions**
Record: No function body change. Data: `edp_panels[]`. Consumers:
`find_edp_panel()`, `generic_edp_panel_probe()`.
**Step 5.2: Callers**
Record:
- `panel_edp_probe()` if DT compatible is `"edp-panel"`
- `panel_edp_platform_probe()` / AUX-bus probe → `panel_edp_probe()`
- Context: device probe (boot / connector bring-up), not IRQ/hot path
**Step 5.3: Callees**
Record: `find_edp_panel()` walks `edp_panels`; on hit, `desc->delay =
*panel->detected_panel->delay`.
**Step 5.4: Reachability**
Record: Yes, from normal laptop/embedded eDP probe when the panel EDID
is BOE `0x0af2`. Unprivileged users do not program the ID; it is
firmware/EDID. Impact is display power-seq and a kernel warning at
probe.
**Step 5.5: Similar patterns**
Record: The table is full of the same `EDP_PANEL_ENTRY` pattern
(including other BOE NE140QDM parts, e.g. `0x0b1e` NE140QDM-N6A). This
is the standard way this driver is extended.
---
## Phase 6: Local tree (this checkout)
**Step 6.1: Does the code exist here?**
Record:
- Tree: `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion` = `7.3.0-rc4`
- `drivers/gpu/drm/panel/panel-edp.c` present; `CONFIG_DRM_PANEL_EDP` in
Kconfig
- `delay_200_500_e50_p2e80` at lines 1768–1773
- `edp_panels[]` and `WARN_ON` unknown-panel path at 829–833
- Line 2060 already has this entry because `354b9c43d36ce` **is an
ancestor of HEAD**. That is mainline history, not a reason to treat
the change as “already selected for stable”.
**Step 6.2: Backport difficulty**
Record: Clean apply: one sorted row, delay symbol already in this tree.
No API/struct change.
**Step 6.3: Related fixes already here?**
Record: No other `NE140QDM-NX2` / `0x0af2` commit besides this one. No
alternate fix.
---
## Phase 7: Subsystem context
**Step 7.1:**
Record: DRM panel (`drivers/gpu/drm/panel/`). Criticality: **IMPORTANT**
for systems using generic eDP (`edp-panel`), typical
laptops/Chromebooks/ARM boards. Not mm/net core; not staging.
**Step 7.2:**
Record: Active table (many recent `Add` commits). Mature lookup/delay
design since ~2021–2023.
---
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
Record: Driver/config-specific: `CONFIG_DRM_PANEL_EDP` + DT `"edp-
panel"` + BOE product ID `0x0af2`. No effect on other panels.
**Step 8.2: Trigger**
Record: Every probe of that panel (boot / display init). Not a race. Not
a syscall exploit path.
**Step 8.3: Failure mode**
Record:
- `WARN_ON` on unknown panel (MEDIUM as a warning, but intentional
“please add this ID” splat)
- Conservative delays: extra ~1.5 s unprepare vs 500 ms (user-visible
resume/power-off lag)
- Panel is still expected to work; this is enablement + warning/latency,
not panic
- Severity: **MEDIUM** as a bug; **high value** as a device-ID exception
**Step 8.4: Risk-benefit**
Record:
- Benefit: correct power-seq and no warning for this hardware; same
class as PCI/USB ID adds
- Risk: very low (1 line, ID-matched only)
- Ratio: favorable
---
## Phase 9: Synthesis
**Step 9.1: Evidence**
FOR:
- Existing driver; only a new panel ID + existing delay pointer
- Matches the documented **new device ID** / hardware-quirk exception
- Prevents `WARN_ON` + 2000 ms conservative unprepare for BOE NE140QDM-
NX2
- 1 line, sorted, uses `delay_200_500_e50_p2e80` already in this tree
- EDID in the message matches vendor/product/name
- Reviewed and applied by the panel-edp reviewer; v2 delay choice came
from datasheet discussion
- Author verified on `next-20260726`
AGAINST:
- Not a UAF/crash/security fix
- Unknown panel still functions with conservative timings
- No `Fixes:` / `Cc: stable` (expected for this review path)
- Commit subject is enablement (“Add …”), not “fix”
UNRESOLVED:
- lore.kernel.org via WebFetch was 403; thread recovered with `b4`
- No stable@ thread found
- Exact laptop SKUs using this panel not identified beyond the EDID
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** (1-line table add; maintainer
review; author verified)
2. Real bug affecting users? **PASS** (missing ID → warning + wrong
delays on real hardware)
3. Important (crash/security/corruption/deadlock)? **PASS via
exception** (device ID / panel quirk; warning + bad power-seq). Not
CRITICAL memory safety.
4. Small and contained? **PASS** (+1 line, one file)
5. No new features/APIs? **PASS** (no new driver, syscall, or userspace
ABI; ID in existing table)
6. Can apply to this tree? **PASS** (driver, macro, delay struct, and
sort neighbors all present)
**Step 9.3: Exception**
Record: **New device ID / hardware quirk** on an existing driver
(`EDP_PANEL_ENTRY` is this driver’s ID table).
**Step 9.4: Decision**
This is the eDP equivalent of adding a PCI/USB ID: a one-line table
entry so existing `panel-edp` uses datasheet power sequencing instead of
the unknown-panel `WARN_ON` + conservative delays. This tree has every
prerequisite. Benefit is real for owners of this panel; risk is
negligible.
### What the commit solves for this tree
On `v7.3-rc4`, generic `"edp-panel"` devices read EDID and look up
`edp_panels[]`. BOE `0x0af2` (NE140QDM-NX2) had no row, so probe warned
and used 2000/200 ms conservative delays. The patch adds that row with
`delay_200_500_e50_p2e80`. Display modes remain EDID-driven.
### Risk vs benefit
Very low risk, contained to one product ID. Benefit is working/faster
power sequencing and no warning for that panel—standard stable device-ID
material.
---
Verification:
- [Phase 1] Parsed subject/tags/body from `git show 354b9c43d36ce`; EDID
`09 e5 f2 0a` + `NE140QDM-NX2` checked against the new `BOE, 0x0af2`
row
- [Phase 2] Diff is +1 line in `edp_panels[]`;
`generic_edp_panel_probe()` / `WARN_ON` /
`panel_edp_set_conservative_timings()` read in `panel-edp.c`
- [Phase 3] `git blame -L 2058,2062`; `git log -L
:delay_200_500_e50_p2e80:…` → `f4ccd9fea2270`; parent has no `0x0af2`;
`git merge-base --is-ancestor 354b9c43d36ce HEAD` → yes
- [Phase 3] No `Fixes:`; author log only this DRM commit
- [Phase 4] `b4 dig -c 354b9c43d36ce` / `-a` / `-w` / `-m`; v1 mbox (7
messages) with Doug’s sort + delay review; v2 applied despite wrap
- [Phase 4] WebFetch lore → 403; discussion taken from b4 mboxes instead
- [Phase 5] Call path: `"edp-panel"` → `panel_edp_probe()` →
`generic_edp_panel_probe()` → `find_edp_panel()`
- [Phase 6] `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`;
`VERSION=7 PATCHLEVEL=3 SUBLEVEL=0 EXTRAVERSION=-rc4`; delay struct
and table present
- [Phase 7] MAINTAINERS: `R: Douglas Anderson` for `panel-edp.c`;
Kconfig `DRM_PANEL_EDP`
- [Phase 8] Failure mode verified: unknown panel → WARN_ON + unprepare
2000 / enable 200
- UNVERIFIED: stable@ archive (lore HTTP 403); specific machine models
shipping this panel
**YES**
drivers/gpu/drm/panel/panel-edp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index 614c63e95c357..65e2f68b919ef 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -1989,6 +1989,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a6a, &delay_200_500_e80, "NV140WUM-N44"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ac5, &delay_200_500_e50, "NV116WHM-N4C"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ae8, &delay_200_500_e50_p2e80, "NV140WUM-N41"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0af2, &delay_200_500_e50_p2e80, "NE140QDM-NX2"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b09, &delay_200_500_e50_po2e200, "NV140FHM-NZ"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b1e, &delay_200_500_e80, "NE140QDM-N6A"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b34, &delay_200_500_e80_d50, "NV122WUM-N41"),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] misc: genwqe: handle a first DMA address of zero
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (24 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/panel-edp: Add BOE NE140QDM-NX2 Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] ALSA: hda/conexant: Add mute LED quirk for HP ProBook 440 G5 Sasha Levin
` (490 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Yousef Alhouseen, Greg Kroah-Hartman, Sasha Levin, haver,
linux-kernel
From: Yousef Alhouseen <alhouseenyousef@gmail.com>
[ Upstream commit d401772a9e18e837631450844f835229354528a4 ]
genwqe_setup_sgl() uses zero as the initial previous DMA address. DMA
address zero is valid, so a first entry at that address enters the
merge path before last_s has been assigned and dereferences NULL.
Only merge adjacent mappings after an SGL data entry has been created.
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Link: https://patch.msgid.link/20260630104923.53827-1-alhouseenyousef@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Confirmed `GENWQE_EXECUTE_DDCB` is unprivileged on a 0666 device node.
Compiling the nine-phase analysis from the code, history, and review
trail.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [misc: genwqe] [handle] [avoid NULL deref when the first SGL DMA
address is zero]
Subsystem prefix `misc: genwqe:`. Verb “handle” is a fix-style verb.
Claimed intent: stop treating DMA address 0 as “no previous mapping.”
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com> (author)
- Link: https://patch.msgid.link/20260630104923.53827-1-
alhouseenyousef@gmail.com
- Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (char-
misc maintainer; applied)
- No Fixes: tag (expected for this review pipeline)
- No Reported-by, Tested-by, Reviewed-by, Acked-by
- No Cc: stable@vger.kernel.org (expected; not a negative)
- Ignoring any Sasha Levin SOB (none on this commit)
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: `genwqe_setup_sgl()` initializes `prev_daddr = 0`. DMA address 0
is valid. If the first mapping is at 0, `prev_daddr == daddr` is true
while `last_s` is still NULL.
- Symptom/failure mode: NULL pointer dereference of `last_s->len`
(kernel oops).
- Version information: none in the message. History shows the pattern
dates to the original GenWQE driver (v3.14).
- Root cause: 0 used as a sentinel for “no previous DMA address,” which
collides with a valid IOVA/physical DMA address.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit NULL-deref fix. The
wording “handle” / “only merge after an SGL data entry has been created”
matches the one-line guard.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/misc/genwqe/card_utils.c` (+1 / -1)
- Function: `genwqe_setup_sgl()`
- Scope: single-file, single-line surgical fix
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
Before: on every mapping, `if (prev_daddr == daddr)` merges into
`last_s`. `prev_daddr` starts at 0, `last_s` starts NULL. First mapping
at DMA 0 takes the merge path and dereferences NULL.
After: `if (last_s && prev_daddr == daddr)` — merge only after a data
entry exists (`last_s` assigned at “start new entry”). First mapping
always creates an entry.
Verified in the current function:
```379:439:drivers/misc/genwqe/card_utils.c
dma_addr_t prev_daddr = 0;
struct sg_entry *s, *last_s = NULL;
...
if (last_s && prev_daddr == daddr) {
u32 prev_len = be32_to_cpu(last_s->len);
...
}
/* start new entry */
s[j].target_addr = cpu_to_be64(daddr);
...
last_s = &s[j];
```
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [NULL pointer dereference] [sentinel 0 vs valid DMA address 0].
`last_s` is only assigned when a new SG_DATA entry is created. Guarding
the merge with `last_s` skips merge until there is a real previous
entry.
Step 2.4: ASSESS THE FIX QUALITY
Record: Obviously correct. `last_s == NULL` means there is nothing to
merge; skipping merge is the right first-entry behavior. One-line, no
API/locking/structure changes. Regression risk is very low: the only new
path is “first daddr==0 creates an entry instead of oopsing.” Later
adjacent merges still work once `last_s` is set.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: Buggy `prev_daddr = 0`, `last_s = NULL`, and `if (prev_daddr ==
daddr)` come from 67f4addbb8fe68 (“GenWQE Utility functions”, Frank
Haverkamp, 2013-12-09). `git describe --contains` →
`v3.14-rc1~152^2~29`. Present for ~12 years. The fix line is
d401772a9e18e8 (this commit).
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Original buggy commit is 67f4addbb8fe68,
confirmed ancestor of HEAD. No intermediate fix of this sentinel bug in
`drivers/misc/genwqe/`.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Recent `card_utils.c` history is mostly treewide
MAX_ORDER/docs/DMA API churn. This commit is the only functional SGL-
merge change. Standalone; not patch X/Y.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Yousef Alhouseen has this single genwqe commit. Not the listed
maintainer (Frank Haverkamp). Greg KH applied it through char-misc. No
related follow-up series from the same author in this tree.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None. The change uses existing locals `last_s` and `prev_daddr`.
Applies standalone on any tree that still has the 2013
`genwqe_setup_sgl()` merge loop.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c d401772a9e18e837631450844f835229354528a4` → https://patch.m
sgid.link/20260630104923.53827-1-alhouseenyousef@gmail.com
- `b4 dig -a`: v1 only, 2026-06-30; no v2/v3
- lore.kernel.org fetches returned 403; discussion recovered from
https://lkml.iu.edu/hypermail/linux/kernel/2606.3/11318.html and
https://lists.openwall.net/linux-kernel/2026/06/30/1334
- Message matches the committed diff. No NAK found in those archives.
Greg applied it 2026-07-17 (char-misc), merged to Linus via `char-
misc-7.3-rc1` (93e4b3076b5f, 2026-08-25).
- No reviewer “Cc: stable” in the archives that were reachable.
- UNVERIFIED: full lore reply chain (403). No public replies found on
IU/openwall for this Message-ID.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc Frank Haverkamp (GENWQE maintainer), Arnd
Bergmann, Greg Kroah-Hartman, linux-kernel@. Applied by Greg (SOB). No
Reviewed-by/Acked-by on the commit.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by, syzbot, or bugzilla. Bug is from code inspection
of the sentinel/NULL pattern, not a published crash report.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone v1 patch, not a series. `git log --grep` on
`drivers/misc/genwqe/` found no companion “DMA address zero” follow-up.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search returned 403. UNVERIFIED whether
stable@ already discussed this specific commit. No local evidence it was
rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `genwqe_setup_sgl()` only. semcode MCP not available; identified
from the hunk header.
Step 5.2: TRACE CALLERS
Record: Single caller, `ddcb_cmd_fixups()` in
`drivers/misc/genwqe/card_dev.c` (ATS_TYPE_SGL_RD / ATS_TYPE_SGL_RDWR),
which is called from `genwqe_execute_ddcb()` → `do_execute_ddcb()` →
ioctl `GENWQE_EXECUTE_DDCB`.
Verified: `GENWQE_EXECUTE_DDCB` does **not** check
`capable(CAP_SYS_ADMIN)` (only `GENWQE_EXECUTE_RAW_DDCB` does).
`genwqe_devnode()` sets the char device mode to 0666. With CONFIG_GENWQE
and hardware present, an unprivileged process that can open
`/dev/genwqe*` can reach this path.
Step 5.3: TRACE CALLEES
Record: Builds hardware SG entries from `dma_list[]` (from
`dma_map_page()` in `genwqe_map_pages()`) or from `sgl->fpage_dma_addr`
/ `sgl->lpage_dma_addr` (`dma_alloc_coherent()`). first-page buffer:
`daddr = sgl->fpage_dma_addr + map_offs`. `dma_mapping_error()` treats
`~0` as error, not 0, so DMA address 0 is accepted as valid.
Step 5.4: FOLLOW THE CALL CHAIN
Record: userspace ioctl → `ddcb_cmd_fixups` → `genwqe_setup_sgl`.
Reachable from userspace when the IBM GenWQE card is present. Trigger
is: first SGL data mapping has DMA address 0 (IOMMU IOVA 0, or coherent
alloc at 0). Not every I/O; depends on the DMA API returning 0. Failure
is an oops, not a WARN.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same file’s `genwqe_unmap_pages()` also treats `dma_list[i] ==
0` as end-of-list. That is a separate sentinel bug and is **not** fixed
here. It does not make this `last_s` guard wrong: `fpage_dma_addr` does
not go through `dma_list`, so a coherent mapping at 0 still hits the
NULL deref. No sibling functions needed the same one-line change.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`
- `make kernelversion` → `7.3.0-rc4` (Linus mainline, not a -stable
series)
- Driver and `genwqe_setup_sgl()` exist. Bug introduced in v3.14
(67f4addbb8fe68), ancestor of HEAD.
- Candidate d401772a9e18 **is already an ancestor of HEAD** (expected:
candidates are taken from this mainline history). The pre-fix
condition is the historical `if (prev_daddr == daddr)` in this
lineage.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Surrounding function is essentially unchanged since 2014
(`718f762efc4547` adjusted mapping sources). Expected apply: clean (1
line). No conflicting refactor in this file’s recent history.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: This commit is the fix. No earlier alternative for the same NULL
deref. No later revert.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [drivers/misc/genwqe — IBM GenWQE PCIe accelerator]
[PERIPHERAL]. CONFIG_GENWQE, depends on PCI && 64BIT. MAINTAINERS:
“Supported,” Frank Haverkamp.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Low churn; mostly treewide and small misc fixes. Mature driver,
bug long-standing rather than a new-feature regression.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: driver-specific / config-specific: users with IBM GenWQE
hardware and CONFIG_GENWQE. Not universal. Device node default 0666
widens who can issue the ioctl on those systems.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger: SGL DDCB ioctl whose first mapped DMA address is 0.
Uncommon without an IOMMU that issues IOVA 0; possible with
`dma_alloc_coherent`/`dma_map_page`. Not every boot. Unprivileged users
can issue `GENWQE_EXECUTE_DDCB` if they can open the device.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: [NULL deref → kernel oops] [CRITICAL for affected systems]. No
data-corruption path identified beyond the crash itself.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: prevents oops on a valid DMA address; long-lived bug; ioctl-
reachable. Benefit is high for GenWQE users, limited population.
- Risk: one-line pointer NULL check; very low.
- Ratio: favorable. Stable rules accept important crashes in drivers,
not only core kernel.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR backporting:
- Real NULL deref, not style.
- DMA 0 is valid per the DMA API; using 0 as “no previous address” is
wrong.
- One-line, obviously correct, no new API.
- Bug in code since v3.14; driver present in this tree.
- Userspace-reachable via `GENWQE_EXECUTE_DDCB` on a 0666 node without
CAP_SYS_ADMIN.
- Applied by Greg KH; no NAK found.
- Applies cleanly; no prerequisites.
AGAINST:
- Peripheral IBM accelerator; few machines.
- No Reported-by/syzbot/crash log; trigger needs DMA address 0.
- Author is not the listed maintainer; no Reviewed-by.
- Separate `dma_list[i]==0` unmap sentinel remains (not a reason to skip
this fix).
UNRESOLVED:
- Full lore thread (403).
- Whether stable@ already queued/rejected it (403).
- How often GenWQE + IOVA 0 occurs in production (unverified frequency;
mechanism is verified).
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — logic is local and correct;
landed in char-misc/mainline. No extra Tested-by.
2. Fixes a real bug that affects users? PASS — NULL deref on a valid
first DMA address 0.
3. Important issue? PASS — kernel oops (CRITICAL on that path).
4. Small and contained? PASS — 1 line, one function.
5. No new features or APIs? PASS.
6. Can apply to the local tree? PASS — same `genwqe_setup_sgl()`; no
missing helpers. (This checkout already contains the commit because
it is 7.3-rc4 mainline; that does not change merit for stable.)
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary memory-
safety bug fix.
Step 9.4: MAKE YOUR DECISION
This is a one-line NULL-deref fix in a driver that exists in this
lineage since v3.14. The bug is real: `prev_daddr` is initialized to 0
while `last_s` is NULL, so a first mapping at DMA address 0 takes the
merge path and crashes. That path is ioctl-reachable. The patch is
minimal and does not need prerequisites. Peripheral hardware limits the
user set, but stable regularly takes crash fixes in supported drivers.
Benefit (oops avoided) outweighs risk (trivial guard).
What the commit solves for stable users: a kernel oops in
`genwqe_setup_sgl()` when the first SGL fragment is at DMA address 0.
Meets stable rules: obviously correct, real crash, small, no new API,
applies to this driver’s long-standing code.
Risk vs benefit: very low risk, meaningful crash fix for GenWQE systems.
Concerns: uncommon trigger; no user report. Those do not override a
verified oops with a one-line fix. This 7.3-rc4 tree already contains
the commit as mainline history; the evaluation is technical fitness for
stable trees that still have the unguarded `prev_daddr == daddr` test.
The surrounding function matches that old code, so a backport does not
need extra commits.
Verification:
- [Phase 1] Parsed tags: author SOB, Greg KH SOB, msgid Link; no
Fixes/Reported-by/Cc: stable
- [Phase 1] Body: first DMA 0 enters merge before `last_s` assigned →
NULL deref
- [Phase 2] Diff: 1 line in `genwqe_setup_sgl()`: `if (prev_daddr ==
daddr)` → `if (last_s && prev_daddr == daddr)`
- [Phase 2] Read `card_utils.c`: `prev_daddr = 0`, `last_s = NULL`,
`last_s` set only on new SG_DATA entry
- [Phase 3] `git blame`: buggy code from 67f4addbb8fe68 (v3.14-rc1); fix
is d401772a9e18
- [Phase 3] `git merge-base --is-ancestor 67f4addbb8fe68 HEAD`: yes;
`d401772a9e18` also ancestor of HEAD
- [Phase 3] `git log --oneline -20 -- drivers/misc/genwqe/card_utils.c`:
no prerequisite series
- [Phase 3] Author log: only this genwqe commit
- [Phase 4] `b4 dig -c d401772a9e18`: lore msgid 20260630104923.53827-1;
v1 only
- [Phase 4] `b4 dig -w`: Haverkamp, Arnd, Greg KH, linux-kernel@
- [Phase 4] IU/openwall: patch text matches commit; no NAK found
- [Phase 4] lore/stable WebFetch: 403 — UNVERIFIED full review thread
and stable@ discussion
- [Phase 5] grep: only caller `ddcb_cmd_fixups` → `GENWQE_EXECUTE_DDCB`
- [Phase 5] `GENWQE_EXECUTE_DDCB` has no CAP_SYS_ADMIN; `genwqe_devnode`
sets 0666
- [Phase 5] `dma_map_page`/`dma_alloc_coherent` + `dma_mapping_error` do
not reject address 0
- [Phase 6] `git describe HEAD`: v7.3-rc4-27; kernelversion 7.3.0-rc4;
driver present
- [Phase 6] Apply difficulty: clean 1-line change vs 2013/2014 function
- [Phase 7] MAINTAINERS: GENWQE Supported, Frank Haverkamp
- [Phase 8] Failure mode: NULL deref oops, severity CRITICAL on that
path
- UNVERIFIED: production frequency of DMA address 0 on GenWQE; full lore
replies
**YES**
drivers/misc/genwqe/card_utils.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index a2c4a9b4f871c..e3b5fb337182e 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -413,7 +413,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
size -= size_to_map;
map_offs = 0;
- if (prev_daddr == daddr) {
+ if (last_s && prev_daddr == daddr) {
u32 prev_len = be32_to_cpu(last_s->len);
/* pr_info("daddr combining: "
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] ALSA: hda/conexant: Add mute LED quirk for HP ProBook 440 G5
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (25 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] misc: genwqe: handle a first DMA address of zero Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] usb: typec: mux: tusb1046: add missing MODULE_DEVICE_TABLE() Sasha Levin
` (489 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Dmytro Moroziuk, Takashi Iwai, Sasha Levin, perex, tiwai,
linux-sound, linux-kernel
From: Dmytro Moroziuk <dmorozyk1@gmail.com>
[ Upstream commit 191fe151eb85ff6cb24189fc88c970745497c057 ]
The HP ProBook 440 G5 requires the CXT_FIXUP_MUTE_LED_GPIO quirk to
properly toggle the physical mute and mic-mute LEDs via the CX8200 codec.
Without this quirk, the LEDs remain permanently dark.
Signed-off-by: Dmytro Moroziuk <dmorozyk1@gmail.com>
Link: https://patch.msgid.link/20260812121856.30353-1-dmorozyk1@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line Conexant mute-LED quirk for HP ProBook 440 G5 (PCI
SSID `0x103c:0x837b`). The local tree is **6.12.111** (`pending-6.12`);
the driver and sibling G4/G5 quirks are already here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: [ALSA: hda/conexant] [Add] [mute LED quirk for HP ProBook 440
G5]
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Dmytro Moroziuk \<dmorozyk1@gmail.com\> (author)
- Link:
https://patch.msgid.link/20260812121856.30353-1-dmorozyk1@gmail.com
- Signed-off-by: Takashi Iwai \<tiwai@suse.de\> (ALSA maintainer)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, or Cc:
stable (absence is expected for this review)
- Ignore any pipeline-added Sasha Levin SOB / Upstream commit markers
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: HP ProBook 440 G5 mute and mic-mute LEDs stay off because the
CX8200 codec is not wired to `CXT_FIXUP_MUTE_LED_GPIO`.
- Symptom: physical mute/mic-mute LEDs remain permanently dark.
- Root cause: missing `SND_PCI_QUIRK` for SSID `0x103c:0x837b`.
- No stack traces, no kernel version range, no crash.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a hidden fix. It is an explicit hardware quirk / device-
table addition.
===============================================================
PHASE 2: DIFF ANALYSIS
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- Upstream file: `sound/hda/codecs/conexant.c` (+1 / −0)
- Function/table: `cxt5066_fixups[]`
- Scope: single-file, one-line table insert
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: SSID `0x103c:0x837b` matches no quirk; GPIO mute-LED setup is
skipped.
- After: match applies `CXT_FIXUP_MUTE_LED_GPIO` →
`cxt_fixup_mute_led_gpio()` at `HDA_FIXUP_ACT_PRE_PROBE` →
`cxt_setup_mute_led(codec, 0x01, 0x02)`.
- Path: codec probe / initialization only; no error-path or hot-path
change.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: [Hardware workaround / codec quirk]
- Mechanism: missing PCI SSID in the existing Conexant quirk table.
- Fix: add one `SND_PCI_QUIRK` using the same `CXT_FIXUP_MUTE_LED_GPIO`
already used by ProBook 440 G4 (`0x822e`), 455 G5 (`0x836e`), 470 G5
(`0x837f`), 450 G4 (`0x8231`).
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct; surgical; no API/locking/refcount change.
Regression risk is limited to that SSID. `0x837b` is unused in this
tree’s quirk table.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: The new line did not exist here. Adjacent entries:
- `0x836e` HP ProBook 455 G5 — present since at least Takashi Iwai 2021
(`2e6a731296be9d`)
- `0x837f` HP ProBook 470 G5 — same
- `0x822e` HP ProBook 440 G4 — `ba92b11428797` (Kai-Heng Feng, 2017),
originally `Cc: stable # v4.12+`
`CXT_FIXUP_MUTE_LED_GPIO` itself dates to `5cd5b1bdfb013` (HP ZBook 15u
G3, 2017).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. The “bug” is a missing table entry, not a
regression from a specific commit.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same-file mute-LED quirks already in this tree include 440 G4,
450 G4 (`1cce98bf41390`, backported here with `Cc: stable`), 455 G5, 470
G5, 645 G4. Standalone, not a series.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: No prior Dmytro Moroziuk commits on `sound/pci/hda/` in this
tree. ALSA maintainer Takashi Iwai applied it the same day.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs `CXT_FIXUP_MUTE_LED_GPIO` / `cxt_fixup_mute_led_gpio()` /
`cxt5066_fixups[]` — all present. Standalone. Path remapped from
`sound/hda/codecs/conexant.c` (post-6.12 move) to
`sound/pci/hda/patch_conexant.c`.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 191fe151eb85f` →
https://patch.msgid.link/20260812121856.30353-1-dmorozyk1@gmail.com
- Single v1 series; no v2/v3
- Thread: author submission + Takashi Iwai: “Thanks, applied to for-next
branch now.”
- No NAK, no requested changes, no reviewer Cc: stable (common for one-
line quirks)
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc perex@perex.cz, tiwai@suse.com, linux-
sound@vger.kernel.org. Right list and both ALSA maintainers.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot link. User-visible hardware issue stated in
the commit; accepted by the subsystem maintainer.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone one-patch series. Later `origin/master` conexant
commits (headset plugin, SN6140 S3) do not touch `0x837b`.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No stable@ discussion found for this model/ID. Sibling quirks
historically went to stable with explicit Cc.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: Table `cxt5066_fixups[]`; applied fixup
`cxt_fixup_mute_led_gpio()`.
**Step 5.2: TRACE CALLERS**
Record: `patch_conexant_auto()` → `snd_hda_pick_fixup(...,
cxt5066_fixups, ...)` for codec IDs including default and CX8200
(`HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto)` at line
1305). Lookup is PCI subsystem vendor/device.
**Step 5.3: TRACE CALLEES**
Record: `cxt_fixup_mute_led_gpio` → `cxt_setup_mute_led(codec, 0x01,
0x02)` → `snd_hda_gen_add_mute_led_cdev` /
`snd_hda_gen_add_micmute_led_cdev`. Existing, stable helpers.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Codec probe on matching HP laptop. Userspace mute/mic-mute then
drives GPIO LEDs. Reachable on that hardware; not a generic syscall
crash path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same one-line pattern used for several HP ProBook G4/G5 Conexant
machines; 450 G4 already backported into this 6.12 tree.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Tree: `p-6.12-3-gc504cf0baa3d8`, `make kernelversion` = 6.12.111
- `git merge-base --is-ancestor 191fe151eb85f HEAD` → not present
- File here: `sound/pci/hda/patch_conexant.c` (no
`sound/hda/codecs/conexant.c`)
- `cxt5066_fixups[]` exists; `0x837b` / “HP ProBook 440 G5” absent
- CX8200 codec entry exists
- Bug is long-standing missing hardware enablement, not a post-6.12
regression
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Path remap required. Context matches. `git apply --check` after
remapping to `sound/pci/hda/patch_conexant.c`: “Hunk #1 succeeded at
1105 (offset -2 lines).” Clean apply with trivial path change.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No 440 G5 / `0x837b` entry. Related G4/G5 mute-LED quirks are
already present.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: [sound/pci/hda Conexant codec] [IMPORTANT for laptop audio;
quirk is machine-specific]
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature table; regular quirk additions. Recent local commits
include other pin/quirk updates. Typical LTS candidate.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific / platform-specific: HP ProBook 440 G5 (SSID
0x103c:0x837b) with CX8200, `CONFIG_SND_HDA_CODEC_CONEXANT`.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every boot on that laptop. Mute/mic-mute keys do not light LEDs.
Unprivileged users see dead LEDs; not a privilege issue.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Mute/mic-mute LEDs stay dark. Severity LOW as crash/corruption,
but a real hardware bug that stable rules call out as a quirk.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: restores LED behavior on a shipping HP ProBook still used on
6.12 LTS; matches sibling models already in this tree.
- Risk: one table line, SSID-gated, existing fixup. Very low.
- Ratio: strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Explicit hardware quirk / PCI ID addition (stable-rules exception)
- Fixes user-visible broken mute/mic-mute LEDs on HP ProBook 440 G5
- One line, existing `CXT_FIXUP_MUTE_LED_GPIO`
- Same pattern as 440 G4 / 450 G4 / 455 G5 / 470 G5 already in this tree
- 450 G4 equivalent already backported here with Cc: stable
- Applied by ALSA maintainer; no NAK
- Applies here with only a path remap
- `Documentation/process/stable-kernel-rules.rst`: “fix a real bug … or
just add a device ID” and “hardware quirk”
AGAINST:
- Not a crash, UAF, or security issue
- No Fixes:/Cc: stable (not a negative for this pipeline)
- Author is not a regular conexant contributor (mitigated by maintainer
apply)
UNRESOLVED:
- Independently verifying the reporter’s hardware beyond SSID +
maintainer accept: not possible from git/lore
- lore.kernel.org WebFetch returned 403; thread recovered via `b4 dig
-m`
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? PASS — one-line table entry, maintainer
applied
2. Fixes a real bug that affects users? PASS — LEDs stay dark on that
laptop
3. Important issue? PASS as hardware quirk / device ID (not crash-level)
4. Small and contained? PASS — +1 line
5. No new features or APIs? PASS — existing fixup, new SSID only
6. Can apply to the local tree? PASS — context present; remap
`sound/hda/codecs/conexant.c` → `sound/pci/hda/patch_conexant.c`
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Hardware quirk / codec quirk table entry (also a device-ID-style
addition to an existing driver).
**Step 9.4: MAKE YOUR DECISION**
This belongs in 6.12.y. The driver, fixup, and neighboring ProBook G5
IDs are already here; only this SSID is missing. Risk is negligible.
------------------------------------------------
What the commit solves and why it matters
------------------------------------------------
Without the quirk, CX8200 GPIO mute/mic-mute LEDs on HP ProBook 440 G5
never toggle. That is a real hardware bug for owners of this 2018-era
ProBook on LTS. The fix is the same one-line SSID mapping already used
on 440 G4 and other G5 ProBooks.
Risk vs benefit: benefit is working LEDs on one laptop model; risk is
confined to SSID `0x103c:0x837b`. Backport needs only the file-path
rename from the later HDA codec shuffle.
Verification:
- [Phase 1] Parsed tags: author SOB, Link msgid, Takashi Iwai SOB; no
Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: +1 `SND_PCI_QUIRK(0x103c, 0x837b, "HP ProBook 440 G5",
CXT_FIXUP_MUTE_LED_GPIO)` in `cxt5066_fixups[]`
- [Phase 2] Local `cxt_fixup_mute_led_gpio()` at
`sound/pci/hda/patch_conexant.c:789` calls `cxt_setup_mute_led(codec,
0x01, 0x02)`
- [Phase 3] `git blame -L 1098,1115`: sibling G4/G5 quirks present; 440
G4 is `ba92b11428797` with original Cc: stable
- [Phase 3] `git show 1cce98bf41390`: 450 G4 mute-LED quirk already in
this 6.12 tree from upstream
- [Phase 3] `git log --author="Dmytro Moroziuk"` on `sound/pci/hda/`: no
prior commits
- [Phase 4] `b4 dig -c 191fe151eb85f`: lore match; v1 only; recipients
perex/tiwai/linux-sound
- [Phase 4] mbox: Iwai “Thanks, applied to for-next branch now.”; no NAK
- [Phase 4] WebFetch lore URLs: 403; thread recovered via b4
- [Phase 4] WebSearch stable@: no discussion of this model
- [Phase 5] CX8200 `HDA_CODEC_ENTRY(0x14f12008, "CX8200",
patch_conexant_auto)` present; `snd_hda_pick_fixup` matches PCI SSID
- [Phase 6] `git describe HEAD` → `p-6.12-3-gc504cf0baa3d8`; `make
kernelversion` → 6.12.111
- [Phase 6] `git merge-base --is-ancestor 191fe151eb85f HEAD` → not in
tree
- [Phase 6] grep `0x837b` / `HP ProBook 440 G5` in conexant: no match
- [Phase 6] remapped `git apply --check`: hunk succeeded at 1105 (offset
-2)
- [Phase 6] `git log origin/master` after the commit: later conexant
changes do not touch `0x837b`
- [Phase 7/8] Failure mode: dark mute/mic-mute LEDs on one HP model;
quirk exception applies
- UNVERIFIED: physical confirmation of reporter’s 440 G5/CX8200 beyond
commit + maintainer apply
- UNVERIFIED: lore.kernel.org HTML fetch (403); b4 mbox used instead
**YES**
sound/hda/codecs/conexant.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/hda/codecs/conexant.c b/sound/hda/codecs/conexant.c
index ef40f1cb1158e..862fcbe74e4f0 100644
--- a/sound/hda/codecs/conexant.c
+++ b/sound/hda/codecs/conexant.c
@@ -1115,6 +1115,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x82b4, "HP ProDesk 600 G3", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x837b, "HP ProBook 440 G5", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] usb: typec: mux: tusb1046: add missing MODULE_DEVICE_TABLE()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (26 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] ALSA: hda/conexant: Add mute LED quirk for HP ProBook 440 G5 Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:03 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Add mute LED support for HP Pavilion 15-eh2xxx Sasha Levin
` (488 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Romain Gantois, Greg Kroah-Hartman, Sasha Levin,
heikki.krogerus, linux-usb, linux-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 5e4eb5c96324b226220d29d025a334df28054ed3 ]
The driver has an OF match table wired to .of_match_table, but does
not export the table with MODULE_DEVICE_TABLE().
Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias
information is generated for OF based module autoloading.
This is a source-level fix. It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the platform driver, and the missing module alias publication.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Reviewed-by: Romain Gantois <romain.gantois@bootlin.com>
Link: https://patch.msgid.link/20260704124714.18404-1-pengpeng@iscas.ac.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **v7.3-rc4**. The tusb1046 driver is present, and this
is a one-line OF module-alias publication so udev can autoload the
driver. That is a real modular-build bug, not a new feature.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[usb: typec: mux: tusb1046]** **[add]** missing
`MODULE_DEVICE_TABLE()` so OF module aliases are generated.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** Romain Gantois \<romain.gantois@bootlin.com\> (driver
author / listed maintainer)
- **Acked-by:** none in the commit; mailing-list thread also has
**Reviewed-by: Heikki Krogerus** (USB Type-C maintainer) that did not
land in the commit text
- **Link:**
https://patch.msgid.link/20260704124714.18404-1-pengpeng@iscas.ac.cn
- **Cc: stable@vger.kernel.org:** absent (expected)
- **Signed-off-by:** Pengpeng Hou (author); Greg Kroah-Hartman (USB
maintainer, merged)
- Ignore any pipeline “already selected” / Sasha Levin markers (none in
this commit object)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `tusb1046_match_table` is wired to `.of_match_table` but not
exported with `MODULE_DEVICE_TABLE(of, ...)`.
- **Symptom:** when `CONFIG_TYPEC_MUX_TUSB1046=m`, `depmod` does not
emit `of:N*T*Cti,tusb1046` aliases, so udev/kmod will not autoload the
module when DT instantiates the I2C device.
- **Failure mode:** Type-C mux / orientation switch stays unbound until
a manual `modprobe`. Built-in (`=y`) is unaffected.
- **Version info:** none in the message.
- **Root cause:** missing module alias publication; match table itself
is correct.
- The “source-level fix / no dynamic hardware reproduction” sentence is
in both the sent patch and the committed message.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. It is an explicit autoload/alias bug. Same class as
device-ID publication: no new behavior, just making existing OF matching
visible to userspace module loading.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/usb/typec/mux/tusb1046.c` — **+1 / −0**
- **Function:** none; one line after `tusb1046_match_table[]`
- **Scope:** single-file, one-line surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** OF table exists and is used for in-kernel matching if the
module is already loaded; file2alias never sees it.
- **After:** `MODULE_DEVICE_TABLE(of, tusb1046_match_table)` creates the
`__mod_of__tusb1046_match_table` alias consumed by
`scripts/mod/file2alias.c`.
- **Path:** build-time module metadata only; probe/remove/mux paths
unchanged.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** hardware matching / module autoload (device-ID
publication), not UAF/race/leak.
- **Mechanism:** OF compatible `ti,tusb1046` was never exported in the
module’s device table, so autoload could not work.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: this is the standard macro used by sibling Type-C
mux drivers (`fsa4480`, `ptn36502`, `it5205`, `nb7vpq904m`, etc.).
- Minimal; no API, locking, or runtime change.
- Regression risk: negligible. Wrong table/type would be a build
concern; here type `of` matches `struct of_device_id`.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Match table introduced in **7c561b8c3e836** (“usb: typec: mux: Add
support for the TUSB1046 crosspoint switch”), **Romain Gantois**,
2024-10-24, first contained in **v6.13-rc1**.
- Original driver had `.of_match_table = tusb1046_match_table` and
**no** `MODULE_DEVICE_TABLE`. Bug present from introduction.
- Candidate: **5e4eb5c96324b226220d29d025a334df28054ed3**, first
contained in **v7.3-rc1**.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Buggy commit is the driver intro
**7c561b8c3e836**, which **is** an ancestor of this HEAD.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record (on this file): driver add → `dev_err_probe` cleanup → include-
header reshuffle → this alias fix. Standalone; not patch x/y. No
prerequisite refactor required for the one-line add.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Pengpeng Hou is a contributor, not the Type-C mux maintainer.
Nearby USB work is unrelated. Weight comes from **Romain Gantois**
(driver maintainer) and **Heikki Krogerus** (Type-C) reviews, plus Greg
KH merge.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None. `MODULE_DEVICE_TABLE` exists in `include/linux/module.h`
in this tree. Applies standalone on any tree that has
`tusb1046_match_table`.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig -c 5e4eb5c96324b:**
https://patch.msgid.link/20260704124714.18404-1-pengpeng@iscas.ac.cn
- **b4 dig -a:** single **v1**, 2026-07-04, no later revision.
- Thread (mbox): Romain Gantois “LGTM, thanks!” + R-b (2026-07-07);
Heikki Krogerus R-b (2026-07-13, after Greg’s 2026-07-08 commit). **No
NAKs, no stable discussion, no risk flags.**
- WebFetch of lore.kernel.org returned **403**; thread recovered via `b4
dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: **b4 dig -w** original To/Cc: Pengpeng Hou, Romain Gantois,
Heikki Krogerus, Greg Kroah-Hartman, linux-usb, linux-kernel. Right
maintainers were on the patch.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla/Reported-by. Justification is the missing
macro vs an existing OF table. No in-tree DTS consumer of `ti,tusb1046`
(only `Documentation/devicetree/bindings/usb/ti,tusb1046.yaml`). User
impact is boards that describe this chip in DT, including out-of-tree
DTS.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone v1. Same pattern already used in this tree:
**15a34e5d4b23c** (“usb: typec: fix module autoloading”),
**f27891abb7930** (“usb: typec: add missing MODULE_DEVICE_TABLE() to
stusb160x”).
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — lore.kernel.org/stable WebFetch 403; WebSearch
failed. No stable nomination in the recovered linux-usb thread.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: No function body changed. Data: `tusb1046_match_table`; driver:
`tusb1046_driver` / `module_i2c_driver()`.
**Step 5.2: TRACE CALLERS**
Record: I2C core binds via `module_i2c_driver`. OF match is used once
the module is loaded. Autoload is userspace (udev) using aliases from
`modules.alias`. Reachable on DT platforms with `compatible =
"ti,tusb1046"`.
**Step 5.3: TRACE CALLEES**
Record: N/A for the added line. Macro expands to a static alias
attribute for modpost.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: DT I2C instantiation → udev/kmod looks up OF alias → `tusb1046`
module → `tusb1046_i2c_probe`. Userspace cannot trigger a crash via this
bug; the failure is **driver never loads**.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Other Type-C mux drivers already have `MODULE_DEVICE_TABLE(of,
...)`. This driver was the one that omitted it. Semcode MCP not
available; used `git grep`.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- **Tree:** `git describe HEAD` = **v7.3-rc4-27-gf0100363d8c37**; `make
kernelversion` = **7.3.0-rc4**.
- Driver file exists; Kconfig `TYPEC_MUX_TUSB1046` is **tristate**.
- Bug introduced **v6.13**; this 7.3 lineage includes that driver.
- **HEAD already contains 5e4eb5c96324b** (`git merge-base --is-
ancestor` succeeded). Current file already has line 181
`MODULE_DEVICE_TABLE(of, tusb1046_match_table)`. That is mainline
history, not a reason to reject on technical merit.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: On **current HEAD**, `git apply --check` of the commit **fails**
because the line is already present. Against the pre-fix file (parent of
5e4eb5c96324b) the hunk is a clean one-line insert after the match
table. Any stable tree that still has the original
`tusb1046_match_table` without the macro would take it cleanly.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This exact fix is already in HEAD. No alternate autoload
workaround in the driver. Sibling Type-C autoload fixes are also present
and do not replace this line.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **USB Type-C mux driver** (`drivers/usb/typec/mux/`).
**PERIPHERAL** — one I2C crosspoint switch, not mm/VFS/net core. Still
user-visible USB-C / DP altmode on boards that have the chip.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Type-C mux is actively developed (ps883x and related churn).
`tusb1046.c` itself is low-churn since v6.13.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific + config-specific:**
`CONFIG_TYPEC_MUX_TUSB1046=m` on OF/I2C systems with `ti,tusb1046`. Not
universal. No in-tree DTS users found; out-of-tree / vendor DT is the
realistic consumer.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every boot/enumeration of that DT node when the driver is a
module. Not a race. Unprivileged users do not exploit it; they just do
not get the mux driver.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Failure mode:** module does not autoload; USB-C orientation/DP
muxing does not come up until manual load. **Severity: MEDIUM**
(functional hardware enablement, not oops/corruption/deadlock). Built-in
builds: no bug.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** high for TUSB1046 modular users (device actually probes);
moderate overall (narrow hardware, no in-tree board).
- **Risk:** very low (1 line, metadata only).
- **Ratio:** favorable — same justification as adding a device ID to an
existing driver.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR backporting:
- Real autoload bug for a tristate driver with an OF table.
- One line, obviously correct, no runtime path change.
- Reviewed by the driver author and Type-C maintainer; merged by Greg
KH.
- Same pattern already used in this Type-C subsystem.
- Fits the stable exception for publishing match IDs so existing
hardware actually binds.
- Driver and match table exist in this 7.3 tree (introduced v6.13).
AGAINST:
- Not a crash, UAF, deadlock, or security issue.
- No user `Reported-by` and no in-tree DTS enabling the compatible.
- “Tested” is source-level, not hardware reproduction.
- HEAD already contains the commit (expected on 7.3-rc; not a pipeline-
selection marker).
UNRESOLVED:
- Could not query lore.kernel.org/stable (HTTP 403 / search failure).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — standard macro; maintainer
R-b. Hardware test not claimed.
2. Fixes a real bug that affects users? **PASS** — modular OF autoload
is broken.
3. Important issue? **PASS** as hardware enablement (autoload),
analogous to new device IDs; not CRITICAL.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS** — exports an existing table.
6. Can apply to the local tree? **PASS** for this codebase (driver
present). Re-applying on current HEAD conflicts only because the fix
is already merged here; a tree that still lacks the line applies
cleanly.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Device ID / module alias publication** for an existing driver
(OF `MODULE_DEVICE_TABLE`). Also build-time metadata, not a new driver.
**Step 9.4: MAKE YOUR DECISION**
This tree has the TUSB1046 driver. Missing `MODULE_DEVICE_TABLE(of,
...)` prevents automatic loading of a modular Type-C mux, so USB-C/DP
switching does not come up on DT systems until someone loads the module
by hand. The fix is one obviously correct line with essentially no
regression risk. That meets stable rules and the device-ID exception, so
it should be backported to this tree’s stable series.
===============================================================
What the commit solves for stable users
===============================================================
With `TYPEC_MUX_TUSB1046=m`, kmod never learns the `ti,tusb1046` OF
alias, so the I2C Type-C mux never autoprobes. Distro/embedded kernels
that ship this as a module then lose orientation switch and DisplayPort
muxing on that hardware. The patch only emits the alias; it does not
change probe logic.
Risk is negligible. Benefit is real for modular users of this chip. No
extra commits are required beyond the driver that this 7.3 tree already
has.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed commit **5e4eb5c96324b**: R-b Romain Gantois; Link
patch.msgid.link; no Fixes/Reported-by/Cc:stable.
- [Phase 2] Diff: **+1** `MODULE_DEVICE_TABLE(of, tusb1046_match_table)`
in `drivers/usb/typec/mux/tusb1046.c`.
- [Phase 2] Confirmed sibling mux drivers already use
`MODULE_DEVICE_TABLE(of, ...)`.
- [Phase 3] `git blame`: table from **7c561b8c3e836** (v6.13-rc1);
original add had no `MODULE_DEVICE_TABLE`.
- [Phase 3] `git describe --contains 7c561b8c3e836` → v6.13-rc1; `git
describe --contains 5e4eb5c96324b` → v7.3-rc1.
- [Phase 3] `git merge-base --is-ancestor 5e4eb5c96324b HEAD` → yes;
`7c561b8c3e836` → yes.
- [Phase 3] `git show 7c561b8c3e836` confirms OF table without the
macro.
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 only; R-b Gantois + Krogerus;
recipients include Type-C and USB maintainers; no NAK.
- [Phase 4] lore WebFetch 403; used mbox instead.
- [Phase 5] Kconfig `TYPEC_MUX_TUSB1046` is tristate; Makefile builds
`tusb1046.o`; DT binding `ti,tusb1046.yaml` exists.
- [Phase 5] `git grep ti,tusb1046 arch/` → no in-tree DTS.
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-g…; kernelversion
7.3.0-rc4.
- [Phase 6] HEAD already has the line; `git apply --check` of the patch
on HEAD fails; parent of the commit lacks the macro.
- [Phase 7] MAINTAINERS: USB TYPEC TUSB1046 MUX DRIVER → Romain Gantois.
- [Phase 8] Failure = missing autoload, severity MEDIUM; risk very low.
- UNVERIFIED: stable@ discussion (lore/stable unreachable).
**YES**
drivers/usb/typec/mux/tusb1046.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/typec/mux/tusb1046.c b/drivers/usb/typec/mux/tusb1046.c
index 3c1a4551c2fbf..89b47aa56c7a9 100644
--- a/drivers/usb/typec/mux/tusb1046.c
+++ b/drivers/usb/typec/mux/tusb1046.c
@@ -179,6 +179,7 @@ static const struct of_device_id tusb1046_match_table[] = {
{.compatible = "ti,tusb1046"},
{},
};
+MODULE_DEVICE_TABLE(of, tusb1046_match_table);
static struct i2c_driver tusb1046_driver = {
.driver = {
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Add mute LED support for HP Pavilion 15-eh2xxx
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (27 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] usb: typec: mux: tusb1046: add missing MODULE_DEVICE_TABLE() Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] wifi: brcmfmac: Set DMA direction for msgbuf packet IDs Sasha Levin
` (487 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Luca Castaldini, Takashi Iwai, Sasha Levin, perex, tiwai,
linux-sound, linux-kernel
From: Luca Castaldini <luca.castaldini96@gmail.com>
[ Upstream commit daf55a381dca9bda12cc8c3a47605698f2d560e9 ]
Add the subsystem ID 103c:8a0e to the ALC287 HP GPIO LED quirk
table so the mute LED follows the speaker mute state.
Tested on HP Pavilion Laptop 15-eh2xxx with ALC287 codec.
The mute LED now follows the speaker mute state.
Signed-off-by: Luca Castaldini <luca.castaldini96@gmail.com>
Link: https://patch.msgid.link/20260805122907.52302-1-luca.castaldini96@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: this is a one-line HP mute-LED quirk, the
`ALC287_FIXUP_HP_GPIO_LED` helper already exists in 5.10, and this tree
already takes the same class of Realtek ID additions.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [ALSA: hda/realtek] [Add] [mute LED support for HP Pavilion
15-eh2xxx by adding PCI subsystem ID 103c:8a0e to an existing GPIO LED
quirk table]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Fixes: none (expected for this review pipeline)
- Reported-by: none
- Tested-by: none as a tag; the body states the author tested it on the
target laptop
- Reviewed-by: none
- Acked-by: none
- Link: https://patch.msgid.link/20260805122907.52302-1-
luca.castaldini96@gmail.com
- Cc: stable@vger.kernel.org: absent (expected; not a negative signal)
- Signed-off-by: Luca Castaldini <luca.castaldini96@gmail.com> (author)
- Signed-off-by: Takashi Iwai <tiwai@suse.de> (ALSA maintainer; applied
the patch)
- Ignore any Sasha Levin SOB if present in candidate packaging
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug description: HP Pavilion Laptop 15-eh2xxx (ALC287) mute LED does
not follow speaker mute because subsystem ID 103c:8a0e is missing from
the ALC287 HP GPIO LED quirk table.
- Symptom/failure mode: mute LED stays out of sync with speaker mute
(LED does not work as users expect). Audio playback itself is not
described as broken.
- Version information: none in the message. Hardware is a 2021–2022
Pavilion (linux-hardware.org year 2021; retail listings 2022).
- Root cause: missing SND_PCI_QUIRK entry; the existing
ALC287_FIXUP_HP_GPIO_LED fixup already implements GPIO mute LED
control.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a hidden bug fix. It is an explicit hardware quirk / device-
ID addition. The subject says "Add" rather than "fix", but this is the
documented stable exception for audio codec quirks (SND_PCI_QUIRK for a
specific laptop).
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- Files: sound/hda/codecs/realtek/alc269.c (+1 / -0)
- Function/table: alc269_fixup_tbl[] (static const struct hda_quirk /
snd_pci_quirk)
- Scope: single-file, one-line surgical quirk addition
- Added line: SND_PCI_QUIRK(0x103c, 0x8a0e, "HP Pavilion Laptop
15-eh2xxx", ALC287_FIXUP_HP_GPIO_LED)
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: codec probe for PCI SSID 103c:8a0e does not match a quirk, so
GPIO mute LED is not hooked to speaker mute.
- After: snd_hda_pick_fixup() matches 0x103c/0x8a0e and applies
ALC287_FIXUP_HP_GPIO_LED, which calls alc287_fixup_hp_gpio_led() →
alc_fixup_hp_gpio_led(..., mute_mask=0x10, micmute_mask=0), wiring
GPIO bit 4 (0x10) as the mute LED.
- Path affected: HDA codec probe / LED classdev registration for this
one SSID only.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Bug category: hardware workaround / audio codec quirk (SND_PCI_QUIRK)
- Mechanism: laptop mute LED is GPIO-driven; without the quirk the LED
is not bound to mute state. The fix only adds the SSID to the existing
table. No new fixup function.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: one ID, existing enum, existing function. Same
pattern as many quirks already in this tree (e.g. 0x87cb/0x87cc
Pavilion 15-eg0xxx).
- Minimal: one line, no unrelated changes, no API change.
- Regression risk: very low. Only machines with SSID 103c:8a0e are
affected. Wrong GPIO would misdrive that laptop's LED, but the author
tested ALC287 on this model and nearby Pavilion 14-ec1xxx (0x8a0f)
uses the same fixup in mainline.
- Red flags: none (no new APIs, no locking, no refcount, no series
dependency).
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- This tree does not have alc269.c; equivalent table is
sound/pci/hda/patch_realtek.c.
- ALC287_FIXUP_HP_GPIO_LED and alc287_fixup_hp_gpio_led() were
introduced by a0ccbc5319d57 ("ALSA: hda/realtek - Add supported mute
Led for HP", Kailang Yang, 2020-11-06). That commit is an ancestor of
HEAD.
- First table users of that fixup in this tree: 0x87f4/0x87f5 (same
commit), later 0x87c8 (3e1bcaebe8b10, 2020-12), 0x87cc (d7e11de23f197,
2025-07), 0x87cb (471db5addec8c, 2026-03).
- 0x8a0e is not present in this checkout.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. The "bug" is a missing quirk for hardware that
shipped after 5.10's original release, not a regression from a specific
earlier commit.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Recent patch_realtek.c history on this branch includes many mute-LED
ID additions (4a660d1dc6a0f 14s-dr1xxx, 471db5addec8c 15-eg0xxx,
d391901abfc67 15s-eq1xxx, etc.).
- Neighbor ID 0x8a0f ("HP Pavilion 14-ec1xxx") is in the candidate hunk
context but is not in this 5.10 table.
- Related mainline commit 068641bc9dc3d adds 15-eh1xxx with a different
codec/fixup (ALC245 / ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT). Not a
prerequisite; different board (88D1 vs 8A0E). Not in this tree.
- Standalone: not patch X/Y.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: git log --author='Luca Castaldini' on this tree's sound/pci/hda/
returned no commits. First-time contributor for this ID. Maintainer
Takashi Iwai applied it the same day.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record:
- Required symbols exist here: ALC287_FIXUP_HP_GPIO_LED enum,
alc287_fixup_hp_gpio_led(), alc_fixup_hp_gpio_led(), alc269_fixup_tbl,
snd_hda_pick_fixup() in alc269 probe.
- No new functions or structs.
- Path differs (mainline split Realtek into
sound/hda/codecs/realtek/alc269.c; 5.10 still uses
sound/pci/hda/patch_realtek.c). Standalone conceptually; apply needs a
path/context tweak, not extra commits.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- Commit on all-next: daf55a381dca9bda12cc8c3a47605698f2d560e9 (not an
ancestor of this HEAD).
- b4 dig -c daf55a381dca9: lore.kernel.org patch-id search errored;
author/subject match succeeded.
- Lore/msgid: https://patch.msgid.link/20260805122907.52302-1-
luca.castaldini96@gmail.com
- Mirrors: https://lkml.iu.edu/hypermail/linux/kernel/2608.0/08604.html
(patch), .../09065.html (Iwai reply)
- b4 dig -a: single v1 series, 2026-08-05. No v2/v3.
- Reviewer: Takashi Iwai applied to for-next the same day: "Applied to
for-next branch now. Thanks." No NAK, no stable discussion, no risk
flags.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: b4 dig -w recipients: Luca Castaldini, tiwai@suse.com,
perex@perex.cz, linux-sound@vger.kernel.org, linux-
kernel@vger.kernel.org. Correct ALSA maintainers and lists. Applied by
Takashi Iwai.
Step 4.3: SEARCH FOR THE BUG REPORT
Record:
- No bugzilla or syzbot link.
- Author tested on HP Pavilion Laptop 15-eh2xxx with ALC287.
- linux-hardware.org probe 0510a78cfe confirms Pavilion Laptop
15-eh2xxx, motherboard 8A0E, PCI SSID 103c:8a0e, Ryzen HD Audio
(snd_hda_intel), year ~2021, Ubuntu 22.04 / kernel 6.5 in that probe.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone v1. Related but independent: 15-eh1xxx quirk
(068641bc9dc3d) uses ALC245, not this fixup. 14-ec1xxx (0x8a0f) is the
table neighbor in mainline; not required here.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable fetch returned 403. Web search did not
find a stable-list thread for 15-eh2xxx / 8a0e. UNVERIFIED that nobody
requested or rejected it on stable@; no evidence of a NAK.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: No function body edited. Table alc269_fixup_tbl[]. Runtime
target: ALC287_FIXUP_HP_GPIO_LED → alc287_fixup_hp_gpio_led() →
alc_fixup_hp_gpio_led().
Step 5.2: TRACE CALLERS
Record:
- alc269_fixup_tbl is passed to snd_hda_pick_fixup() from the
ALC269-family probe in patch_realtek.c (around line 10471).
- alc287_fixup_hp_gpio_led is only referenced as that fixup's .v.func.
- Context: HDA codec probe (device enumeration), not IRQ/hot path.
Userspace mute then drives the LED via the registered mute LED cdev.
Step 5.3: TRACE CALLEES
Record (this tree, alc_fixup_hp_gpio_led at 4431–4449):
- alc_fixup_gpio(codec, action, mute_mask | micmute_mask)
- On PRE_PROBE, if mute_mask: set spec->gpio_mute_led_mask and
snd_hda_gen_add_mute_led_cdev(codec, gpio_mute_led_set)
- ALC287 variant uses mute_mask 0x10, micmute_mask 0
Step 5.4: FOLLOW THE CALL CHAIN
Record: PCI HDA probe → Realtek ALC269/ALC287 patch →
snd_hda_pick_fixup(SSID) → GPIO LED hook. Reachable on this laptop
whenever the HDA codec probes. Unprivileged users can toggle mute; they
cannot widen the quirk to other SSIDs.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same ALC287_FIXUP_HP_GPIO_LED already used here for 0x87c8,
0x87cb, 0x87cc, 0x87f4, 0x87f5. This tree has a long history of HP mute-
LED ID additions. Systematic, established pattern.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Local tree: pending-5.10, git describe p-5.10-2-g5aaf1e4e5aa4d, make
kernelversion 5.10.270.
- Missing ID 103c:8a0e: confirmed (no 0x8a0e, no 15-eh2xxx, no 0x8a* HP
entries at all).
- Fixup and driver: present. Without the ID, 5.10 will not enable the
mute LED on this laptop.
- Introduced: missing-ID class; hardware ~2021–2022. 5.10 still ships
this driver and already backports later Pavilion LED quirks.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Expected difficulty: minor conflicts / path remap, not rework.
- Mainline file sound/hda/codecs/realtek/alc269.c does not exist; use
sound/pci/hda/patch_realtek.c.
- Hunk context (0x8a05/0x8a06/0x8a0f) is absent. Insert one
SND_PCI_QUIRK among the 0x103c HP entries (table currently jumps
0x89aa → 0x8e1d).
- No structural conflict with ALC287_FIXUP_HP_GPIO_LED.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: 0x8a0e not present. No 15-eh2xxx/15-eh1xxx quirk. Similar
Pavilion 15-eg0xxx IDs (0x87cb/0x87cc) already backported. This ID is
new.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [sound/pci/hda Realtek codec / ALSA HDA] [IMPORTANT for laptop
audio; this change is laptop-specific, not core MM/net]
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature, still active on this 5.10 branch. Recent mute-LED quirks
continue to land (2025–2026). MAINTAINERS: SOUND — Jaroslav Kysela,
Takashi Iwai.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific / platform-specific: only HP Pavilion 15-eh2xxx
(PCI SSID 103c:8a0e). 5.10 users of that laptop (Debian 11-class LTS,
appliances, custom 5.10 images) benefit. Everyone else unchanged.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger is codec probe on that SSID, then mute/unmute. Common
for owners of that model. Unprivileged users can toggle mute; not a
security trigger.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Mute LED does not track speaker mute. Not panic/UAF/corruption.
Severity LOW–MEDIUM functionally, but this is the documented hardware-
quirk exception (broken LED on a real laptop).
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: mute LED works on this Pavilion series; matches many quirks
already accepted on this branch.
- Risk: very low (one SSID, existing fixup, author-tested, maintainer-
applied).
- Ratio: high benefit for those users vs negligible regression risk.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR backporting:
- Explicit stable exception: audio codec SND_PCI_QUIRK / hardware quirk
for an existing driver.
- One-line addition; ALC287_FIXUP_HP_GPIO_LED already in 5.10 since
a0ccbc5319d57 (v5.10 era, Cc: stable originally).
- Real hardware, author-tested; SSID 103c:8a0e confirmed on linux-
hardware.org.
- Applied by ALSA maintainer; no NAK.
- This 5.10 tree already backports the same class of HP mute-LED IDs.
AGAINST:
- Not a crash, UAF, or data-corruption fix (LED-only).
- Mainline path differs; hunk context IDs missing (trivial remap).
- Laptop postdates original 5.10 (2021–2022); still relevant because
this LTS keeps taking such quirks.
- First-time author; mitigated by maintainer apply + identical existing
fixup.
UNRESOLVED:
- lore.kernel.org/stable search 403; no confirmed stable-list thread.
- Could not confirm from this checkout whether every 15-eh2xxx SKU uses
GPIO 0x10; author test and 14-ec1xxx using the same fixup support that
choice.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — one ID, existing fixup, author
tested, maintainer applied.
2. Fixes a real bug that affects users? PASS — mute LED does not follow
mute on this laptop.
3. Important issue? PASS under the hardware-quirk exception (not a
panic). Severity: broken LED on a specific model.
4. Small and contained? PASS — +1 line.
5. No new features or APIs? PASS — enables existing GPIO LED fixup for
one SSID; no new userspace API.
6. Can apply to the local tree? PASS — equivalent table and fixup exist
in patch_realtek.c; needs path/context adjustment only.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Hardware quirk / audio codec SND_PCI_QUIRK for an existing
Realtek HDA driver. This is the category the rules call out as
appropriate for stable.
Step 9.4: MAKE YOUR DECISION
This should be backported to this 5.10.270 tree. It is a one-line PCI
quirk onto a fixup that already exists here, it fixes real mute-LED
behavior on HP Pavilion 15-eh2xxx, and it matches quirks this branch
already carries. Apply it in sound/pci/hda/patch_realtek.c's
alc269_fixup_tbl[] as:
SND_PCI_QUIRK(0x103c, 0x8a0e, "HP Pavilion Laptop 15-eh2xxx",
ALC287_FIXUP_HP_GPIO_LED),
placed among the other 0x103c HP entries (for example after 0x89aa,
before 0x8e1d).
Verification:
- [Phase 1] Parsed tags: Link msgid
20260805122907.52302-1-luca.castaldini96@gmail.com; SOB Luca
Castaldini + Takashi Iwai; no Fixes/Reported-by/Cc:stable
- [Phase 1] Body: missing 103c:8a0e; mute LED should follow speaker
mute; tested on Pavilion 15-eh2xxx ALC287
- [Phase 2] Diff: +1 SND_PCI_QUIRK in alc269_fixup_tbl;
ALC287_FIXUP_HP_GPIO_LED
- [Phase 3] git describe HEAD: p-5.10-2-g5aaf1e4e5aa4d; make
kernelversion 5.10.270; branch pending-5.10
- [Phase 3] glob: no alc269.c; equivalent sound/pci/hda/patch_realtek.c
- [Phase 3] git merge-base --is-ancestor a0ccbc5319d57 HEAD: YES (fixup
introduced 2020-11-06)
- [Phase 3] git merge-base --is-ancestor daf55a381dca9 HEAD: NO (this ID
not in 5.10 yet)
- [Phase 3] grep 0x8a0e / 15-eh2xxx / 0x8a0f: no matches in this tree
- [Phase 3] blame alc287_fixup_hp_gpio_led: a0ccbc5319d57; table already
has 0x87cb/0x87cc/0x87c8/0x87f4/0x87f5
- [Phase 3] git log --author='Luca Castaldini' -- sound/pci/hda/: empty
on this tree
- [Phase 4] b4 dig -c daf55a381dca9: msgid match; v1 only; Iwai applied
same day
- [Phase 4] b4 dig -w: tiwai, perex, linux-sound, linux-kernel
- [Phase 4] lkml.iu.edu 08604/09065: patch + "Applied to for-next"; no
NAK
- [Phase 4] linux-hardware.org probe 0510a78cfe: 103c:8a0e Pavilion
15-eh2xxx, board 8A0E
- [Phase 4] lore.kernel.org WebFetch 403; stable-list discussion
UNVERIFIED
- [Phase 5] alc269_fixup_tbl used at patch_realtek.c:10471 via
snd_hda_pick_fixup; alc_fixup_hp_gpio_led uses mute_mask 0x10
- [Phase 6] Insertion point: after 0x89aa / before 0x8e1d in
alc269_fixup_tbl; path remap required
- [Phase 6] Related 15-eh1xxx 068641bc9dc3d not in this tree and uses a
different fixup; not a dependency
- [Phase 7] SOUND maintainers Takashi Iwai / Jaroslav Kysela; this
branch already lands mute-LED quirks
- [Phase 8] Failure mode: mute LED desync, not crash; quirk exception
applies
- UNVERIFIED: GPIO 0x10 for every 15-eh2xxx SKU beyond the author's
test; no stable@ thread due to 403
The patch is a one-line hardware quirk for an existing Realtek HDA
fixup, it matches stable policy, and it applies to this 5.10 tree with
only a path/context adjustment.
**YES**
sound/hda/codecs/realtek/alc269.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 4cadbad99537a..68d5e5aa7f62d 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -6881,6 +6881,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8a05, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8a06, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8a0e, "HP Pavilion Laptop 15-eh2xxx", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8a1b, "HP 255 15.6 inch G9 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8a1f, "HP Laptop 14s-dr5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] wifi: brcmfmac: Set DMA direction for msgbuf packet IDs
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (28 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Add mute LED support for HP Pavilion 15-eh2xxx Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: hda/conexant: Add pin config quirk for Huawei Matebook Sasha Levin
` (486 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Can Peng, Arend van Spriel, Johannes Berg, Sasha Levin,
linux-wireless, brcm80211, brcm80211-dev-list.pdl, linux-kernel
From: Can Peng <pengcan@kylinos.cn>
[ Upstream commit f0ba5fd51ff23077ce66cb9be79d41a4b7c19c5e ]
brcmf_msgbuf_init_pktids() takes the DMA direction from its callers,
but never stores it in the packet ID state. Since the state is zeroed,
pktids->direction remains DMA_BIDIRECTIONAL for both the TX and RX
packet ID pools.
All msgbuf packet ID map and unmap paths use pktids->direction. As a
result, TX buffers requested with DMA_TO_DEVICE and RX buffers requested
with DMA_FROM_DEVICE are mapped and unmapped as DMA_BIDIRECTIONAL
instead.
Store the caller-provided direction when initializing the packet ID
state.
Signed-off-by: Can Peng <pengcan@kylinos.cn>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20260724092530.674624-1-pengcan@kylinos.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **5.15.221** (`pending-5.15`). The missing
`pktids->direction` store is present here, so this is a one-line DMA
correctness fix for this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[wifi / brcmfmac]** **[Set]** Store DMA direction on msgbuf
packet ID pools so TX/RX map/unmap use the caller’s direction instead of
the zeroed `DMA_BIDIRECTIONAL` default.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
From the commit text under review:
- **Acked-by:** Arend van Spriel `<arend.vanspriel@broadcom.com>`
(brcm80211 maintainer)
- **Link:**
`https://patch.msgid.link/20260724092530.674624-1-pengcan@kylinos.cn`
- **Signed-off-by:** Can Peng `<pengcan@kylinos.cn>` (author)
- **Signed-off-by:** Johannes Berg `<johannes.berg@intel.com>` (wireless
maintainer)
- No **Fixes:** / **Cc: stable** / **Reported-by** in the applied
message (expected for this review queue)
Original mailing-list submission (openwall / LKML, msgid
`20260724092530.674624-1-pengcan@kylinos.cn`) **did** include:
- `Fixes: 9a1bb60250d2 ("brcmfmac: Adding msgbuf protocol.")`
- `Cc: stable@vger.kernel.org`
Those tags were dropped when the patch was applied. That is
author/maintainer intent, not a pipeline “already selected” marker.
Decision below is still on technical merit.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
**Bug:** `brcmf_msgbuf_init_pktids()` takes `enum dma_data_direction
direction` but never writes `pktids->direction`. `pktids` is zeroed, and
`DMA_BIDIRECTIONAL == 0`.
**Symptom:** TX pools created with `DMA_TO_DEVICE` and RX pools with
`DMA_FROM_DEVICE` are mapped/unmapped as bidirectional.
**Version:** Introduced with msgbuf (2014); no version cutoff in the
message.
**Root cause:** Missing store of a parameter that every map/unmap path
already reads.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit DMA-direction
correctness fix. The unused parameter plus zeroed field is the entire
bug.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- **File:** `drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c`
- **Scope:** +1 line in `brcmf_msgbuf_init_pktids()` (`pktids->direction
= direction;`)
- **Classification:** single-file surgical fix
- Mainline hunk context uses `kzalloc_objs` / `kzalloc_obj`; this 5.15
tree uses `kcalloc` / `kzalloc`. The added line is the same.
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
**Before:** After allocating the array and `pktids`, only `array` and
`array_size` are set. `direction` stays 0.
**After:** The caller-provided direction is stored.
**Path:** Probe/init (`brcmf_proto_msgbuf_attach`), then every TX/RX
`dma_map_single` / `dma_unmap_single` via `pktids->direction`.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **Logic / DMA API correctness** (with IOMMU and cache/bounce
side effects).
Callers already pass the right direction:
```1580:1585:drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
msgbuf->tx_pktids = brcmf_msgbuf_init_pktids(NR_TX_PKTIDS,
DMA_TO_DEVICE);
if (!msgbuf->tx_pktids)
goto fail;
msgbuf->rx_pktids = brcmf_msgbuf_init_pktids(NR_RX_PKTIDS,
DMA_FROM_DEVICE);
```
Map/unmap always use `pktids->direction` (`brcmf_msgbuf_alloc_pktid`,
`brcmf_msgbuf_get_pktid`, `brcmf_msgbuf_release_array`). Verified
`DMA_BIDIRECTIONAL = 0` in `include/linux/dma-direction.h`.
Verified DMA consequences in this tree:
- **IOMMU:** `dma_info_to_prot()` maps BIDIRECTIONAL → `IOMMU_READ |
IOMMU_WRITE`, TO_DEVICE → `IOMMU_READ` only, FROM_DEVICE →
`IOMMU_WRITE` only (`drivers/iommu/dma-iommu.c`). TX SKBs currently
get device **write** permission they should not have.
- **Docs:** Networking TX must be `DMA_TO_DEVICE`, RX `DMA_FROM_DEVICE`
(`Documentation/core-api/dma-api-howto.rst`).
- **SWIOTLB / non-coherent:** direction selects bounce copy and
`arch_sync_dma_*` behavior.
Step 2.4: ASSESS THE FIX QUALITY
Record: Obviously correct: the parameter exists only to be stored. One
assignment, no API/lock/structure change. Regression risk is low: it
uses the directions the callers already requested. Using stricter TX
mapping (device read-only) is the intended, safer model.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: Buggy code from **`9a1bb60250d2`** (“brcmfmac: Adding msgbuf
protocol.”, Hante Meuleman, 2014-07-30). `git describe --contains` →
`v3.17-rc1`. Field, parameter, and missing store have been this way
since introduction. `git merge-base --is-ancestor 9a1bb60250d2b HEAD`
succeeded.
Step 3.2: FOLLOW THE FIXES: TAG
Record: Applied commit has no Fixes tag. Original submission fixes
**`9a1bb60250d2`**, which **is** in this tree. No later intermediate fix
stores `direction` (`git log --grep` on this file found none).
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Recent related commit already here: **`ddb864ea9ca2e`** (“wifi:
brcmfmac: unmap dma buffer in brcmf_msgbuf_alloc_pktid()”) — error-path
unmap, still using `pktids->direction`. Standalone; not part of a
numbered series.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Can Peng has **no** other commits in this 5.15 brcm80211
history. Arend van Spriel is the listed brcm80211 maintainer
(`MAINTAINERS`) and **Acked-by** the patch.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: No new helpers. The one-line store applies on the existing
`kcalloc`/`kzalloc` function. **Standalone.**
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record: `b4 dig -c` on this tree cannot target the mainline SHA (commit
not present). lore.kernel.org fetch returned 403. Thread recovered from:
- https://lists.openwall.net/linux-kernel/2026/07/24/732 (v1 submission)
- https://lkml.iu.edu/hypermail/linux/kernel/2608.0/00969.html (Ack)
Single revision. No NAK. Maintainer ack only.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: To: Arend van Spriel. Cc: linux-wireless, brcm80211 lists,
linux-kernel, **stable@vger.kernel.org**. Ack from the brcm80211
maintainer. Applied by Johannes Berg.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla/user crash in the message. Bug is from code
inspection (parameter never stored).
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone 1-line patch, not `N/M`.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: Author Cc’d stable on submission. Targeted
lore.kernel.org/stable search did not return a later rejection thread
(lore 403 / search noise). **UNVERIFIED:** no explicit stable-list NAK
found.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `brcmf_msgbuf_init_pktids()` only. Consumers of the field:
`brcmf_msgbuf_alloc_pktid`, `brcmf_msgbuf_get_pktid`,
`brcmf_msgbuf_release_array`.
Step 5.2: TRACE CALLERS
Record:
- Init: `brcmf_proto_msgbuf_attach()` → TX `DMA_TO_DEVICE`, RX
`DMA_FROM_DEVICE`.
- Alloc: TX from `brcmf_msgbuf_txflow`; RX from
`brcmf_msgbuf_rxbuf_data_fill` and ioctl/event buffer post.
- Get/unmap: TX status and RX complete paths.
Hot path for **PCIe** brcmfmac (`CONFIG_BRCMFMAC_PCIE` selects
`BRCMFMAC_PROTO_MSGBUF`). SDIO/USB use BCDC, not this file.
Step 5.3: TRACE CALLEES
Record: `dma_map_single` / `dma_unmap_single` with `pktids->direction`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace networking on Broadcom FullMAC **PCIe** WiFi (TX/RX).
Unprivileged traffic hits this path. Not an init-only leak.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: All four map/unmap sites in this file already use
`pktids->direction`. No second missing store.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes.** `msgbuf.c` lines 294–313 omit the store. Introduced in
v3.17, present for the entire 5.15 lifetime. `git log --grep="Set DMA
direction for msgbuf"` on this file is empty.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **Clean apply** of the one added line. Context around allocators
differs (`kcalloc` vs mainline `kzalloc_objs`); do not transplant the
mainline hunk blindly—only add `pktids->direction = direction;`.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: Only the 2022 unmap-on-alloc-failure fix (`ddb864ea9ca2e`).
Direction is still unset.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **wifi / brcmfmac msgbuf (PCIe).** **IMPORTANT** — common
laptop/embedded Broadcom FullMAC PCIe devices, not core mm/VFS.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature driver (msgbuf since 2014). File still gets targeted
fixes; this is an old latent bug, not churn from a new API.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific / config-specific:** `CONFIG_BRCMFMAC` +
`CONFIG_BRCMFMAC_PCIE` (msgbuf). Not SDIO/USB BCDC. Enabled in several
ARM/arm64 defconfigs; widely used on x86 laptops with Broadcom PCIe
WiFi.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Every TX map and RX buffer post for msgbuf. Common path.
Unprivileged traffic can trigger it. Not a rare race.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- **IOMMU:** TX buffers mapped writable to the device → expanded DMA
attack surface / isolation bug. **HIGH** (security-relevant).
- **Non-coherent / bounce DMA:** extra or wrong sync/copy vs the
documented TX/RX directions → possible packet corruption. **HIGH** if
it hits; **MEDIUM** on typical coherent x86 without IOMMU
(BIDIRECTIONAL is documented to “work” at a cost).
- No oops in the commit message. Severity still **HIGH** because DMA
permission and coherency are real user-visible classes, not style.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record: **Benefit: high** (correct DMA direction on every packet for a
common WiFi driver; tighter IOMMU perms on TX). **Risk: very low** (one
assignment of an already-passed enum). **Ratio: strongly favors
backport.**
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
**FOR:**
- Real, long-standing bug: direction parameter never stored; field stays
`DMA_BIDIRECTIONAL`.
- Code is in this 5.15 tree (`9a1bb60250d2` is an ancestor).
- One-line, obviously correct, no new API.
- IOMMU maps BIDIRECTIONAL as R+W; TX should be device-read-only.
- DMA API requires precise TX/RX directions for networking.
- Maintainer Acked-by; original submission had Fixes + Cc: stable
(dropped on apply).
- Applies here with only the one store.
**AGAINST:**
- No crash/syzbot report; driver has “worked” since 2014 on many
coherent platforms.
- Affects PCIe msgbuf only, not all brcmfmac buses.
**UNRESOLVED:**
- Could not `b4 dig` the mainline SHA (not in this checkout);
lore.kernel.org HTTP 403.
- No evidence of a stable-list rejection.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — missing store; maintainer
ack.
2. Fixes a real bug that affects users? **PASS** — wrong DMA direction
on live TX/RX.
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
IOMMU write on TX buffers; coherency/bounce mismatch.
4. Small and contained? **PASS** — +1 line, one function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — add the assignment after
`pktids->array_size = nr_array_entries;`.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/quirk/DT/docs exception. Ordinary correctness
fix.
Step 9.4: MAKE YOUR DECISION
Backport. The bug exists in 5.15, the fix is the intended store of an
existing parameter, and DMA direction is not optional cosmetics: it
controls IOMMU prot and cache/bounce behavior on a production WiFi
datapath.
What it solves for stable users: PCIe brcmfmac currently maps TX and RX
SKBs as bidirectional. That grants the device write access to TX buffers
under IOMMU and uses the wrong sync/bounce path. Storing the caller
direction restores `DMA_TO_DEVICE` / `DMA_FROM_DEVICE` as the attach
path already requests.
Risk vs benefit: one assignment vs a persistent DMA-permission/coherency
bug. No prerequisites beyond code already in this tree.
Verification:
- [Phase 1] Tags on applied commit: Acked-by Arend van Spriel, Link
msgid, SOBs Can Peng / Johannes Berg; no Fixes/Cc in applied text
- [Phase 1] Original mail: Fixes 9a1bb60250d2, Cc:
stable@vger.kernel.org (openwall 2026-07-24)
- [Phase 2] Diff: +1 line `pktids->direction = direction;` in
`brcmf_msgbuf_init_pktids`
- [Phase 2] Local `dma-direction.h`: `DMA_BIDIRECTIONAL = 0`
- [Phase 2] `dma_info_to_prot`: BIDIRECTIONAL → READ|WRITE; TO_DEVICE →
READ
- [Phase 3] `git blame`: missing store since 9a1bb60250d2 (v3.17-rc1)
- [Phase 3] `git merge-base --is-ancestor 9a1bb60250d2b HEAD`: yes
- [Phase 3] This fix not in tree (`git log --grep` empty on msgbuf.c)
- [Phase 3] Related: ddb864ea9ca2e already in tree; still uses unset
direction
- [Phase 4] b4 dig: cannot run on missing mainline SHA; lore 403
- [Phase 4] Thread: v1 only; Ack 2026-08-02; no NAK
- [Phase 5] Callers: attach + TX flow + RX/ioctl/event buffer post; PCIe
msgbuf hot path
- [Phase 6] `git describe HEAD`: p-5.15-2-g6703e5d2f3a29; `make
kernelversion`: 5.15.221
- [Phase 6] Local init still lacks the store (lines 310–313)
- [Phase 8] Failure: wrong DMA dir / IOMMU TX writable; severity HIGH
- UNVERIFIED: full lore.kernel.org thread via b4; explicit stable-list
NAK (none found)
**YES**
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 45fbcbdc7d9e4..de47d6b7e02b2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -310,6 +310,7 @@ brcmf_msgbuf_init_pktids(u32 nr_array_entries,
}
pktids->array = array;
pktids->array_size = nr_array_entries;
+ pktids->direction = direction;
return pktids;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] ALSA: hda/conexant: Add pin config quirk for Huawei Matebook
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (29 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] wifi: brcmfmac: Set DMA direction for msgbuf packet IDs Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/panel: simple: Add Kyocera tcg070wvlq panel Sasha Levin
` (485 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Zhang Heng, Takashi Iwai, Sasha Levin, perex, tiwai, linux-sound,
linux-kernel
From: Zhang Heng <zhangheng@kylinos.cn>
[ Upstream commit d152afd1cd7a69c752236b6e825c4e62a74788eb ]
The headphone jack is not detected on this Huawei Matebook (Conexant
SN6140 codec). The BIOS incorrectly marks Pin 0x18 as [N/A], causing
the driver to report hp_outs=0 and no "Headphones" output appears.
Override the pin configuration for NID 0x18 to set it as a headphone
jack, which restores proper detection and audio routing.
Link: https://github.com/thesofproject/sof/issues/10687
Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20260807125857.678297-4-zhangheng@kylinos.cn
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Local tree is **6.12.111** (`pending-6.12`). This is a Conexant SN6140
pin-config quirk for one Huawei PCI/codec SSID; the driver and SN6140
support are already here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[ALSA hda/conexant] [Add] pin config quirk for Huawei Matebook`
Subsystem: ALSA HD-audio Conexant codec. Action: add a hardware quirk
(not a feature). Intent: restore headphone jack detection on a specific
laptop whose BIOS marks the jack pin as N/A.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Link: https://github.com/thesofproject/sof/issues/10687` — user bug
report with codec dump
- `Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>` — author
- `Signed-off-by: Takashi Iwai <tiwai@suse.de>` — ALSA maintainer
applied it
- `Link:
https://patch.msgid.link/20260807125857.678297-4-zhangheng@kylinos.cn`
— lore msgid; **patch 4/4** of a series
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Cc:
stable` (absence expected for this review)
- Ignore any pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit
…]`
Notable: GitHub issue is a concrete user report, not syzbot. Maintainer
SOB is a strong quality signal.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Huawei Matebook, Conexant SN6140. BIOS marks pin NID 0x18 as
`[N/A]`.
- **Symptom:** driver reports `hp_outs=0`; no "Headphones" sink; sound
stays on internal speakers when a 3.5mm jack is plugged in.
- **Root cause:** wrong pin default so autoconfig never classifies a
headphone output.
- **Fix:** override NID 0x18 to pin config `0x03211020` (headphone
jack).
- **Version info in message:** none. GitHub issue (followed in Phase 4)
used **Debian 13, kernel 6.12.73**.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a hidden fix. It is an explicit hardware quirk for a broken
BIOS pin config. That is the documented stable exception for codec/PCI
quirks.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File in the commit: `sound/hda/codecs/conexant.c` (+9 / −0)
- Local 6.12 path: `sound/pci/hda/patch_conexant.c` (codecs had not been
moved yet)
- Functions/data: `enum { … }` last entry; `cxt_fixups[]`;
`cxt5066_fixups[]`
- Scope: single-file surgical quirk; three tiny hunks
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
1. Enum: add `CXT_FIXUP_HUAWEI_MATEBOOK_HP` after
`CXT_FIXUP_ACER_SWIFT_HP` (already the last entry in this tree at
line 309).
2. `cxt_fixups[]`: `HDA_FIXUP_PINS` table `{ 0x18, 0x03211020 }`.
3. `cxt5066_fixups[]`: `SND_PCI_QUIRK(0x19e5, 0x3289, …)` inserted after
the Lenovo vendor catch-all and before Lemote `0x1c06`.
Before: SN6140 probe hits `default:` in `patch_conexant_auto()`, picks
`cxt5066_fixups`, no Huawei entry, BIOS pin 0x18 (`0x40f001f0`,
connectivity N/A) is parsed, `hp_outs=0`.
After: SSID `19e5:3289` selects the new fixup.
`snd_hda_apply_fixup(PRE_PROBE)` calls `snd_hda_apply_pincfgs()` and
overrides pin 0x18 before `snd_hda_parse_pin_defcfg()`.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Hardware quirk / pin-config workaround (category h).** BIOS
advertises the headphone pin as unconnected. The driver then never
creates a Headphones path or jack-based speaker mute. Override is the
standard HDA fix (`HDA_FIXUP_PINS`), same pattern as Acer Swift SF314
and Lenovo IdeaPad Slim 5 already in this file.
Pin default `0x03211020` = Jack, external left, HP Out, 1/8" stereo,
black, association 2. Matches the GitHub user’s working `hda-jack-
retask` firmware.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct and minimal. Scoped to one SSID.
`SND_PCI_QUIRK_VENDOR(0x17aa, …)` cannot match Huawei `0x19e5`.
Regression risk is limited to machines that share `19e5:3289` and need a
*different* pin 0x18 role — standard quirk risk, same as other SSID
entries. No locking, no API, no extra module parameter.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: The bug is missing a table entry, not a newly introduced logic
bug. SN6140 IDs exist since `ca348e7fe1ab9` ("add a new hda codec
SN6140") — **ancestor of this HEAD**. Pin parse / `HDA_FIXUP_PINS` is
old (2011-era enum terminator still blamed on Takashi Iwai). Insertion
neighbors: Acer Swift (Feb 2026, already backported here as
`ab6a494abecb8b`), Lemote quirks from 2012.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Expected. Nothing to follow. The “bug” is a
BIOS pin default, not a kernel regression SHA.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record (this tree, `sound/pci/hda/patch_conexant.c`):
- `775911e09ec28` pin config quirk for Lenovo IdeaPad Slim 5 16AKP10
(SN6140)
- `ab6a494abecb8b` Acer Swift headphone pin tweak
- `6e1664116a9609` MECHREVO headset-mic quirk
Same class of backports already landed in 6.12.y.
Standalone vs series: submitted as **4/4**. Patches 1–3 are Realtek
`alc269.c` quirks for unrelated SSIDs. This hunk does not use any of
them.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Zhang Heng has other ALSA quirk work in this tree (Realtek +
Conexant mic-bias). Not the subsystem maintainer. Takashi Iwai applied
the patch. That is the usual path for HDA quirks.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs existing `HDA_FIXUP_PINS`, `cxt_fixups[]`,
`cxt5066_fixups[]`, SN6140 `0x14f11f87`, and `snd_hda_pick_fixup()`. All
present. Does **not** need `CXT_FIXUP_LENOVO_XPAD_ACPI` (mainline
context only). Can apply standalone with a path rename plus one-line
context fuzz on the Lenovo vendor quirk string.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 am` on msgid `20260807125857.678297-4-zhangheng@kylinos.cn`
matched the series:
https://patch.msgid.link/20260807125857.678297-1-zhangheng@kylinos.cn
- Public copies: https://lists.openwall.net/linux-kernel/2026/08/07/1129
and https://lkml.iu.edu/hypermail/linux/kernel/2608.0/13447.html
- Single revision of this series (no v2 of 4/4 in the thread `b4`
analyzed)
- `b4 dig -c` on this SHA was not possible: the commit is not in this
6.12 object graph
- No NAK in the saved series mbox. Applied by Takashi (SOB on the commit
under review)
- Lore HTTP fetch returned 403; used `b4` + openwall/lkml mirrors
instead
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 am` headers): To `tiwai@suse.com`; Cc `linux-
sound@vger.kernel.org`, `linux-kernel@vger.kernel.org`. Correct
maintainer and list. No extra Reviewed-by on the patch itself;
maintainer SOB is the review signal.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record — GitHub thesofproject/sof#10687 (closed):
- Author ciniap, 2026-04-07; **Kernel 6.12.73+deb13-amd64**, Intel Alder
Lake-P Huawei, SOF `sof-hda-generic-2ch.tplg`
- Codec dump: Node 0x18 Pin Default `0x40f001f0: [N/A]`; dmesg
`hp_outs=0`
- User fixed it with firmware pin override `{ 0x18 0x03211020 }` —
**same value as this patch**
- Impact: speakers stay on with headphones; no private listening
- Zhang Heng later commented that the upstream patch was sent
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 1/4 Acer Nitro Realtek headset mic; 2/4 Acer Gadget E10 speaker
pin; 3/4 ASUS Vivobook Realtek headset mic; 4/4 this Conexant Huawei
pincfg. Independent table rows. 4/4 does not need 1–3.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned 403. No evidence in-tree
that this Huawei SSID was already selected. Similar Conexant pin quirks
**were** already pulled into this 6.12 branch.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: No function bodies edited. Data consumed by
`snd_hda_pick_fixup()`, `__snd_hda_apply_fixup()` / `HDA_FIXUP_PINS`,
`snd_hda_apply_pincfgs()`, `patch_conexant_auto()`.
**Step 5.2: TRACE CALLERS**
Record: `patch_conexant_auto()` is the SN6140 probe
(`HDA_CODEC_ENTRY(0x14f11f87, "SN6140", patch_conexant_auto)`). Default
branch uses `cxt5066_fixups`. Probe-time only, not IRQ/hot path.
**Step 5.3: TRACE CALLEES**
Record: `snd_hda_codec_set_pincfg()` per pin; then
`snd_hda_parse_pin_defcfg()` / `snd_hda_gen_parse_auto_config()` build
Headphones and auto-mute.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace-visible on boot of that laptop (codec probe). Original
report is plugging headphones. Unprivileged user can trigger the broken
behavior; the quirk itself is not a syscall attack surface.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same file already has `CXT_FIXUP_ACER_SWIFT_HP` (`{ 0x16,
0x0321403f }`) and Lenovo Slim 5 SN6140 pincfg. Realtek uses
`0x03211020` widely for HP Out. Pattern is established.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Tree is `v6.12.111` (`pending-6.12`).
- Driver: `sound/pci/hda/patch_conexant.c`
- SN6140: `HDA_CODEC_ENTRY(0x14f11f87, "SN6140", patch_conexant_auto)`
and `is_cx11880_sn6140` for `0x14f11f87`
- No `CXT_FIXUP_HUAWEI_MATEBOOK_HP`, no `0x19e5` in this file
- Reporter’s kernel was **6.12.73** — this series
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Minor conflicts, not a rewrite.**
- Path: `sound/hda/codecs/conexant.c` → `sound/pci/hda/patch_conexant.c`
- Enum/fixup table context matches (`CXT_FIXUP_ACER_SWIFT_HP` is last)
- Quirk-table context: 6.12 still has `SND_PCI_QUIRK_VENDOR(0x17aa,
"Thinkpad", CXT_FIXUP_THINKPAD_ACPI)` vs mainline `Thinkpad/Ideapad` +
`CXT_FIXUP_LENOVO_XPAD_ACPI`. Insert still goes before
`SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", …)`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No Huawei Matebook Conexant pincfg. Acer Swift / IdeaPad Slim 5
/ MECHREVO are different SSIDs. Not a duplicate.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `sound/pci/hda` Conexant codec. **IMPORTANT** (common laptop
audio), not core mm/VFS. User-visible breakage for that hardware.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Active enough that 6.12 already received several Conexant quirks
in 2026. Mature table; this is another row, not a redesign.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific / SSID-specific: Huawei machines with PCI or
codec SSID **19e5:3289** and SN6140. `snd_hda_pick_fixup()` matches PCI
SSID first, then codec SSID, so the GitHub codec SSID `0x19e53289` is
covered even on SOF (`ehdaudio0D0`).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every boot on that SKU; 100% repro in the bug report when
plugging 3.5mm headphones. Not a race. Unprivileged user hits it by
using the jack.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Headphones not enumerated; speakers keep playing. Not an
oops/UAF. **MEDIUM** functional/hardware-enablement failure, the class
stable already takes as audio quirks. Privacy impact (cannot mute
speakers via jack) is real.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: high for that SKU (headphones/auto-mute restored); reporter
was on 6.12.
- Risk: very low (≈9 lines, one SSID, existing `HDA_FIXUP_PINS`
machinery).
- Ratio: strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real hardware bug with codec dump and 100% repro
- Reporter on **6.12.73**, this tree’s series
- Same pin value the user already verified via jack retask
- Textbook HDA pin quirk (stable exception)
- ~9 lines, no new API
- SN6140 + quirk tables already in 6.12
- Maintainer SOB (Takashi Iwai)
- Sibling Conexant pin quirks already in this branch
- Independent of series patches 1–3
AGAINST:
- Not a crash/security issue
- Path + one-line context need a trivial backport
- SSID-wide pin override could theoretically mis-configure another board
sharing `19e5:3289` (normal quirk caveat; no such report found)
UNRESOLVED:
- Full lore thread replies (`b4 mbox` failed to write the file); no NAK
found in the series mbox
- Stable list 403; no prior rejection found
- Exact Matebook marketing name beyond SSID `19e5:3289`
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — standard pincfg; user-
validated override; maintainer applied
2. Fixes a real bug that affects users? **PASS** — GitHub #10687, Debian
6.12
3. Important issue? **PASS** as hardware-enablement/quirk (headphones
dead; speakers stay on), not CRITICAL oops
4. Small and contained? **PASS** — 9 lines, one file
5. No new features or APIs? **PASS** — table entry only
6. Can apply to the local tree? **PASS** — content matches; remap path
to `patch_conexant.c`; fuzz the 17aa vendor line
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk/workaround** (HDA pin-config / PCI SSID quirk).
Also the “device ID / quirk table” class used constantly in stable
audio.
**Step 9.4: MAKE YOUR DECISION**
This belongs in this 6.12 tree. The Conexant SN6140 driver is here, the
BIOS bug is here, and the original report is this stable series.
Backport with the usual path adjustment.
Verification:
- [Phase 1] Tags: GitHub sof#10687, msgid 4/4, SOB Zhang Heng + Takashi
Iwai; no Fixes/Cc:stable
- [Phase 1] Body: BIOS pin 0x18 N/A → hp_outs=0; override 0x03211020
- [Phase 2] Diff: +9 lines, enum + `cxt_fixups` + `cxt5066_fixups`;
`HDA_FIXUP_PINS`
- [Phase 3] `git merge-base --is-ancestor ca348e7fe1ab9 HEAD` → SN6140
in tree (exit 0)
- [Phase 3] `git log` on `patch_conexant.c`: Acer Swift, IdeaPad Slim 5,
MECHREVO already backported
- [Phase 3] Series 1–3 are Realtek-only; 4/4 standalone
- [Phase 4] `b4 am` found 4-patch series; openwall/lkml copies of 4/4;
no NAK in series mbox
- [Phase 4] sof#10687: kernel 6.12.73, pin dump 0x40f001f0, working
override 0x03211020
- [Phase 4] lore.kernel.org WebFetch 403; `b4 dig -c` N/A (commit not in
this repo); `b4 mbox` traceback on output path
- [Phase 5] `patch_conexant_auto` default → `cxt5066_fixups`; PRE_PROBE
`snd_hda_apply_pincfgs`
- [Phase 5] `snd_hda_pick_fixup` matches PCI SSID then codec SSID
- [Phase 6] `git describe HEAD` → `p-6.12-3-g710455e2077bb`; Makefile
6.12.111; file `sound/pci/hda/patch_conexant.c`
- [Phase 6] No `0x19e5` / `CXT_FIXUP_HUAWEI` in local conexant driver
- [Phase 6] Enum last entry is `CXT_FIXUP_ACER_SWIFT_HP` (clean insert);
quirk insert before Lemote 0x1c06
- [Phase 8] Failure: missing Headphones + no auto-mute; severity MEDIUM;
SSID-scoped
- UNVERIFIED: complete lore reply set after maintainer apply; whether
any other SKU shares 19e5:3289 with a different pin 0x18 role
The patch is a small, SSID-scoped HDA pin quirk for a real headphone-
detection failure that was reproduced on 6.12. It matches stable’s
hardware-quirk exception and applies here with only a path remap.
**YES**
sound/hda/codecs/conexant.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/sound/hda/codecs/conexant.c b/sound/hda/codecs/conexant.c
index 56d6fbdd9b06d..ef40f1cb1158e 100644
--- a/sound/hda/codecs/conexant.c
+++ b/sound/hda/codecs/conexant.c
@@ -298,6 +298,7 @@ enum {
CXT_PINCFG_TOP_SPEAKER,
CXT_FIXUP_HP_A_U,
CXT_FIXUP_ACER_SWIFT_HP,
+ CXT_FIXUP_HUAWEI_MATEBOOK_HP,
};
/* for hda_fixup_thinkpad_acpi() */
@@ -1043,6 +1044,13 @@ static const struct hda_fixup cxt_fixups[] = {
{ }
},
},
+ [CXT_FIXUP_HUAWEI_MATEBOOK_HP] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x18, 0x03211020 }, /* Headphone */
+ { }
+ },
+ },
};
static const struct hda_quirk cxt5045_fixups[] = {
@@ -1143,6 +1151,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad/Ideapad", CXT_FIXUP_LENOVO_XPAD_ACPI),
+ SND_PCI_QUIRK(0x19e5, 0x3289, "Huawei Matebook", CXT_FIXUP_HUAWEI_MATEBOOK_HP),
SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
SND_PCI_QUIRK(0x1d05, 0x3012, "MECHREVO Wujie 15X Pro", CXT_FIXUP_HEADSET_MIC),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/panel: simple: Add Kyocera tcg070wvlq panel
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (30 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: hda/conexant: Add pin config quirk for Huawei Matebook Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.15] ACPI: FPDT: validate table and record lengths Sasha Levin
` (484 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Heiko Schocher, Neil Armstrong, Sasha Levin, maarten.lankhorst,
mripard, tzimmermann, airlied, simona, dri-devel, linux-kernel
From: Heiko Schocher <hs@nabladev.com>
[ Upstream commit 900517da69afca6f72dacf14278aee3b65275507 ]
Commit 922fb2db0287 ("dt-bindings: display: simple: Add Kyocera
tcg070wvlq panel") added the compatible string for the Kyocera
tcg070wvlq panel to the devicetree bindings documentation
(panel-simple.yaml), but the corresponding entry was not added
to the panel-simple driver.
Add the missing compatible entry to the driver.
Signed-off-by: Heiko Schocher <hs@nabladev.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://patch.msgid.link/20260721041935.757240-1-hs@nabladev.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). This
commit is a 3-line `of_device_id` addition to the existing `panel-
simple` driver. Official stable rules allow that class of change.
## Phase 1: Commit message forensics
**Step 1.1:** Record: `[drm/panel: simple] [Add] [register OF compatible
kyo,tcg070wvlq, reusing existing lg_lb070wv8 descriptor]`
**Step 1.2:** Record: tags present:
- Reviewed-by: Neil Armstrong (drm/panel maintainer)
- Signed-off-by: Heiko Schocher (author); Neil Armstrong (applied to
drm-misc)
- Link: https://patch.msgid.link/20260721041935.757240-1-hs@nabladev.com
- No Fixes:, Reported-by, Tested-by, Cc: stable, or syzbot (absence
expected)
Ignored pipeline markers: none in the provided text beyond the usual
evaluation context.
**Step 1.3:** Record:
- Bug: commit `922fb2db0287` (v5.12-rc1) documented `kyo,tcg070wvlq` in
`panel-simple.yaml` but never added the matching `of_device_id` entry.
- Symptom: a DT node whose only compatible is `kyo,tcg070wvlq` does not
bind to `panel-simple`.
- Version info: bindings since v5.12; driver entry added 2026-07-22.
- Root cause: incomplete match-table vs documented binding, not a crash
path.
**Step 1.4:** Record: Not a hidden crash/UAF/leak fix. It is hardware-ID
enablement. The 2021 bindings commit said the panel “seems to be
compatible with `lg,lb070wv8`” and added the string “only to the dt-
binding documentation to fix the checkpatch warnings.”
## Phase 2: Diff analysis
**Step 2.1:** Record: `drivers/gpu/drm/panel/panel-simple.c` +3/−0.
Function/table: `platform_of_match[]`. Scope: single-file surgical
match-table insert.
**Step 2.2:** Record: Before, `kyo,tcg070wvlq` was not in
`platform_of_match`. After, it matches and uses `&lg_lb070wv8` (same
timings/size/bus as `lg,lb070wv8`).
**Step 2.3:** Record: category **h) hardware / device ID**. Mechanism:
documented OF compatible now matches the existing panel descriptor.
**Step 2.4:** Record: Obviously correct (alias of an existing
descriptor). Minimal. Regression risk very low: in-tree `imx6dl-
prtmvt.dts` already has fallback `lg,lb070wv8` pointing at the same
data, so probe behavior is unchanged there.
## Phase 3: Git history
**Step 3.1:** Record: Missing driver ID is the gap left by
`922fb2db0287` (v5.12-rc1). `lg_lb070wv8` itself is `dd0150026901b`
(v4.2-rc1). In-tree DTS usage is `f3604ba14bd75e` (v5.12-rc1):
`compatible = "kyo,tcg070wvlq", "lg,lb070wv8"`.
**Step 3.2:** Record: No Fixes: tag. The referenced bindings commit is
an ancestor of HEAD.
**Step 3.3:** Record: Standalone; not `patch X/Y`. Nearby `panel-simple`
commits are other panel IDs, not prerequisites.
**Step 3.4:** Record: Heiko originally added `lg_lb070wv8` (2015) and
this ID (2026). Neil Armstrong reviewed and applied it. Maintainer-
acked.
**Step 3.5:** Record: Depends only on `lg_lb070wv8` and
`platform_of_match`, both present here. Applies standalone.
## Phase 4: Mailing list / external
**Step 4.1:** Record: `b4 dig` → v1 only,
https://patch.msgid.link/20260721041935.757240-1-hs@nabladev.com.
Thread: Heiko submit → Neil `Reviewed-by` → applied to drm-misc-next as
`900517da69afc`. No NAK, no stable discussion, no requested revisions.
**Step 4.2:** Record: Recipients included Neil Armstrong, Maxime Ripard,
dri-devel, DRM maintainers, original bindings author Oleksij Rempel.
**Step 4.3:** Record: No bugzilla/syzbot. Motivation is binding/driver
mismatch, not a crash report.
**Step 4.4:** Record: Single-patch series.
**Step 4.5:** Record: lore.kernel.org/stable search returned 403; no
stable-list discussion verified. LKML mirrors confirm review-only
thread.
## Phase 5: Code semantics
**Step 5.1:** Record: `platform_of_match[]` only.
**Step 5.2:** Record: Used as `.of_match_table` of
`panel_simple_platform_driver` (`panel_simple_platform_probe`). Probe
path on DT match.
**Step 5.3:** Record: Match data is existing `lg_lb070wv8` (`panel_desc`
+ LVDS timings). No new alloc/lock/API.
**Step 5.4:** Record: Reachable when a DT node uses `kyo,tcg070wvlq`.
In-tree board `imx6dl-prtmvt` already matches via fallback. Userspace
does not trigger this except by using that panel.
**Step 5.5:** Record: Same file already has `kyo,tcg121xglp` and
`lg,lb070wv8`. This is the standard panel-simple ID pattern.
## Phase 6: This checkout
**Step 6.1:** Record: Tree is 7.3.0-rc4. `panel-simple.c`,
`lg_lb070wv8`, bindings `kyo,tcg070wvlq`, and DTS fallback all exist.
Commit `900517da69afc` is already an ancestor of HEAD (merged via drm-
misc-next → drm-next before v7.3-rc1). The **match table and descriptor
this patch needs are in this tree**.
**Step 6.2:** Record: Clean apply (already applied here). Insertion sits
alphabetically between `koe,tx31d200vm0baa` and `kyo,tcg121xglp`.
**Step 6.3:** Record: No alternate fix. This *is* the driver-side
completion of the v5.12 binding.
## Phase 7: Subsystem context
**Step 7.1:** Record: `drivers/gpu/drm/panel` — **PERIPHERAL** (one LVDS
panel / Protonic MVT i.MX6 board).
**Step 7.2:** Record: `panel-simple` is mature and still gets ID
additions; this is normal hardware enablement, not a new subsystem.
## Phase 8: Impact and risk
**Step 8.1:** Record: Driver/board-specific (`CONFIG_DRM_PANEL_SIMPLE`,
DT with this compatible). Not universal.
**Step 8.2:** Record: Trigger is panel probe. Common for that one
industrial board; otherwise only if DT lists `kyo,tcg070wvlq`. Not a
syscall/security path.
**Step 8.3:** Record: Without the ID, a **primary-only**
`kyo,tcg070wvlq` node fails to bind (no display). In-tree DTS still
works via `lg,lb070wv8`. Severity **LOW** as a crash; **hardware
enablement** under the device-ID rule.
**Step 8.4:** Record: Benefit = correct match for a documented
compatible / existing panel. Risk = very low (3 lines, existing
descriptor). Ratio favors taking it: official rules explicitly allow
device IDs.
## Phase 9: Synthesis
**Evidence FOR:**
- `Documentation/process/stable-kernel-rules.rst` in this tree: “It must
either fix a real bug that bothers people **or just add a device
ID**.”
- Device-ID exception in the review criteria: ID-only change in an
existing driver.
- 3 lines, reuses `lg_lb070wv8` since v4.2, reviewed by the panel
maintainer.
- Completes a compatible documented since v5.12.
**Evidence AGAINST:**
- Not a crash, UAF, deadlock, or corruption fix.
- In-tree `imx6dl-prtmvt.dts` already falls back to `lg,lb070wv8`, so
this tree’s in-tree board already probes.
- 2021 bindings commit intentionally omitted the driver entry at first.
- No user/syzbot report.
**Unresolved:** Could not fetch lore.kernel.org/stable (403). No
evidence this was rejected for stable.
**Stable checklist:**
1. Obviously correct and tested — **PASS** (maintainer Reviewed-by,
applied to drm-misc-next)
2. Real bug that affects users — **PASS** as device ID (documented
compatible did not match); in-tree fallback means limited user-
visible delta
3. Important issue — **PASS via device-ID exception**, not via
crash/security
4. Small and contained — **PASS** (+3)
5. No new features/APIs — **PASS** (no new descriptor, timings, or uAPI;
match-table ID only)
6. Can apply to this tree — **PASS** (`lg_lb070wv8` and
`platform_of_match` present)
**Exception category:** New device ID (OF compatible) on an existing
driver.
This is not a stability fix, but it is exactly the “just add a device
ID” case the stable rules call out. Risk is negligible.
Verification:
- [Phase 1] Parsed tags: Reviewed-by Neil Armstrong; Link msgid
20260721041935.757240-1; no Fixes/syzbot
- [Phase 2] Diff: +3 in `platform_of_match[]`; `.data = &lg_lb070wv8`
- [Phase 3] `git name-rev --tags 922fb2db02871` → v5.12-rc1;
`dd0150026901b` → v4.2-rc1; `f3604ba14bd75e` DTS fallback
- [Phase 3] `git merge-base --is-ancestor 922fb2db0287 HEAD` exit 0;
`900517da69afc` ancestor of HEAD
- [Phase 4] `b4 dig -c 900517da69afc` / `-a` / `-w` / `-m`: v1 only;
Neil review + apply; dri-devel CCd
- [Phase 4] lore.kernel.org WebFetch 403; LKML mirrors used instead
- [Phase 5] `platform_of_match` →
`panel_simple_platform_driver.of_match_table`
- [Phase 6] `git describe HEAD` → v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` → 7.3.0-rc4
- [Phase 6] Grep: `kyo,tcg070wvlq` in driver, yaml, and `imx6dl-
prtmvt.dts`
- [Phase 8] Failure mode: unmatched compatible → no panel probe; in-tree
DTS still matches fallback
- [Phase 9] Read `Documentation/process/stable-kernel-rules.rst` lines
15–16: device IDs are allowed
- UNVERIFIED: stable@vger discussion (HTTP 403)
**YES**
drivers/gpu/drm/panel/panel-simple.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 878a5dc7748fb..c784f67f58fa4 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -5245,6 +5245,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "koe,tx31d200vm0baa",
.data = &koe_tx31d200vm0baa,
+ }, {
+ .compatible = "kyo,tcg070wvlq",
+ .data = &lg_lb070wv8,
}, {
.compatible = "kyo,tcg121xglp",
.data = &kyo_tcg121xglp,
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] ACPI: FPDT: validate table and record lengths
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (31 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/panel: simple: Add Kyocera tcg070wvlq panel Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] ACPI: sysfs: Properly map BERT and CCEL data to their ACPI tables Sasha Levin
` (483 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Rafael J. Wysocki, Sasha Levin, rafael, linux-acpi,
linux-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 458b40fcdd04a9a0334830de5a536d8425454e4b ]
FPDT records are supplied by firmware and are walked through
length fields stored in the table itself.
Check the main-table entry length before reading an entry, check
the mapped subtable length before remapping it, and check each
record length before saving a typed record pointer for sysfs.
This keeps malformed firmware records from being interpreted as
complete resume, suspend, or boot records when the current item
is shorter than the structure consumed by the driver.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260706094141.82438-1-pengpeng@iscas.ac.cn
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough verified history, diff, and review context to judge this
against the local 7.3-rc4 tree.
## Phase 1: Commit message forensics
**Step 1.1: Subject line**
Record: **[ACPI / FPDT] [validate] check firmware-supplied FPDT
table/record lengths before walking them or exposing typed records via
sysfs**
**Step 1.2: Tags**
Record:
- `Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>` (author)
- `Link:
https://patch.msgid.link/20260706094141.82438-1-pengpeng@iscas.ac.cn`
- `Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>` (ACPI
maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence expected here)
- Ignore any pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit
...]` markers
**Step 1.3: Body**
Record:
- **Bug:** FPDT entries/records are walked using length fields supplied
by firmware. The driver previously trusted those lengths.
- **Symptom:** A truncated/malformed record can be treated as a full
resume, suspend, or boot record. Sysfs then consumes a larger C struct
than the firmware item actually occupies.
- **Root cause:** Missing bounds checks before mapping the subtable,
before advancing the walker, and before storing typed pointers.
- **Versions:** none stated. Introduced with FPDT support, not by a
later feature.
**Step 1.4: Hidden bug fix?**
Record: Not hidden. It is an explicit firmware bounds-check plus a
signature-mismatch unmap. That is a real OOB/leak fix, not style
cleanup.
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/acpi/acpi_fpdt.c` only (`+47 / -6`)
- Functions: `fpdt_process_subtable()`, `acpi_init_fpdt()`
- Scope: single-file surgical fix
**Step 2.2: Code flow**
Record (verified against parent `458b40fcdd04a^`):
1. **Signature mismatch:** mapped header was returned without unmap →
now unmaps (fixes ioremap leak).
2. **Subtable remap:** `length` from firmware was passed to
`acpi_os_map_memory()` with no lower bound → reject if `length <
sizeof(*subtable_header)`.
3. **Record walk:** header was read and `offset +=
record_header->length` before checking remaining space; only zero
length was rejected (`a83c68a3bf7c4`) → require a full header,
`length >= sizeof(header)`, and `length <= remaining`; zero is still
rejected because `sizeof(*record_header)` is 4.
4. **Typed records:** `RECORD_S3_RESUME` / `SUSPEND` / `BOOT` stored
pointers used by sysfs (`sizeof` 24 / 20 / 48) with no size check →
reject if the firmware length is smaller than the struct.
5. **Main FPDT table:** walker did `offset += sizeof(*subtable)` with no
leftover-bytes check → reject truncated/invalid entry lengths, then
advance by `subtable->length` (spec length field).
**Step 2.3: Bug mechanism**
Record:
- **Category:** memory safety (OOB read) + resource leak
- **Mechanism:** firmware-controlled lengths were used as cursor and as
justification to treat a short blob as a full
`resume_performance_record` / `suspend_performance_record` /
`boot_performance_record`. Sysfs `*_show` helpers then read fields
past the real record. Truncated headers could also read past the
mapped subtable.
**Step 2.4: Fix quality**
Record: Obviously correct, localized, no API/feature change. Regression
risk is low. The one behavioral change is walking the main table by
`subtable->length` instead of a fixed 16-byte stride. Spec pointer
records are 16 bytes (`struct fpdt_subtable_entry` /
`acpi_fpdt_boot_pointer`). Firmware with a garbage non-zero length in an
otherwise packed 16-byte table could now skip or fail FPDT init instead
of parsing later entries; that fails closed (no FPDT sysfs), not a
kernel crash. No follow-up on this file after `458b40fcdd04a`.
## Phase 3: Git history
**Step 3.1: Blame**
Record: Buggy walker comes from `d1eb86e59be09` (“ACPI: tables:
introduce support for FPDT table”, 2021-01-29), first in **v5.12-rc1**.
Zero-length hang was later fixed by `a83c68a3bf7c4` (2023), which did
**not** check truncated non-zero lengths or typed-struct size.
**Step 3.2: Fixes: tag**
Record: none. The incomplete predecessor is `a83c68a3bf7c4` (`Fixes:
d1eb86e59be0`, `Cc: stable`). That confirms the class (malformed FPDT
firmware) is real; this commit finishes the length checks.
**Step 3.3: File history**
Record (newest first):
- `458b40fcdd04a` this commit
- `8dcb4485e7672` expose FBPT/S3PT via sysfs (already in this tree;
ancestor of the fix)
- `a83c68a3bf7c4` zero-length / invalid subtables
- `211391bf04b3c` invalid phys address
- `d1eb86e59be09` introduce driver
Standalone length-validation patch, not `N/M`.
**Step 3.4: Author**
Record: Pengpeng Hou; same period also `2c50ffdc73f3a` “ACPI: processor:
validate MADT IOAPIC entry bounds” (same firmware-table bounds pattern).
Not the ACPI maintainer; Rafael applied it.
**Step 3.5: Dependencies**
Record: No extra helpers. Needs the FPDT driver (`d1eb86e59be09`),
present here. `8dcb4485e7672` is already an ancestor (`git merge-base
--is-ancestor` succeeded). Can apply in this tree; it is already an
ancestor of HEAD.
## Phase 4: Mailing list / external
**Step 4.1:** `b4 dig -c 458b40fcdd04a` →
https://patch.msgid.link/20260706094141.82438-1-pengpeng@iscas.ac.cn
`b4 dig -a`: **v1 only**. Thread saved to mbox (2 messages).
Rafael: **“Applied as 7.3 material, thanks!”** No NAK, no requested
respin, no `Cc: stable` in review.
**Step 4.2:** `b4 dig -w` recipients: Pengpeng Hou, Rafael J. Wysocki,
Len Brown, linux-acpi, linux-kernel. Maintainer was on To/Cc and merged
it.
**Step 4.3:** No bugzilla/syzbot/Reported-by. No extra crash report
beyond the commit text. Related real hardware: `a83c68a3bf7c4` already
documented buggy FPDT BIOS tables (zero-length S3PT record, duplicated
FBPT signature).
**Step 4.4:** Not a multi-patch series.
**Step 4.5:** lore.kernel.org/stable search returned HTTP 403.
**UNVERIFIED:** whether stable@ discussed this hash.
## Phase 5: Semantic / reachability
**Step 5.1:** `fpdt_process_subtable`, `acpi_init_fpdt`.
**Step 5.2:** `acpi_init_fpdt` is `fs_initcall`; only caller of
`fpdt_process_subtable` is that init function. Boot path, not
interrupt/hot path.
**Step 5.3:** `acpi_get_table` / `acpi_os_map_memory` /
`acpi_os_unmap_memory` / `sysfs_create_group`. Records are later read by
sysfs `*_show` using `record_boot` / `record_suspend` / `record_resume`.
**Step 5.4:** Reachable when `CONFIG_ACPI_FPDT=y` and firmware publishes
FPDT. Userspace cannot craft the ACPI table on a locked-down platform;
VMs and broken BIOS can. Sysfs is the consumer of the typed pointers.
**Step 5.5:** Same pattern as the author’s MADT IOAPIC length checks.
Prior FPDT fix only handled length==0.
## Phase 6: This checkout
**Step 6.1:** `git describe HEAD` → **v7.3-rc4-27-gf0100363d8c37**.
`make kernelversion` → **7.3.0-rc4**.
`git merge-base --is-ancestor 458b40fcdd04a HEAD` → yes.
Current `drivers/acpi/acpi_fpdt.c` already contains the new checks
(lines 190–219, 223–226, 243–246, 262–265, 347–360, 374).
Buggy walker has existed in this lineage since v5.12.
**Step 6.2:** Backport difficulty **clean apply** here (already merged).
No later conflicting edits on this file.
**Step 6.3:** Related fix `a83c68a3bf7c4` is present (zero-length only).
It does not replace this patch.
## Phase 7: Subsystem
**Step 7.1:** ACPI FPDT driver under `drivers/acpi/`. **IMPORTANT**
(common x86_64/ARM64/LOONGARCH firmware table), not mm/core.
`CONFIG_ACPI_FPDT` is opt-in (`bool`, not `default y`); local `.config`
has it unset. Not staging.
**Step 7.2:** File is mature (2021–2026, few commits). This is hardening
of long-standing parse code, not a brand-new subsystem.
## Phase 8: Impact and risk
**Step 8.1:** Users who enable `CONFIG_ACPI_FPDT` on
x86_64/ARM64/LOONGARCH and whose firmware exposes FPDT. Not universal.
**Step 8.2:** Trigger is boot-time FPDT parse (`fs_initcall`) with a
malformed table. Unprivileged userspace cannot normally inject ACPI
tables; broken BIOS and untrusted VM firmware can. Real malformed FPDT
firmware is already documented.
**Step 8.3:** Failure mode:
- Read past mapped subtable → possible oops during boot
(**HIGH/CRITICAL** if it faults)
- Short record accepted → sysfs reads adjacent firmware bytes (wrong
data / info leak, **HIGH** memory-safety)
- Signature-mismatch ioremap leak at init (**LOW**, one-shot)
Severity: **HIGH** (firmware-controlled OOB on an enabled driver).
**Step 8.4:** Benefit high for FPDT-enabled systems with bad tables;
risk low (47 lines, fail closed, maintainer-acked, no revert).
## Phase 9: Synthesis
**For backporting**
- Firmware-supplied lengths used as walk cursor and as struct size:
classic OOB.
- Completes a known FPDT firmware-bug class (`a83c68a3bf7c4` already
proved bad BIOSes and was sent to stable).
- Also fixes a real `acpi_os_map_memory` leak on signature mismatch.
- Small, single-file, obviously correct; Rafael merged it.
- Driver and buggy code exist in this tree; no missing prerequisites.
**Against**
- No crash log / syzbot / `Fixes:` / explicit stable nomination.
- `CONFIG_ACPI_FPDT` is opt-in, not defconfig.
- Rafael labeled it “7.3 material,” not stable, but that is merge-window
wording, not a NAK of the bug.
- Main-table walk-by-length could hide later entries if firmware lies
about length; fail-closed.
**Unresolved**
- UNVERIFIED: stable@ thread (lore 403).
- UNVERIFIED: which distros set `CONFIG_ACPI_FPDT=y`.
**Stable rules**
1. Obviously correct and tested? **PASS** (v1 applied as-is by ACPI
maintainer; in 7.3-rc4 with no follow-up revert).
2. Real user-affecting bug? **PASS** (OOB + leak on firmware tables;
prior FPDT BIOS bugs in the wild).
3. Important (crash/security/corruption/deadlock)? **PASS** (OOB read
from firmware lengths; possible oops or sysfs leak).
4. Small/contained? **PASS** (`+47/-6`, one file).
5. No new features/APIs? **PASS**.
6. Applies to this tree? **PASS**.
**Exception category:** none required (not a device-
ID/quirk/DT/build/doc exception). It is a straightforward memory-safety
fix.
This tree is **7.3.0-rc4**. The FPDT walker has been here since v5.12,
so the bug is in this lineage. The patch is small, correct, and prevents
firmware-controlled out-of-bounds reads (and an ioremap leak) in
`acpi_init_fpdt`. That meets stable criteria for this checkout.
### Verification
- [Phase 1] Parsed tags: author SOB, Rafael SOB, msgid Link; no
Fixes/Reported-by/Cc stable
- [Phase 2] `git show 458b40fcdd04a`: +47/-6 in
`drivers/acpi/acpi_fpdt.c`; parent walker lacked remaining/size
checks; signature path leaked the map
- [Phase 2] Struct sizes: header 4, resume 24, suspend 20, boot 48,
subtable entry 16
- [Phase 3] `git blame`: checks from `458b40fcdd04a`; original walker
`d1eb86e59be09` (v5.12-rc1)
- [Phase 3] `git merge-base --is-ancestor 458b40fcdd04a HEAD` → 0
(present)
- [Phase 3] `a83c68a3bf7c4` only handled zero length; `Cc: stable` on
that older hang fix
- [Phase 3] `8dcb4485e7672` is ancestor; no later commits on this file
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 only; Rafael “Applied as 7.3
material, thanks!”; lists linux-acpi + Rafael + Len Brown
- [Phase 4] lore.kernel.org WebFetch/curl → 403; stable@ discussion
UNVERIFIED
- [Phase 5] `acpi_init_fpdt` is `fs_initcall`; only caller of
`fpdt_process_subtable`
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; current
file already has the validation
- [Phase 7] `CONFIG_ACPI_FPDT` depends on X86_64||ARM64||LOONGARCH, not
default y
- [Phase 8] Failure mode: firmware OOB on FPDT parse / sysfs typed reads
- UNVERIFIED: distro `CONFIG_ACPI_FPDT` defaults; stable@ mailing-list
history
**YES**
drivers/acpi/acpi_fpdt.c | 53 +++++++++++++++++++++++++++++++++++-----
1 file changed, 47 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/acpi_fpdt.c b/drivers/acpi/acpi_fpdt.c
index 271092f2700a1..058d1ad47699a 100644
--- a/drivers/acpi/acpi_fpdt.c
+++ b/drivers/acpi/acpi_fpdt.c
@@ -165,7 +165,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
struct fpdt_subtable_header *subtable_header;
struct fpdt_record_header *record_header;
char *signature = (subtable_type == SUBTABLE_FBPT ? "FBPT" : "S3PT");
- u32 length, offset;
+ u32 length, offset, remaining;
int result;
if (!fpdt_address_valid(address)) {
@@ -179,10 +179,17 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
if (strncmp((char *)&subtable_header->signature, signature, 4)) {
pr_info(FW_BUG "subtable signature and type mismatch!\n");
+ acpi_os_unmap_memory(subtable_header, sizeof(*subtable_header));
return -EINVAL;
}
length = subtable_header->length;
+ if (length < sizeof(*subtable_header)) {
+ pr_err(FW_BUG "Invalid FPDT subtable length %u.\n", length);
+ acpi_os_unmap_memory(subtable_header, sizeof(*subtable_header));
+ return -EINVAL;
+ }
+
acpi_os_unmap_memory(subtable_header, sizeof(*subtable_header));
subtable_header = acpi_os_map_memory(address, length);
@@ -191,17 +198,29 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
offset = sizeof(*subtable_header);
while (offset < length) {
- record_header = (void *)subtable_header + offset;
- offset += record_header->length;
+ remaining = length - offset;
+ if (remaining < sizeof(*record_header)) {
+ pr_err(FW_BUG "Truncated FPDT record header.\n");
+ result = -EINVAL;
+ goto err;
+ }
- if (!record_header->length) {
- pr_err(FW_BUG "Zero-length record found in FPTD.\n");
+ record_header = (void *)subtable_header + offset;
+ if (record_header->length < sizeof(*record_header) ||
+ record_header->length > remaining) {
+ pr_err(FW_BUG "Invalid FPDT record length %u.\n",
+ record_header->length);
result = -EINVAL;
goto err;
}
+ offset += record_header->length;
switch (record_header->type) {
case RECORD_S3_RESUME:
+ if (record_header->length < sizeof(*record_resume)) {
+ result = -EINVAL;
+ goto err;
+ }
if (subtable_type != SUBTABLE_S3PT) {
pr_err(FW_BUG "Invalid record %d for subtable %s\n",
record_header->type, signature);
@@ -218,6 +237,10 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
goto err;
break;
case RECORD_S3_SUSPEND:
+ if (record_header->length < sizeof(*record_suspend)) {
+ result = -EINVAL;
+ goto err;
+ }
if (subtable_type != SUBTABLE_S3PT) {
pr_err(FW_BUG "Invalid %d for subtable %s\n",
record_header->type, signature);
@@ -233,6 +256,10 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
goto err;
break;
case RECORD_BOOT:
+ if (record_header->length < sizeof(*record_boot)) {
+ result = -EINVAL;
+ goto err;
+ }
if (subtable_type != SUBTABLE_FBPT) {
pr_err(FW_BUG "Invalid %d for subtable %s\n",
record_header->type, signature);
@@ -289,7 +316,21 @@ static int __init acpi_init_fpdt(void)
}
while (offset < header->length) {
+ if (header->length - offset < sizeof(*subtable)) {
+ pr_err(FW_BUG "Truncated FPDT subtable entry.\n");
+ result = -EINVAL;
+ goto err_subtable;
+ }
+
subtable = (void *)header + offset;
+ if (subtable->length < sizeof(*subtable) ||
+ subtable->length > header->length - offset) {
+ pr_err(FW_BUG "Invalid FPDT subtable entry length %u.\n",
+ subtable->length);
+ result = -EINVAL;
+ goto err_subtable;
+ }
+
switch (subtable->type) {
case SUBTABLE_FBPT:
case SUBTABLE_S3PT:
@@ -302,7 +343,7 @@ static int __init acpi_init_fpdt(void)
/* Other types are reserved in ACPI 6.4 spec. */
break;
}
- offset += sizeof(*subtable);
+ offset += subtable->length;
}
return 0;
err_subtable:
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ACPI: sysfs: Properly map BERT and CCEL data to their ACPI tables
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (32 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.15] ACPI: FPDT: validate table and record lengths Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] rtc: ds1307: fix RX8130 wakeup alarm WADA bit for day-of-month mode Sasha Levin
` (482 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Thomas Renninger, Michal Suchanek, Rafael J. Wysocki, Sasha Levin,
rafael, linux-acpi, linux-kernel
From: Thomas Renninger <trenn@suse.de>
[ Upstream commit e45ee607ca6f9f97a2f97be356d844a912971a16 ]
In the case of multiple BERT ACPI tables, one gets:
sysfs: cannot create duplicate filename '/firmware/acpi/tables/data/BERT'
This is because both:
/firmware/acpi/tables/BERT1
/firmware/acpi/tables/BERT2
are attempted to be mapped to the same data table:
/firmware/acpi/tables/data/BERT
Address this problem by passing and using the same filename for data
tables.
Signed-off-by: Thomas Renninger <trenn@suse.de>
Reported-by: Michal Suchanek <msuchanek@suse.com>
Closes: https://bugzilla.suse.com/show_bug.cgi?id=1270211
[ rjw: Subject and changelog edits ]
Link: https://patch.msgid.link/20260717065129.72924-3-trenn@suse.de
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Local tree
This checkout is **mainline 7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`,
`VERSION=7 PATCHLEVEL=3 SUBLEVEL=0 EXTRAVERSION=-rc4`). The commit under
review is already an ancestor of `HEAD` as `e45ee607ca6f9`. The verdict
is whether this fix is suitable to backport, based on the code and
history in this tree.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[ACPI sysfs] [Properly map] BERT and CCEL data sysfs names to
the same instance filenames as the parent ACPI tables.** Subsystem
prefix `ACPI: sysfs:`. “Properly map” is a correctness/fix verb even
without “fix”.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected for this review pipeline)
- **Reported-by:** Michal Suchanek `<msuchanek@suse.com>` (real distro
report)
- **Closes:** `https://bugzilla.suse.com/show_bug.cgi?id=1270211`
- **Link:**
`https://patch.msgid.link/20260717065129.72924-3-trenn@suse.de` (patch
2/2 of a series)
- **Cc: stable:** absent (expected; not a negative signal)
- **Signed-off-by:** Thomas Renninger `<trenn@suse.de>` (author); Rafael
J. Wysocki `<rafael.j.wysocki@intel.com>` (ACPI maintainer)
- **[ rjw: Subject and changelog edits ]** — maintainer edited the
changelog before applying
- No Tested-by, Reviewed-by, Acked-by, or syzbot tags
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** With more than one BERT table, sysfs tries to create
`/firmware/acpi/tables/data/BERT` twice.
- **Symptom:** `sysfs: cannot create duplicate filename
'/firmware/acpi/tables/data/BERT'`. Table files are `BERT1`/`BERT2`;
data files were all named `BERT`.
- **Failure mode:** `sysfs_warn_dup()` prints that warning and calls
`dump_stack()` at boot. The second BERT (or CCEL) error region is
never exported.
- **Version info:** none in the message.
- **Root cause:** `acpi_bert_data_init` / `acpi_ccel_data_init` hard-
coded the bin-attribute name to `"BERT"` / `"CCEL"` instead of using
the instance filename already computed for the table.
Cover letter (from the lore mbox) shows real firmware with two BERT
tables:
```
ACPI: BERT ... (v01 AMD AMD BERT ...)
ACPI: BERT ... (v01 AMI AMI.BERT ...)
sysfs: cannot create duplicate filename
'/firmware/acpi/tables/data/BERT'
```
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not hidden.** This is an explicit sysfs-name collision fix. It
is not cleanup, refactor, or a new feature.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/acpi/sysfs.c` only — **+5 / −4** (9 lines).
- **Functions:** `acpi_bert_data_init`, `acpi_ccel_data_init`,
`acpi_table_data_init`, `acpi_tables_sysfs_init`.
- **Struct:** `acpi_data_attr` gains `filename[]`.
- **Scope:** single-file surgical fix.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `acpi_table_attr_init()` already builds `BERT` vs
`BERT1`/`BERT2`. `acpi_table_data_init()` then created data files with
a hard-coded `"BERT"` / `"CCEL"` name.
- **After:** `acpi_table_data_init(th, table_attr)` copies
`table_attr->filename` into `data_attr->filename` and uses that as the
sysfs name. Data nodes match table nodes (`BERT`, or `BERT1`/`BERT2`).
- **Path:** boot-time ACPI sysfs init only (`acpi_tables_sysfs_init`).
Return value of `acpi_table_data_init` is still ignored (pre-
existing).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Logic / correctness]** Hard-coded sysfs names collide when
ACPI has multiple tables of the same signature. Fix: reuse the already-
instanced filename. Same pattern for BERT and CCEL.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Quality:** obviously correct. `acpi_table_attr_init()` runs first
and fills `table_attr->filename`; then `acpi_table_data_init()` copies
it. `attr.name` points at the heap `data_attr->filename` buffer, which
lives as long as the bin attribute (same lifetime as the old string-
literal names).
- **Single-table ABI:** unchanged. Instance suffix is added only when a
second table exists (`instance > 1` or `acpi_get_table(..., 2, ...)`
succeeds), so a lone BERT still appears as
`/firmware/acpi/tables/data/BERT`.
- **Regression risk:** very low. No locking, no public API, no new sysfs
files in the common case.
- **Not introduced here:** if `sysfs_create_bin_file()` fails,
`data_attr` is still leaked (return value ignored). This patch avoids
the duplicate-name failure; it does not add that leak.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- BERT data sysfs: **`7dae6326ed764`** (“ACPI / sysfs: Extend ACPI sysfs
to provide access to boot error region”), Tony Luck, **v4.14-rc1**.
Hard-coded `"BERT"` is from that commit.
- CCEL: **`4f855dcead6c5`** (“ACPI: sysfs: Enable ACPI sysfs support for
CCEL records”), **v6.4-rc1**. Copied the same hard-coded-name pattern.
- Table instance filenames: `acpi_table_attr.filename` since
**`1c8fce27e275fd`** (v2.6.36-era sysfs) / **`3278675567dfb9`**
(ACPI_NAMESEG_SIZE rename, 2019).
- Buggy pattern has been in tree for years, not last-month code.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Introducer is `7dae6326ed764` (BERT, v4.14)
and `4f855dcead6c5` (CCEL, v6.4). Both are ancestors of this HEAD (`git
merge-base --is-ancestor` exit 0).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Immediate parent: **`f45c999e67120`** — series patch 1/2, BERT
`sizeof` check (`acpi_hest_generic_status` → `acpi_bert_region`).
Independent; this patch does not need it.
- No later commits on `drivers/acpi/sysfs.c` after `e45ee607ca6f9` (no
follow-up revert or fix).
- **Standalone** as a 2/2 series member: patch 1 is a separate size-
check fix.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Thomas Renninger is a long-time ACPI contributor (SUSE). Same-
day sibling is only the BERT sizeof patch. Merged by ACPI maintainer
Rafael J. Wysocki.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: **None required for the naming fix.** It uses existing
`table_attr->filename`, `strscpy`, and `acpi_table_attr_init`.
`kzalloc_obj` in surrounding lines is later mainline allocation API and
is **not** introduced by this diff. On older trees the same hunks apply
around `kzalloc`. `strscpy` has been in the kernel since v4.3.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig:** series at
`https://patch.msgid.link/20260717065129.72924-3-trenn@suse.de`
- Cover: `[PATCH 0/2] Fix sysfs duplicate filename if multiple BERT
tables exist`
- This commit is **[PATCH 2/2]** (msgid `...72924-3...`). Subject on the
list differed slightly from the applied subject (rjw edited it).
- **v2:** cover says previously sent to linux-pm; v2 stopped using
`acpi_get_table` inside data init and instead passes `table_attr`.
Applied version is that v2.
- **Reviewer:** Rafael: “Applied (with some modifications in
subjects/changelogs) as 7.3 material, thanks!” No NAK.
- **Stable nomination in review:** none found.
- lore.kernel.org WebFetch returned **403**; thread recovered via `b4
dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: **b4 dig -w** recipients: Thomas Renninger, `linux-
acpi@vger.kernel.org`, Saket Dumbre (Intel ACPI), Michal Suchanek
(reporter). ACPI maintainer applied it. No separate Reviewed-by.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: SUSE bugzilla 1270211 WebFetch **403** (likely login-walled).
Cover letter includes the reporter’s dmesg: two BERT tables (AMD + AMI)
and the exact sysfs duplicate warning. That is enough to treat it as a
real distro hit, not theoretical.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 2-patch series. Patch 1/2 (`f45c999e67120`) is an independent
BERT region-size check. This 2/2 patch does not depend on it.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No stable@ discussion found (lore WebFetch 403; web search did
not turn up a stable thread). **UNVERIFIED** whether anyone later asked
for or rejected it on stable@.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `acpi_bert_data_init`, `acpi_ccel_data_init`,
`acpi_table_data_init`, `acpi_tables_sysfs_init`. Struct field added on
`acpi_data_attr`.
**Step 5.2: TRACE CALLERS**
Record:
- `acpi_table_data_init` — only caller: `acpi_tables_sysfs_init`
- `acpi_tables_sysfs_init` — only caller: `acpi_sysfs_init`
(`drivers/acpi/sysfs.c`)
- `acpi_sysfs_init` — called from `acpi_bus_init()` in
`drivers/acpi/bus.c` during ACPI boot
- `acpi_sysfs_table_handler` (hot-added tables) does **not** call
`acpi_table_data_init`; BERT/CCEL data nodes are boot-only. Confirmed
with grep: only those two sites.
**Step 5.3: TRACE CALLEES**
Record: `kzalloc_obj` / `sysfs_attr_init` / `strscpy` /
`sysfs_create_bin_file` / `acpi_os_map_iomem` (read path). Init-time
sysfs creation, then userspace reads of BERT/CCEL error regions.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: ACPI boot → `acpi_bus_init` → `acpi_sysfs_init` →
`acpi_tables_sysfs_init` → per-table `acpi_table_data_init`. Triggered
on every ACPI boot that has BERT or CCEL. Userspace RAS tools read
`/sys/firmware/acpi/tables/data/`. Unprivileged users typically cannot
read these (mode `0400`). The **warning/dump_stack** happens in kernel
init regardless.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Only BERT and CCEL are in `acpi_data_objs[]`. Both had the same
hard-coded name. No other ACPI data table types in this file.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** BERT data sysfs since v4.14 (`7dae6326ed764`,
ancestor). CCEL since v6.4 (`4f855dcead6c5`, ancestor). The fix is
already applied here as `e45ee607ca6f9`. The bug is old, not introduced
after 7.3 branched.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean / minor context.** Hunks are localized. Older trees may
still use `kzalloc` instead of `kzalloc_obj` (adjacent lines only).
Pre-v6.4 trees have no CCEL function; BERT hunks still apply. `strscpy`
and `filename` on `acpi_table_attr` are present in long-term stables.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This is the fix. No earlier equivalent. No later follow-up on
this file.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM**
Record: **ACPI sysfs** (`drivers/acpi/sysfs.c`). **IMPORTANT** (not
mm/core, but ACPI boot sysfs on essentially all x86 and many ARM
servers). BERT is RAS/boot-error; CCEL is confidential-computing event
log.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature. BERT data mapping has been stable since 2017. Occasional
sysfs/BERT/CCEL fixes, not high churn.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: **Firmware-specific.** Systems with **two or more BERT** (or
CCEL) tables. Cover letter shows a real AMD + AMI dual-BERT OEM
firmware. Single-table systems are unaffected (same sysfs name as
before). CONFIG_ACPI.
**Step 8.2: TRIGGER CONDITIONS**
Record: **Every boot** on affected firmware. Not a race. Not
unprivileged-triggerable for the data read (0400), but the kernel
`dump_stack()` is automatic at init.
**Step 8.3: FAILURE MODE SEVERITY**
Record:
- `sysfs_warn_dup()` → `pr_warn` + **`dump_stack()`**
(`fs/sysfs/dir.c`). Looks like a kernel bug in dmesg; `panic_on_warn`
would panic (unverified whether any of these machines set that).
- Second BERT/CCEL error region is not in sysfs, so RAS tools can miss
boot errors.
- Boot continues; `acpi_table_data_init` return is ignored.
- **Severity: MEDIUM** (boot warning + missing diagnostic RAS data). Not
oops/corruption/deadlock, but a real distro-reported “oh, that’s not
good” bug.
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit:** medium-high for dual-BERT firmware (every boot warning
gone; both error regions exported). Zero change for the common single-
table case.
- **Risk:** very low (5 insertions / 4 deletions, init-only naming).
- **Ratio:** favorable.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**For backporting:**
- Real bug on real hardware (AMD BERT + AMI BERT), SUSE bugzilla +
dmesg.
- `dump_stack()` on every boot; second error region missing from sysfs.
- Tiny, obviously correct, ACPI-maintainer merged, v2 after review.
- Bug present since v4.14 (BERT) / v6.4 (CCEL).
- No new APIs; single-table sysfs ABI unchanged.
- Standalone; does not need series patch 1/2.
- Matches stable-kernel-rules: a real bug that bothers distro users, and
an “oh, that’s not good” sysfs warning.
**Against:**
- Not a panic, UAF, deadlock, or data-corruption bug in normal configs.
- Only dual BERT/CCEL firmware hits it (uncommon, but not fictional).
- No `Cc: stable` (not a negative signal here).
- Rafael called it “7.3 material” without mentioning stable.
**Unresolved:**
- SUSE bugzilla body (403).
- Whether stable@ ever discussed this (403 / no hits).
- Whether affected machines use `panic_on_warn`.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — naming logic is local and
matches existing instance filenames; maintainer applied v2; reporter
provided dmesg.
2. Fixes a real bug that affects users? **PASS** — distro report,
dump_stack, missing BERT data node.
3. Important issue? **PASS** (medium) — boot `dump_stack` plus
inaccessible RAS region; rules explicitly include “oh, that’s not
good” and distro-reported issues.
4. Small and contained? **PASS** — 9 lines, one file.
5. No new features or APIs? **PASS** — corrects names of existing sysfs
nodes.
6. Can apply to the local tree? **PASS** — already in this 7.3-rc4 tree;
backport to older stables is clean or BERT-only on pre-CCEL trees.
**Step 9.3: EXCEPTION CATEGORIES**
Record: None (not a device ID, quirk, DT, build, or docs patch).
Qualifies as a normal small bugfix.
**Step 9.4: DECISION**
This is a small, correct fix for a user-visible boot warning and a real
RAS sysfs hole on multi-BERT firmware. The code has been wrong since
v4.14, the patch is surgical, and the common single-table ABI is
unchanged. That meets stable criteria.
---
## What the commit solves (for stable users)
On machines whose firmware publishes **two BERT tables** (seen with AMD
+ AMI), the kernel already creates `/sys/firmware/acpi/tables/BERT1` and
`BERT2`, but both data mappings used the name `BERT`.
`sysfs_create_bin_file()` fails, `sysfs_warn_dup()` dumps a stack at
every boot, and the second boot-error region is never exposed. The same
bug exists for multiple CCEL tables. The fix copies the table’s instance
filename onto the data node.
## Risk vs benefit
Benefit is removing a boot `dump_stack` and exporting all BERT/CCEL
regions on affected firmware. Risk is negligible: init-only string copy,
no locking, no ABI change when there is only one table.
## Concerns
Older stables without CCEL need the CCEL hunk dropped; BERT hunks still
apply. Adjacent `kzalloc_obj` is not part of this patch. Series patch
1/2 is optional, not a prerequisite.
---
## Verification
- **[Phase 1]** Parsed tags: Reported-by Michal Suchanek (SUSE), Closes
bugzilla 1270211, Link patch 2/2, SOB author + Rafael; no
Fixes/stable/syzbot.
- **[Phase 2]** `git show e45ee607ca6f9`: `drivers/acpi/sysfs.c` +5/−4;
add `filename`, stop hard-coding `"BERT"`/`"CCEL"`, pass `table_attr`.
- **[Phase 2]** Read `acpi_table_attr_init` (instance suffix) and
`acpi_tables_sysfs_init` (attr_init then data_init).
- **[Phase 2]** Read `sysfs_warn_dup` in `fs/sysfs/dir.c`: `pr_warn` +
`dump_stack()`.
- **[Phase 3]** Blame: BERT data `7dae6326ed764` (v4.14-rc1), CCEL
`4f855dcead6c5` (v6.4-rc1).
- **[Phase 3]** `git merge-base --is-ancestor 7dae6326ed764 HEAD` and
`4f855dcead6c5 HEAD` and `e45ee607ca6f9 HEAD`: all 0 (present).
- **[Phase 3]** Sibling `f45c999e67120` is independent sizeof fix; no
later sysfs.c commits after this one.
- **[Phase 4]** `b4 dig -c e45ee607ca6f9`: lore thread; v2 cover +
dmesg; Rafael applied as 7.3 material; no NAK.
- **[Phase 4]** `b4 dig -w`: linux-acpi, Saket Dumbre, reporter on CC.
- **[Phase 4]** `b4 dig -m`: full mbox; WebFetch lore/bugzilla 403.
- **[Phase 5]** grep: `acpi_table_data_init` only from
`acpi_tables_sysfs_init`; `acpi_sysfs_init` from `acpi_bus_init`.
- **[Phase 6]** `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`;
`make kernelversion` → 7.3.0-rc4; buggy BERT/CCEL code in this
lineage.
- **[Phase 8]** Failure mode: boot dump_stack + missing second data
node; severity MEDIUM.
- **UNVERIFIED:** full SUSE bugzilla text; stable@ archives;
`panic_on_warn` on affected hosts.
The patch is obviously correct, fixes a real distro-reported boot
warning and missing RAS sysfs data, is nine lines in one file, and does
not add features.
**YES**
drivers/acpi/sysfs.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index e596224302f4c..d8d04437f63d6 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -316,6 +316,7 @@ struct acpi_table_attr {
struct acpi_data_attr {
struct bin_attribute attr;
u64 addr;
+ char filename[ACPI_NAMESEG_SIZE+ACPI_INST_SIZE];
};
static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
@@ -453,7 +454,6 @@ static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)
}
data_attr->addr = bert->address;
data_attr->attr.size = bert->region_length;
- data_attr->attr.attr.name = "BERT";
return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr);
}
@@ -469,7 +469,6 @@ static int acpi_ccel_data_init(void *th, struct acpi_data_attr *data_attr)
}
data_attr->addr = ccel->log_area_start_address;
data_attr->attr.size = ccel->log_area_minimum_length;
- data_attr->attr.attr.name = "CCEL";
return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr);
}
@@ -484,7 +483,7 @@ static struct acpi_data_obj {
#define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs)
-static int acpi_table_data_init(struct acpi_table_header *th)
+static int acpi_table_data_init(struct acpi_table_header *th, struct acpi_table_attr *table_attr)
{
struct acpi_data_attr *data_attr;
int i;
@@ -497,6 +496,8 @@ static int acpi_table_data_init(struct acpi_table_header *th)
sysfs_attr_init(&data_attr->attr.attr);
data_attr->attr.read = acpi_data_show;
data_attr->attr.attr.mode = 0400;
+ strscpy(data_attr->filename, table_attr->filename);
+ data_attr->attr.attr.name = data_attr->filename;
return acpi_data_objs[i].fn(th, data_attr);
}
}
@@ -543,7 +544,7 @@ static int acpi_tables_sysfs_init(void)
return ret;
}
list_add_tail(&table_attr->node, &acpi_table_attr_list);
- acpi_table_data_init(table_header);
+ acpi_table_data_init(table_header, table_attr);
}
kobject_uevent(tables_kobj, KOBJ_ADD);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] rtc: ds1307: fix RX8130 wakeup alarm WADA bit for day-of-month mode
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (33 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] ACPI: sysfs: Properly map BERT and CCEL data to their ACPI tables Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:04 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.6] wifi: iwlwifi: mvm: ignore sync frames when sync is disabled Sasha Levin
` (481 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Robert Leussler, Alexandre Belloni, Sasha Levin, linux-rtc,
linux-kernel
From: Robert Leussler <robert.leussler@leica-geosystems.com>
[ Upstream commit 878d93aaa596a861dbc8d71f7c38e62a2e805f01 ]
The RX8130 wakeup alarm never fired when set via
/sys/class/rtc/rtc0/wakealarm. The root cause is that the WADA bit
(bit 3) in the Extension register (0x1c) was never set before
programming the alarm registers.
Per the RX8130 datasheet:
WADA=0 - Week alarm: register 0x19 is compared against day-of-week
WADA=1 - Day alarm: register 0x19 is compared against day-of-month
rx8130_set_alarm() always writes a BCD day-of-month value to alarm
register 0x19, so WADA must be 1. With WADA=0 the hardware matched the
day-of-month value (e.g. 15) as a day-of-week index, which is always
out of range (valid weekdays are 0-6), so the alarm interrupt was never
asserted.
Fix by setting the WADA bit in rx8130_set_alarm() before writing the
Extension register back to the device.
This is consistent with rx8130_read_alarm(), which decodes the same
register under the same assumption (24-hour and day-of-month mode).
Signed-off-by: Robert Leussler <robert.leussler@leica-geosystems.com>
Link: https://patch.msgid.link/20260721081907.3518648-1-robert.leussler@leica-geosystems.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line RX8130 wakeup-alarm fix. The buggy `&=` is present in
this 6.12.111 tree, the datasheet matches the new polarity, and the
patch applies cleanly.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: PARSE THE SUBJECT LINE
Record: **[rtc/ds1307] [fix] RX8130 wakeup alarm never fires because
WADA is not set for day-of-month mode**
### Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none
- **Tested-by:** none (author is from Leica Geosystems; they hit this on
hardware)
- **Reviewed-by:** none
- **Acked-by:** none
- **Link:** `https://patch.msgid.link/20260721081907.3518648-1-
robert.leussler@leica-geosystems.com`
- **Cc: stable:** none (expected)
- **Signed-off-by:** Robert Leussler (author); Alexandre Belloni (RTC
maintainer). Ignore any Sasha Levin SOB if later added by the
pipeline.
### Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** RX8130 wakeup alarm never fires when set via
`/sys/class/rtc/rtc0/wakealarm`.
- **Symptom:** scheduled RTC wakeup does not occur; `/IRQ` is never
asserted.
- **Root cause:** `rx8130_set_alarm()` writes BCD day-of-month to alarm
register 0x19 but never sets WADA (Extension 0x1c bit 3). With WADA=0
the chip compares 0x19 as a week alarm.
- **Version info:** none in the message. Code has been in-tree since
RX8130 support (v4.13); the current `&=` form dates to 2019.
- **Author’s fix:** `ctl[0] &= WADA` → `ctl[0] |= WADA` so WADA=1 (day-
of-month), matching `rx8130_read_alarm()`.
### Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not hidden. Explicit hardware-logic fix. The `&=` → `|=` change
also stops wiping other Extension bits (FSEL/USEL/TE/TSEL), which is
extra correctness, not a drive-by refactor.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/rtc/rtc-ds1307.c` — **1 line changed** (`&=` → `|=`)
- Function: `rx8130_set_alarm()`
- Scope: single-file surgical fix
### Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- **Before:** after reading Extension/Flag/Control0, `ctl[0] &= BIT(3)`
keeps only the current WADA bit (typically 0 from POR) and **clears
every other Extension bit**, then writes it back, then programs
min/hour/**mday**.
- **After:** `ctl[0] |= BIT(3)` **sets WADA=1** and **preserves**
FSEL/USEL/TE/TSEL, then programs the same mday alarm.
### Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- **Category:** logic / hardware-programming correctness (wrong alarm
mode bit).
- **Mechanism:** RX8130 WADA selects week vs day comparison for register
0x19. Driver always writes `bin2bcd(tm_mday)` to 0x19, so WADA must be
1. WADA=0 makes the chip treat that BCD value as a week-alarm bitmap,
so the alarm either never matches or matches the wrong weekdays.
Verified from Epson RX8130CE application manual (Table 23):
- WADA=0 → WEEK is the alarm target
- WADA=1 → DAY (day-of-month) is the alarm target
- Example “Day” settings explicitly use WADA=1
### Step 2.4: ASSESS THE FIX QUALITY
Record:
- **Quality:** obviously correct. One operator change; polarity matches
the datasheet and the existing read path (`tm_mday`, comment “day-of-
month modes”).
- **Regression risk:** very low. Only RX8130 `set_alarm`. `|=` is the
correct RMW (old `&= BIT(3)` was also clobbering FSEL/TE/TSEL). No
API/lock/struct change.
- The author’s “valid weekdays are 0-6, so mday 15 never matches” is
slightly imprecise: week mode is a **bitmap**, so some BCD mday values
can match the wrong weekdays. Failure mode is still “alarm broken,”
possibly worse than “never fires.”
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: BLAME THE CHANGED LINES
Record:
- Buggy line `ctl[0] &= RX8130_REG_EXTENSION_WADA` introduced by
**3f929cad94338** (“rtc: ds1307: rx8130: Fix alarm handling”, Uwe
Kleine-König, 2019-01-25).
- First appeared: **v5.1-rc1**. Present in this tree (`git merge-base
--is-ancestor` succeeded).
- RX8130 support itself: **ee0981be77045** (v4.13-rc1), which used
`ctl[0] &= ~WADA` (explicitly **cleared** WADA).
### Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Historical introducer is 3f929cad94338, which is
in this tree.
That 2019 commit **intended** to “clear WADA for day-of-month,” but:
1. Its datasheet polarity was inverted vs Epson (it treated WADA=1 as
weekdays).
2. Its diff changed `&= ~WADA` to `&= WADA` (dropped `~`), which does
**not** clear WADA; it preserves WADA and zeros other Extension bits.
Original 2017 code already chose the wrong polarity for mday. The 2019
change left WADA at POR 0 and made Extension clobber worse.
### Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record (recent on this file in this tree):
- `e0e6ddc431177` rtc: ds1307: Fix off-by-one issue with wday for rx8130
— **time** wday encoding, not alarm WADA. Independent; already here.
- `204756f016726` rtc: ds1307: Fix wday settings for rx8130 — also time,
not alarm.
- `3f929cad94338` — the buggy alarm handling change.
Standalone one-line fix; not patch X/Y.
### Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Robert Leussler has no other rtc commits in this tree. Alexandre
Belloni (RTC maintainer) signed off and applied it. Weight comes from
maintainer application + hardware report, not from a regular-contributor
history.
### Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None. Diff only needs `rx8130_set_alarm()` and
`RX8130_REG_EXTENSION_WADA`, both present. `git show 878d93aaa596 | git
apply --check` **succeeded** on this tree.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 878d93aaa596` → https://patch.msgid.link/20260721081907.351
8648-1-robert.leussler@leica-geosystems.com
- `b4 dig -a`: **v1 only** (no v2/v3)
- Thread: submission (2026-07-21) → Sashiko AI note on pre-existing FLAG
RMW → author reply (2026-08-10): FLAG issue is pre-existing and out of
scope → **Alexandre Belloni: “Applied, thanks!”** (2026-08-20), no NAK
- lore.kernel.org WebFetch returned 403; thread recovered via `b4 dig
-m` and openwall/spinics
### Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc were Alexandre Belloni, linux-rtc, linux-
kernel. Maintainer applied it. No other human Reviewed-by.
### Step 4.3: SEARCH FOR THE BUG REPORT
Record: No bugzilla/syzbot. Concrete userspace trigger in the message
(`/sys/class/rtc/rtc0/wakealarm`). Author is an RX8130 user (Leica
Geosystems). Sashiko flagged a **pre-existing** write-0-to-clear FLAG
RMW (VLF); author correctly kept that separate. That does not weaken
this WADA fix.
### Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone 1/1. Not part of a multi-patch series.
### Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable WebFetch 403. No other evidence of a
stable NAK. Absence of prior stable discussion is not a negative.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: IDENTIFY KEY FUNCTIONS
Record: `rx8130_set_alarm()` only.
### Step 5.2: TRACE CALLERS
Record:
- Wired as `rx8130_rtc_ops.set_alarm` in `drivers/rtc/rtc-ds1307.c`
- RTC core: `rtc_set_alarm()` / `__rtc_set_alarm()` in
`drivers/rtc/interface.c`
- Userspace: `drivers/rtc/sysfs.c` (`wakealarm`), plus `RTC_WKALM_SET` /
`RTC_ALM_SET` ioctls
- Reachable whenever RX8130 alarm IRQ or `wakeup-source` is enabled
(chip desc has `.alarm = 1`)
### Step 5.3: TRACE CALLEES
Record: `regmap_bulk_read/write` of Extension+Flag+Control0 and alarm
min/hour/day, then optional Control0 AIE write. No alloc/locking in this
function.
### Step 5.4: FOLLOW THE CALL CHAIN
Record: `echo T > /sys/class/rtc/rtc0/wakealarm` or `rtcwake` →
`rtc_set_alarm` → `rx8130_set_alarm`. Unprivileged access depends on rtc
device node permissions; typical embedded images use this for suspend
wakeup. **Yes, userspace-reachable.**
### Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Sibling Epson/MicroCrystal chips also program WADA, with **chip-
specific polarity** (RX8010 clears WADA while writing mday;
RV8803/RV3028/RV3032 set WADA). Not a copy-paste of those; RX8130
datasheet is the authority. No second broken copy in `rtc-ds1307.c`.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
### Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Tree: **`git describe HEAD` = `p-6.12-3-gc504cf0baa3d8`**, **`make
kernelversion` = 6.12.111**
- Buggy code is here at `drivers/rtc/rtc-ds1307.c:665`: `ctl[0] &=
RX8130_REG_EXTENSION_WADA;`
- `git merge-base --is-ancestor 878d93aaa596 HEAD` → **not an ancestor**
(fix not in this tree)
- `git merge-base --is-ancestor 3f929cad94338 HEAD` → **yes** (bug is in
this tree)
- Bug introduced v5.1 (wrong `&=` form); wrong polarity since v4.13
### Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **Clean apply** (`git apply --check` exit 0). Surrounding
`rx8130_set_alarm()` matches the mainline hunk. No rework needed.
### Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: wday off-by-one (`e0e6ddc431177`) is already here and is a
different bug. No existing WADA `|=` fix.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **drivers/rtc** (Epson RX8130 in rtc-ds1307). Criticality:
**PERIPHERAL** for the kernel as a whole, **IMPORTANT** for boards that
use this RTC as the wake source.
### Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: rtc-ds1307 still gets real fixes in this tree (OSF, max clock
rate, wday). Mature driver; this is a long-standing programming error,
not churn from new code.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific / config-specific** — `CONFIG_RTC_DRV_DS1307`
+ Epson RX8130 (`epson,rx8130` / `rx8130`) with alarm/wakeup wired.
### Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Any `set_alarm` / `wakealarm` / `rtcwake` on RX8130. Common on
embedded systems that sleep and wake on RTC. Not a rare error path.
### Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- Failure: RTC alarm IRQ/`/IRQ` does not fire as intended → **system
fails to wake from suspend** at the scheduled time (or wakes on the
wrong weekday if the BCD mday happens to look like a week bitmap).
- Severity: **HIGH** for those devices (lost wakeup; device can stay
asleep). Not a KASAN/UAF/panic.
### Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** high for RX8130 users — restores the documented
alarm/wakeup path.
- **Risk:** very low — 1 line, polarity confirmed by datasheet,
maintainer applied, no locking/API change.
- **Ratio:** strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: COMPILE THE EVIDENCE
**FOR:**
- Real user-visible bug: RX8130 `wakealarm` does not work
- Datasheet-confirmed WADA polarity (0=week, 1=day)
- Driver always writes `tm_mday`; WADA must be 1
- Buggy `&=` is in this 6.12.111 tree; fix is not
- 1-line, obviously correct; apply-check clean
- RTC maintainer applied after review window; no NAK
- Also stops Extension-register clobber of FSEL/TE/TSEL
- Standalone; no prerequisites missing here
**AGAINST:**
- Not a crash/security/corruption issue
- Only RX8130, not all rtc-ds1307 chips
- No Fixes:/Cc:stable (expected; not a negative)
- No second independent reporter beyond the author
**UNRESOLVED:**
- Could not fetch lore.kernel.org or lore.kernel.org/stable (403);
thread recovered via b4/openwall
- Did not re-test on hardware (author did; commit describes
`/sys/class/rtc/rtc0/wakealarm`)
### Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — datasheet + maintainer apply
+ hardware report
2. Fixes a real bug that affects users? **PASS** — wakeup alarm broken
on RX8130
3. Important issue? **PASS** — failed RTC wakeup / wrong-day match; HIGH
for this hardware
4. Small and contained? **PASS** — 1 line, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — clean apply; buggy code
present
### Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary
contained driver bugfix.
### Step 9.4: MAKE YOUR DECISION
This 6.12.111 tree has the 2019 `&= WADA` bug. The fix is the smallest
possible correction so the chip compares day-of-month the way the driver
already programs it. That is exactly the kind of hardware bug stable
users of this RTC need.
Verification:
- [Phase 1] Parsed tags: Link to patch.msgid.link; SOBs Leussler +
Belloni; no Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: 1 line in `rx8130_set_alarm()`, `&=` → `|=` on
`RX8130_REG_EXTENSION_WADA`
- [Phase 2] Datasheet (Epson RX8130CE app manual Table 23): WADA=0 week,
WADA=1 day — matches the patch
- [Phase 3] git blame: line from 3f929cad94338 (v5.1-rc1); original
support ee0981be77045 (v4.13) used `&= ~WADA`
- [Phase 3] git show 3f929cad94338: dropped `~`, inverted polarity vs
datasheet
- [Phase 3] git merge-base --is-ancestor 3f929cad94338 HEAD: yes;
878d93aaa596 HEAD: no
- [Phase 4] b4 dig -c 878d93aaa596: lore msgid 20260721081907.3518648-1
- [Phase 4] b4 dig -a: v1 only
- [Phase 4] b4 dig -w: Belloni + linux-rtc + linux-kernel
- [Phase 4] b4 mbox: Belloni “Applied, thanks!”; Sashiko FLAG note pre-
existing, not a NAK
- [Phase 5] `rx8130_set_alarm` is `rtc_class_ops.set_alarm`; sysfs
`wakealarm` calls `rtc_set_alarm()`
- [Phase 6] git describe HEAD: p-6.12-3-gc504cf0baa3d8; kernelversion
6.12.111; line 665 still `&=`
- [Phase 6] `git apply --check` of 878d93aaa596: clean
- [Phase 8] Failure mode: RTC wakeup does not fire (or fires on wrong
weekdays); HIGH for RX8130 boards
- UNVERIFIED: live lore.kernel.org/stable HTML (HTTP 403); hardware
retest in this environment
**YES**
drivers/rtc/rtc-ds1307.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 9ba5958ca7a6e..d9a8e5045e37d 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -662,7 +662,7 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t)
if (ret < 0)
return ret;
- ctl[0] &= RX8130_REG_EXTENSION_WADA;
+ ctl[0] |= RX8130_REG_EXTENSION_WADA;
ctl[1] &= ~RX8130_REG_FLAG_AF;
ctl[2] &= ~RX8130_REG_CONTROL0_AIE;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] wifi: iwlwifi: mvm: ignore sync frames when sync is disabled
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (34 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] rtc: ds1307: fix RX8130 wakeup alarm WADA bit for day-of-month mode Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Add ALC235 support for headset mode Sasha Levin
` (480 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Emmanuel Grumbach, Miri Korenblit, Sasha Levin, linux-wireless,
linux-kernel
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
[ Upstream commit a790f60cc4d7dc64a2d7cadb94a3d9f60392bed4 ]
Gate time-sync frame interception on the active flag so frames are not
queued after time-sync teardown.
Assisted-by: GitHubCopilot:GPT-5.3-Codex
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Link: https://patch.msgid.link/20260717172958.ac73ee199a25.Ic1489244f9b02da93060f0a0e5b300a73527f265@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). This
analysis is only about that checkout: the iwlwifi MVM time-sync path
exists here, and the two-line guard is a real teardown leak/drop fix.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[iwlwifi/mvm] [ignore/gate] intercept time-sync frames only
while time-sync is active**
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Assisted-by:** GitHubCopilot:GPT-5.3-Codex
- **Signed-off-by:** Emmanuel Grumbach (author)
- **Link:** https://patch.msgid.link/20260717172958.ac73ee199a25.Ic14892
44f9b02da93060f0a0e5b300a73527f265@changeid
- **Signed-off-by:** Miri Korenblit (iwlwifi maintainer)
- **No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, or Cc:
stable** (absence is expected for this pipeline)
- Ignored: any pipeline “already selected” markers (none present beyond
a normal maintainer SOB)
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** After time-sync teardown, matching TM/FTM frames are still
intercepted and queued.
- **Symptom:** Frames sit on `frame_list` instead of going through the
normal RX/TX-status path; they are not consumed by firmware time-sync
notifications once the feature is off.
- **Version info in message:** none.
- **Root cause (from message + code):** interception is keyed only on
`peer_addr`, which is left set after disable.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: This is an explicit bug fix (not style). “Ignore … when
disabled” / “frames are not queued after teardown” is incomplete disable
handling, which produces an skb leak and dropped TM/FTM frames.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- **File:** `drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h` (+4 /
~0; copyright year + 2-line guard)
- **Function:** `iwl_mvm_time_sync_frame()`
- **Scope:** single-file surgical fix
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- **Before:** If `peer_addr` matches and the skb is a TM or FTM action
frame, queue it on `mvm->time_sync.frame_list` and return true (caller
skips `ieee80211_tx_status_skb` / `iwl_mvm_pass_packet_to_mac80211`).
- **After:** If `!mvm->time_sync.active`, return false immediately so
the frame takes the normal path.
- **Path:** RX NAPI and TX-status reclaim; not probe init.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- **Category:** logic/correctness + resource leak on teardown.
- **Mechanism:** `iwl_mvm_time_sync_config()` sets `active = (protocols
!= 0)` and purges `frame_list` when inactive, but still copies
`peer_addr`. The interceptor never consulted `active`, so after
disable it kept stealing matching frames.
- Compared with MLD: `iwl_mld_time_sync_frame()` already no-ops when
`mld->time_sync` is NULL after `iwl_mld_deinit_time_sync()`. MVM
stores time-sync in an embedded struct, so it needs the `active` flag.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: gate on the same flag config already uses.
- Minimal; no API/data-structure change.
- Regression risk is low. A remaining TOCTOU vs
`iwl_mvm_time_sync_config()` (mutex vs RX/TX softirq, no `READ_ONCE`)
is pre-existing; this closes the post-teardown window, which is the
user-visible bug.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Interceptor introduced in **c7eca79def44f** (`wifi: iwlwifi: mvm:
report hardware timestamps in RX/TX status`, Avraham Stern,
2023-03-20).
- First appeared in **v6.4-rc1** (`git describe --contains
c7eca79def44f` → `v6.4-rc1~132^2~151^2~105`).
- `struct iwl_time_sync_data { frame_list, peer_addr, active }` is from
that same commit. The bug is old, not last-month code.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No `Fixes:` tag. The incomplete disable path is
**cf85123a210fe** (`wifi: iwlwifi: mvm: support enabling and disabling
HW timestamping`, also v6.4-rc1): it stopped auto-enabling on station
add, added purge-on-disable, and removed `iwl_mvm_time_sync_sta_rm()`,
but did not gate `iwl_mvm_time_sync_frame()`.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record (on this tree, path-limited):
- `a790f60cc4d7d` — this fix
- `08e6183ed2568` — wifi action-frame struct move
- `cf85123a210fe` — enable/disable HW timestamping
- `a2f49f7d52a9e` / `c7eca79def44f` — original time-sync
Standalone. Series tag is **3/8** of an iwlwifi-next bundle; patches 1–2
and 4–8 touch other files. This hunk does not depend on them.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Emmanuel Grumbach is a long-time iwlwifi developer. Nearby July
2026 commits are other iwlwifi correctness fixes. Maintainer **Miri
Korenblit** signed off and applied it.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Needs `mvm->time_sync.active` and `iwl_mvm_time_sync_frame()`,
both present since v6.4 and in this 7.3 tree. Applies standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c a790f60cc4d7` → https://patch.msgid.link/20260717172958.ac7
3ee199a25.Ic1489244f9b02da93060f0a0e5b300a73527f265@changeid
- `b4 dig -a`: single **v1** series `[PATCH iwlwifi-next 0/8] wifi:
iwlwifi: updates - 07-17-2026`
- Cover letter: “A couple of fixes, features and cleanups.” This patch
is listed under Emmanuel’s fixes.
- Saved mbox: 9 messages (cover + 8 patches), **no review replies, NAKs,
or Cc: stable**.
- WebFetch of lore returned **403**; discussion recovered via `b4 dig
-m`.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): Miri Korenblit, Johannes Berg
(`johannes@sipsolutions.net`), linux-wireless, Emmanuel Grumbach. Right
lists/maintainers; no extra Reviewed-by on this patch. Miri’s SOB is the
maintainer merge.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by / bugzilla / syzbot. Bug is from code inspection
of teardown vs interceptor.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Mixed iwlwifi-next series. This patch only changes `mvm/time-
sync.h`. Other patches are MLD/ACPI/debug and are **not** prerequisites.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: WebSearch of lore.kernel.org/stable for this subject found
**no** discussion. UNVERIFIED beyond that search (lore HTML 403).
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `iwl_mvm_time_sync_frame()` only.
Step 5.2: TRACE CALLERS
Record:
1. `drivers/net/wireless/intel/iwlwifi/mvm/tx.c` — TX-status reclaim: if
interceptor returns true, skip `ieee80211_tx_status_skb()`.
2. `drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c` — RX: if true, skip
pass-to-mac80211.
Both are hot NAPI/TX-complete paths, but the match is rare (TM/FTM
action frames to a configured peer).
Step 5.3: TRACE CALLEES
Record: `ether_addr_equal()`, `ieee80211_is_timing_measurement()`,
`ieee80211_is_ftm()`, `skb_queue_tail()`. No alloc/locks in the inline
itself. Disable path: `iwl_mvm_time_sync_config()` under `mvm->mutex`
(from `iwl_mvm_set_hw_timestamp()` via mac80211 `set_hw_timestamp`).
Step 5.4: FOLLOW THE CALL CHAIN
Record:
- Enable/disable: userspace nl80211 `SET_HW_TIMESTAMP` →
`ieee80211_set_hw_timestamp()` → `iwl_mvm_set_hw_timestamp()` →
`iwl_mvm_time_sync_config()`.
- After disable, any later TM/FTM RX/TX for that `peer_addr` hits the
interceptor.
- Reachable from the air for RX (FTM/TM responses) once the feature was
enabled then disabled. Not a general unprivileged syscall crash path.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: MLD already treats “no time_sync object” as inactive. No second
MVM copy of this bug.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Tree: **7.3.0-rc4** (`git describe HEAD` =
`v7.3-rc4-27-gf0100363d8c37`).
- `git merge-base --is-ancestor a790f60cc4d7 HEAD` succeeded (commit is
in this lineage; expected for mainline, not used as “already
selected”).
- Pre-fix interceptor and `time_sync.active` / `peer_addr` /
`frame_list` all exist here. Bug introduced in v6.4, **not** after
this tree.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Current `time-sync.h` matches the patched form. Against the pre-
fix function (unchanged since c7eca79 except this guard), apply is
**clean**.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: Only this commit implements the `active` gate. `ead65aa2d5155`
(“send time sync only if needed”) is unrelated.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **wifi / iwlwifi MVM** (Intel wireless). **IMPORTANT** (very
common hardware), not core mm/VFS. Time-sync/HW timestamping is a
narrower slice of that driver.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: iwlwifi is actively developed (many 2026 commits). This
particular file is mature (stable since 6.4 aside from the action-frame
helper move).
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Intel iwlwifi **MVM** users who used nl80211 HW timestamping
(TM/FTM) and then disabled it, while TM/FTM frames for that peer
continue. Not universal.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Trigger: enable HW timestamp for a peer, then disable (`protocols ==
0`). `peer_addr` stays set; `active` is false; interceptor still
matched.
- Not every boot; requires that userspace API.
- After that, RX of matching FTM/TM frames from the network can keep
filling `frame_list`.
- Enable/disable typically needs netlink admin; subsequent RX leak can
be driven by frames on the air.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- Unbounded **skb leak** of intercepted frames (purge only runs on a
later inactive config).
- **Dropped** TM/FTM frames that should have gone to mac80211.
- **Missing TX status** (`ieee80211_tx_status_skb` skipped) for
intercepted TX frames.
- Not a panic, UAF, or filesystem corruption.
- **Severity: HIGH** for the leak/drop on a live packet path; feature is
uncommon so blast radius is limited.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** stops post-disable frame theft, skb leak, and missing TX
completion. Small but real.
- **Risk:** very low (2 functional lines, same flag already used in
config).
- **Ratio:** favorable for any tree that has MVM time-sync (this 7.3
tree does).
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
**FOR backporting to this tree:**
- Real teardown bug: interceptor ignored `active` while `peer_addr`
survived disable.
- Consequences: skb leak, silent TM/FTM drops, skipped TX status.
- Two-line, obviously correct guard; no new API.
- Bug in code present since v6.4; this 7.3 tree has that code.
- Author + iwlwifi maintainer SOB; sent to linux-wireless / Johannes
Berg.
- Standalone; other 3/8 series patches not required.
- MLD already has the equivalent “don’t intercept after teardown”
behavior.
**AGAINST:**
- No `Fixes:` / `Reported-by` / syzbot / stable discussion.
- Path is niche (HW timestamping), not a crash/CVE-class bug.
- Commit message is short and Copilot-assisted.
- Mixed “fixes + features” series with no extra review on this patch.
**UNRESOLVED:**
- lore HTML 403; used b4 mbox instead.
- No public user reports found.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — matches existing `active`
flag; merged by iwlwifi maintainer (no separate Tested-by).
2. Fixes a real bug that affects users? **PASS** — post-disable
intercept/leak/drop.
3. Important issue? **PASS** — unbounded skb leak and missing TX
completion on a packet path (not a panic; still user-visible).
4. Small and contained? **PASS** — one inline, +2 functional lines.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — `time_sync.active` and
callers exist; hunk is trivial.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID / quirk / DT / build / docs exception).
Ordinary small driver correctness fix.
Step 9.4: MAKE YOUR DECISION
This tree’s iwlwifi MVM time-sync stack still has the disable path that
leaves `peer_addr` set. Without the `active` check, teardown is
incomplete: TM/FTM skbs are queued forever and never get TX status or
mac80211 RX. The patch is the same check MVM config already uses and
that MLD gets via a NULL time-sync object. That is in scope for this 7.3
tree and meets stable rules.
What it solves for users of this tree: after HW timestamping is turned
off, FTM/TM frames are delivered normally instead of leaking on
`frame_list`.
Risk vs benefit: two lines vs a real leak/drop; benefit wins.
No missing prerequisites in this checkout.
Verification:
- [Phase 1] Parsed tags: Assisted-by Copilot, SOB Grumbach + Korenblit,
msgid.link; no Fixes/Reported-by/Cc stable
- [Phase 2] Diff: +2-line `if (!mvm->time_sync.active) return false;` in
`iwl_mvm_time_sync_frame()`
- [Phase 2] Confirmed disable leaves `peer_addr` set in
`iwl_mvm_time_sync_config()` (`time-sync.c` around the `active =
protocols != 0` assignment and `skb_queue_purge`)
- [Phase 3] `git blame` parent: interceptor from c7eca79def44f
(v6.4-rc1); disable redesign cf85123a210fe (v6.4-rc1)
- [Phase 3] No Fixes: tag; related history limited to `mvm/time-sync.*`
- [Phase 3] `git merge-base --is-ancestor a790f60cc4d7 HEAD` — commit is
in this 7.3 lineage
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 iwlwifi-next 3/8, no replies;
recipients Korenblit, Johannes, linux-wireless
- [Phase 4] WebFetch lore 403; stable WebSearch found no thread
- [Phase 5] Callers: `mvm/tx.c` TX status, `mvm/rxmq.c` RX; userspace
via `set_hw_timestamp`
- [Phase 5] MLD equivalent already NULL-checks `time_sync` after deinit
- [Phase 6] `git describe HEAD` = v7.3-rc4-27; `make kernelversion` =
7.3.0-rc4; feature present
- [Phase 8] Failure mode: skb leak + dropped TM/FTM + skipped TX status;
severity HIGH on that path
- UNVERIFIED: public user reports; full lore HTML thread rendering
**YES**
drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h b/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h
index 2cfd0fb5e781a..7bdbacb640787 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2026 Intel Corporation
*/
#ifndef __TIME_SYNC_H__
#define __TIME_SYNC_H__
@@ -19,6 +20,9 @@ int iwl_mvm_time_sync_config(struct iwl_mvm *mvm, const u8 *addr,
static inline
bool iwl_mvm_time_sync_frame(struct iwl_mvm *mvm, struct sk_buff *skb, u8 *addr)
{
+ if (!mvm->time_sync.active)
+ return false;
+
if (ether_addr_equal(mvm->time_sync.peer_addr, addr) &&
(ieee80211_is_timing_measurement(skb) || ieee80211_is_ftm(skb))) {
skb_queue_tail(&mvm->time_sync.frame_list, skb);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Add ALC235 support for headset mode
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (35 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.6] wifi: iwlwifi: mvm: ignore sync frames when sync is disabled Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] drm/amdgpu/gfx11: WARN() rather than BUG() for invalid SDMA engine Sasha Levin
` (479 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Zeyu Li, Takashi Iwai, Sasha Levin, perex, tiwai, linux-sound,
linux-kernel
From: Zeyu Li <13776528859@163.com>
[ Upstream commit 9ee4266827cfb67b9fbb89136ea6a8f3d7809f5c ]
The ALC235 (0x10ec0235) is registered as the ALC255 codec variant in
patch_alc269(), but the headset mode functions were missing a case
for it, so the CTIA/OMTP jack type detection and routing never ran
on this codec. As a result, a plugged-in headset is detected (jack
presence works) but the microphone signal is never routed, leaving
the capture stream permanently silent.
Verified on an ASUS M5451GA laptop (HDA:10ec0235,10431814): with the
ALC255 coef sequence applied, the headset microphone works correctly.
Signed-off-by: Zeyu Li <13776528859@163.com>
Link: https://patch.msgid.link/20260926140336.27896-1-13776528859@163.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
Record: **[ALSA/hda/realtek] [Add] Add ALC235 support for headset mode**
The verb is “Add”, but the body is a missing-ID fix: ALC235 is already
treated as an ALC255 variant, and the headset-mode switches never
included it.
**Step 1.2 — Tags**
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none
- **Tested-by:** none (author states hardware verification in the body)
- **Reviewed-by / Acked-by:** none on the commit
- **Link:**
https://patch.msgid.link/20260926140336.27896-1-13776528859@163.com
- **Cc: stable:** none (expected)
- **Signed-off-by:** Zeyu Li (author); Takashi Iwai (ALSA maintainer)
- Pipeline tags ignored: `[Upstream commit ...]`, `Signed-off-by: Sasha
Levin`
**Step 1.3 — Body**
Record:
- **Bug:** ALC235 (`0x10ec0235`) is classified as `ALC269_TYPE_ALC255`
in `patch_alc269()`, but the six headset-mode helpers omit that vendor
ID.
- **Symptom:** combo-jack presence works; headset capture stays silent
because CTIA/OMTP detection and mic routing never run.
- **Root cause:** `switch (codec->core.vendor_id)` falls through with no
match, so `alc_process_coef_fw(codec, coef0255)` is never applied.
- **Verification:** ASUS M5451GA (`HDA:10ec0235,10431814`); ALC255 coef
sequence restores headset mic.
- **Version info:** none in the message. Codec ID has been in-tree since
2014.
**Step 1.4 — Hidden bug fix?**
Record: Not hidden. This is a hardware-routing bug written as “Add
support”. It does not add a driver or API; it fills in a missing vendor-
ID case in existing tables.
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
Record:
- **File:** `sound/hda/codecs/realtek/realtek.c` — **+6 / −0**
- **Functions:** `alc_headset_mode_unplugged`,
`alc_headset_mode_mic_in`, `alc_headset_mode_default`,
`alc_headset_mode_ctia`, `alc_headset_mode_omtp`,
`alc_determine_headset_type`
- **Scope:** single-file, surgical. One `case 0x10ec0235:` added
immediately above each existing `case 0x10ec0255:`.
**Step 2.2 — Flow change**
Record: Before, those switches did nothing for vendor `0x10ec0235`.
After, ALC235 uses the same ALC255 coefficient firmware already used for
`0x10ec0255` (unplug, mic-in, default headphone, CTIA, OMTP, and type-
detect).
Author-reported working values `COEF 0x45=0xd489`, `0x1b=0x0c2b` match
`alc_headset_mode_ctia()`’s `coef0255` exactly.
**Step 2.3 — Bug mechanism**
Record: **Hardware workaround / missing codec ID** in existing headset-
mode tables. Without the case, jack detect still works via generic HP
automute, but combo-jack mic routing never happens.
**Step 2.4 — Fix quality**
Record: Minimal and obviously correct given that `patch_alc269()`
already maps ALC235 → ALC255. Regression risk is low: the new cases only
run when headset-mode hooks are installed (`alc_fixup_headset_mode` /
`alc_probe_headset_mode`). Realtek confirmed compatibility (Phase 4).
Residual incompleteness: `alc255_set_default_jack_type()` still has only
`0x10ec0255`; the author still got a working headset mic without that
extra case.
## Phase 3: Git history
**Step 3.1 — Blame**
Record:
- Headset-mode switches (minus the new case) come from the 6.16-era
Realtek split `aeeb85f26c3bb` (2025-07-11), itself a move of older
`patch_realtek.c` logic.
- ALC235 vendor ID added in `92f974df34601` (2014-06-06, Kailang Yang):
“New vendor ID for ALC233 … compatible with ALC255. It is use for
Lenovo.”
- Variant assignment added in `ea04a1dbf8b1d` (2018-04-25, Kailang Yang,
already sent to stable). Maintainer note then: *“the chip is 10ec:0235
bonding for ALC233b, which is equivalent with ALC255. It's only used
for Lenovo. The chip needs no alc_process_coef_fw() for headset unlike
ALC255.”*
That 2018 note is why the ID was classified as ALC255 but
**intentionally omitted** from headset coef switches. The 2026 report is
an ASUS machine, not Lenovo, and Realtek later said the ALC255 sequence
is compatible.
**Step 3.2 — Fixes tag**
Record: No `Fixes:` tag. The incomplete classification dates to
`ea04a1dbf8b1d` (2018), which is in this tree.
**Step 3.3 — File history**
Record: Recent `realtek.c` / `alc269.c` history is the usual stream of
laptop quirks. No prerequisite refactor is required. Not a `patch X/Y`
series.
**Step 3.4 — Author**
Record: Zeyu Li has no other Realtek commits in this tree. This is a
user-reported hardware fix reviewed by the ALSA maintainer and a Realtek
engineer, not a maintainer-authored cleanup.
**Step 3.5 — Dependencies**
Record: Standalone. It only adds a `case` next to an existing
`0x10ec0255` arm. Those functions and `coef0255` already exist here. No
new helpers.
## Phase 4: Mailing list / external research
**Step 4.1 — Original discussion**
Record:
- Lore/msgid:
https://patch.msgid.link/20260926140336.27896-1-13776528859@163.com
- `b4 dig -c 9ee4266827cfb67b9fbb89136ea6a8f3d7809f5c` matched that
thread.
- Revisions: same patch sent twice (lkml + linux-sound). No v2/v3 code
change.
- Takashi Iwai (28 Sep 2026): *“I'm not sure whether it's 100% safe…
Kailang, could you check it? Can ALC235 be fully compatible in this
manner?”*
- Author follow-up: jack sense and VREF were already correct; capture
stayed silent until ALC255 CTIA coefs were applied.
- **Kailang Yang, Realtek (1 Oct 2026): “Yes, it's compatible.”**
- Takashi then applied the patch. No NAK.
**Step 4.2 — Recipients (`b4 dig -w`)**
Record: Zeyu Li; linux-sound; Takashi Iwai; Jaroslav Kysela. Realtek
(Kailang) was added during review.
**Step 4.3 — Bug report**
Record: Reporter is the author, on a specific ASUS laptop. One machine,
but a concrete silent-mic failure with before/after coefs. No
syzbot/bugzilla.
**Step 4.4 — Series**
Record: Standalone single patch. No sibling commits required.
**Step 4.5 — Stable list**
Record: **UNVERIFIED** — lore.kernel.org/stable returned HTTP 403. No
other evidence it was rejected for stable.
## Phase 5: Code semantic analysis
**Step 5.1 — Functions**
Record: the six headset-mode helpers listed in 2.1. They are called only
from `alc_update_headset_mode()`.
**Step 5.2 — Callers**
Record:
- `alc_update_headset_mode()` ← `alc_update_headset_mode_hook` (capture
mux), `alc_update_headset_jack_cb` (HP jack), `alc_fixup_headset_mode`
INIT, `alc_probe_headset_mode` (installs the hooks).
- Those hooks are installed only when a headset-mode fixup is active
(`ALC255_FIXUP_HEADSET_MODE`, `model=alc255-asus`, etc.).
- This tree has **no** PCI/pin quirk for ASUS `1043:1814`. Existing
ALC235 pin quirks are Lenovo-only and do **not** enable headset mode.
The author’s box therefore needed a headset-mode fixup or `model=` to
hit this path. The commit still fixes every ALC235 device that already
uses that path.
**Step 5.3 — Callees**
Record: `alc_process_coef_fw`, `alc_write_coef_idx`,
`alc_read_coef_idx`, `snd_hda_set_pin_ctl_cache`. Codec coefficient
writes plus pin VREF. No locking/alloc/API changes.
**Step 5.4 — Reachability**
Record: Userspace-reachable: plug a headset and select the headset-mic
input on a machine whose quirk/model enables headset mode. Unprivileged
audio use; not a syscall crash path.
**Step 5.5 — Similar patterns**
Record: Same table already groups sibling IDs
(`0x10ec0230`/`0236`/`0256`, `0x10ec0234`/`0274`/`0294`). Adding `0235`
next to `0255` matches that pattern. The only remaining
`0x10ec0255`-only switch is `alc255_set_default_jack_type()` in
`alc269.c`.
## Phase 6: This tree (6.18.y)
**Step 6.1 — Does the bug exist here?**
Record: **Yes.** Local tree is **6.18.57** (`git describe`:
`v6.18.57-155-gcdf239ca885b2`; Makefile `VERSION=6 PATCHLEVEL=18
SUBLEVEL=57`).
Without this change (parent of the candidate):
- `patch_alc269()` already has `case 0x10ec0235:` → `ALC269_TYPE_ALC255`
- Headset-mode switches have only `case 0x10ec0255:`
- File path is already `sound/hda/codecs/realtek/realtek.c` (split
commit is an ancestor)
The codec has been present since 2014; the ALC255 classification since
2018. This is not post-6.18 hardware enablement of a new driver.
**Step 6.2 — Backport difficulty**
Record: **Clean apply.** Same file, same six switches, same neighboring
`0x10ec0255` cases. No structural conflict.
**Step 6.3 — Related fixes already here?**
Record: No other ALC235 headset-mode fix. No follow-up on `realtek.c`
after this candidate that would supersede it.
## Phase 7: Subsystem context
**Step 7.1**
Record: **ALSA HD-audio / Realtek codec.** Criticality: **IMPORTANT**
(common laptop audio), not core mm/VFS. Realtek HDA is the default codec
path on a large fraction of x86 laptops.
**Step 7.2**
Record: Very active (many recent laptop quirks). That is normal for this
file and is why codec-ID / quirk additions are routinely taken into
stable.
## Phase 8: Impact and risk
**Step 8.1 — Who is affected**
Record: Users of Realtek ALC235 (`CONFIG_SND_HDA_CODEC_REALTEK`) whose
machine enables headset mode (quirk or `model=`). Confirmed hardware:
ASUS M5451GA. Older Lenovo ALC235 boxes use other pin quirks and do not
enter these switches.
**Step 8.2 — Trigger**
Record: Plug a CTIA/OMTP headset and use the headset mic. Common laptop
action. Unprivileged.
**Step 8.3 — Failure mode**
Record: Headset playback/jack detect works; **headset microphone capture
is permanently silent**. Severity: **HIGH** for affected laptops (broken
input device), not a panic/UAF. This is the standard “audio hardware
quirk” class.
**Step 8.4 — Risk vs benefit**
Record:
- **Benefit:** restores headset mic on ALC235 machines that already go
through headset mode; Realtek-confirmed; hardware-tested.
- **Risk:** very low (6 fallthrough cases, existing coef table).
Theoretical risk to old Lenovo ALC233b bonding is mitigated by (a)
those quirks not enabling headset mode, and (b) Kailang’s 2026
“compatible” ack.
- **Ratio:** favorable.
## Phase 9: Synthesis
**Step 9.1 — Evidence**
For:
- Real user-visible bug (silent headset mic) on identified hardware
- 6-line vendor-ID addition to an existing driver table (hardware-quirk
exception)
- Codec already present and classified as ALC255 in this 6.18 tree
- Applies cleanly; no new API; standalone
- Tested by the author; ALSA maintainer applied it after Realtek
confirmation
- Same pattern as other Realtek headset vendor-ID additions that stable
accepts
Against:
- Subject reads like a feature (“Add support”)
- 2018 Realtek note said this bonding originally needed **no** headset
`alc_process_coef_fw()` (Lenovo-only)
- No machine-specific quirk for `1043:1814` in this tree, so the ASUS
laptop may still need `model=alc255-asus` (or a later quirk) for the
new cases to run
- `alc255_set_default_jack_type()` still omits ALC235
Unresolved:
- Stable-list discussion (lore 403)
The “against” items do not outweigh the fix. The 2018 note is superseded
by the same Realtek engineer in 2026. Missing `model=`/quirk is a
separate enablement issue; this commit is still the required routing fix
once headset mode is on. Incomplete default-jack-type setup did not
prevent the reported fix from working.
**Step 9.2 — Stable rules**
1. Obviously correct and tested? **PASS** — fallthrough onto the
existing ALC255 path; hardware + Realtek + maintainer.
2. Real bug affecting users? **PASS** — silent headset capture.
3. Important? **PASS** — broken headset mic on laptop HDA; hardware-
quirk class.
4. Small and contained? **PASS** — +6 lines, one file.
5. No new features/APIs? **PASS** — missing ID in existing tables, not a
new driver.
6. Applies to this 6.18 tree? **PASS** — same file and switches.
**Step 9.3 — Exception**
Record: **Hardware quirk / missing codec ID** in an existing Realtek HDA
driver. This is an allowed stable exception.
**Step 9.4 — Decision**
This tree is 6.18.y. The buggy omission exists here. The patch is the
standard Realtek headset-ID fix, confirmed by Realtek, and is
appropriate for this stable tree.
## What this means for 6.18 users
ALC235 has been registered for years and is already treated as ALC255,
but the headset-mode coefficient path never ran. On machines that use
that path, a plugged headset is detected and the mic stays silent.
Adding `0x10ec0235` beside `0x10ec0255` is a 6-line, already-tested
hardware quirk with no API change and a clean apply on this tree.
## Verification
- [Phase 1] Parsed tags: Link to msgid `20260926140336.27896-1`; SOBs
Zeyu Li + Takashi Iwai; no Fixes/Reported-by/Cc-stable
- [Phase 2] Diff: +6 `case 0x10ec0235:` lines in six headset-mode
functions in `sound/hda/codecs/realtek/realtek.c`
- [Phase 2] `coef0255` in `alc_headset_mode_ctia()` is `WRITE_COEF(0x45,
0xd489)` + `WRITE_COEF(0x1b, 0x0c2b)`, matching the author’s test
- [Phase 3] `git describe HEAD` / `make kernelversion`: **6.18.57**
- [Phase 3] `git show 92f974df34601`: ALC235 ID added 2014 as
ALC233/ALC255-compatible
- [Phase 3] `git show ea04a1dbf8b1d`: 2018 variant assignment + note
that headset coefs were then thought unnecessary
- [Phase 3] Parent of candidate: headset switches have `0x10ec0255`
only; `patch_alc269()` already has `0x10ec0235` → `ALC269_TYPE_ALC255`
- [Phase 3] `git log --author="Zeyu Li"`: only this commit in-tree
- [Phase 4] `b4 dig -c 9ee4266827cfb…`: thread at
patch.msgid.link/20260926140336.27896-1
- [Phase 4] `b4 dig -a`: same patch, no later revision
- [Phase 4] `b4 dig -w`: linux-sound, Takashi Iwai, Jaroslav Kysela
- [Phase 4] mbox: Takashi asked Realtek; Kailang: “Yes, it's
compatible.”; Takashi applied
- [Phase 5] Callers of the six functions are only
`alc_update_headset_mode()`; that is wired only by headset-mode fixups
- [Phase 5] No `1043:1814` / M5451 quirk in `alc269.c`; ASUS pin quirks
match `0x10ec0255` only
- [Phase 6] File and buggy switches exist in this 6.18 checkout; Realtek
split `aeeb85f26c3bb` is an ancestor
- [Phase 6] Expected apply: clean
- [Phase 8] Failure mode: silent headset mic, severity HIGH for affected
laptops
- UNVERIFIED: lore.kernel.org/stable search (HTTP 403)
The patch is a small, tested hardware-quirk fix for a real silent-mic
bug that exists in this 6.18 tree.
**YES**
sound/hda/codecs/realtek/realtek.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/sound/hda/codecs/realtek/realtek.c b/sound/hda/codecs/realtek/realtek.c
index ca377a5adadb5..a1529650950d8 100644
--- a/sound/hda/codecs/realtek/realtek.c
+++ b/sound/hda/codecs/realtek/realtek.c
@@ -1305,6 +1305,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
}
switch (codec->core.vendor_id) {
+ case 0x10ec0235:
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
@@ -1420,6 +1421,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
};
switch (codec->core.vendor_id) {
+ case 0x10ec0235:
case 0x10ec0255:
alc_write_coef_idx(codec, 0x45, 0xc489);
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
@@ -1575,6 +1577,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
alc_process_coef_fw(codec, coef0225);
alc_hp_enable_unmute(codec, 75);
break;
+ case 0x10ec0235:
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
@@ -1676,6 +1679,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
};
switch (codec->core.vendor_id) {
+ case 0x10ec0235:
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
@@ -1793,6 +1797,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
};
switch (codec->core.vendor_id) {
+ case 0x10ec0235:
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
break;
@@ -1894,6 +1899,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
}
switch (codec->core.vendor_id) {
+ case 0x10ec0235:
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
msleep(300);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] drm/amdgpu/gfx11: WARN() rather than BUG() for invalid SDMA engine
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (36 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Add ALC235 support for headset mode Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] selftests/ftrace: Force C locale in ftracetest Sasha Levin
` (478 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Alex Deucher, Kent Russell, Sasha Levin, Felix.Kuehling,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Alex Deucher <alexander.deucher@amd.com>
[ Upstream commit c24edbd5ae0e4f24e0179e8c9f22a867016177bb ]
There's no need to crash the kernel for these cases.
Reviewed-by: Kent Russell <kent.russell@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough context: this is a three-line `BUG()`-to-`WARN()` change
on the GFX11 KFD SDMA path, already present in this 7.3-rc4 tree. The
remaining question is whether it is a real panic-prevention fix worth
keeping in stable.
## Phase 1: Commit message forensics
**Step 1.1: Subject line**
Record: `[drm/amdgpu/gfx11]` `[WARN() rather than BUG()]` `[stop
panicking on an invalid SDMA engine id in get_sdma_rlc_reg_offset()]`
**Step 1.2: Tags**
Record:
- `Reviewed-by: Kent Russell <kent.russell@amd.com>` (AMD GPU developer)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (amdgpu
maintainer; ignore any Sasha Levin SOB)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Link:`, or `Cc: stable`
(absence expected)
**Step 1.3: Body**
Record: Body is one sentence: “There's no need to crash the kernel for
these cases.” No stack trace, no reproducer, no version range. Failure
mode claimed: kernel crash via `BUG()`. Root cause as stated: invalid
`engine_id` in `get_sdma_rlc_reg_offset()` was treated as fatal.
**Step 1.4: Hidden bug fix?**
Record: Not hidden. It is an explicit panic-to-warning conversion. It is
also patch `15/43` of Alex Deucher’s amdgpu `BUG()`-removal series
(later resent as `02/30`). Same boilerplate appears on sibling
gfx12/gfx12.1 patches. That is hardening of a driver `BUG()`, not a
style-only rename.
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record: One file, `drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c`.
Function: `get_sdma_rlc_reg_offset()`. Scope: +2/−1, single-file
surgical change.
**Step 2.2: Code flow**
Record: Before: `switch (engine_id)` handles 0 and 1; `default:` calls
`BUG()` and never returns. After: `WARN(1, "Invalid SDMA engine id
%d\n", engine_id); break;` then the function still computes
`sdma_rlc_reg_offset` from `sdma_engine_reg_base` (initialized to 0) and
returns. Affected path: invalid engine id on SDMA queue
load/dump/occupy/destroy.
**Step 2.3: Bug mechanism**
Record: Category **(g) logic / correctness** plus crash hardening.
`BUG()` is a kernel panic (unless `CONFIG_BUG` is off). The fix stops
the panic and logs. It does not add a hard error return; callers still
`RREG32`/`WREG32` using a 0 base.
**Step 2.4: Fix quality**
Record: Obviously correct as “don’t panic.” Minimal. Regression risk is
low: if the default branch is taken, the kernel continues and may
program SDMA engine 0-ish registers instead of dying. That matches the
older gfx9/gfx10.3 pattern (`dev_warn` + fallthrough to engine 0),
though this gfx11 version warns and breaks with `base = 0` rather than
explicitly using the engine-0 `SOC15_REG_OFFSET`. No public API change.
## Phase 3: Git history
**Step 3.1: Blame**
Record: Function and original `BUG()` introduced in `cc009e613de65`
(“drm/amdkfd: Add KFD support for soc21 v3”, Mukul Joshi, 2022-05-04).
That commit is an ancestor of `v6.1` and `v6.6` in this repo. The
`WARN()` lines are from `c24edbd5ae0e4` (Alex Deucher, 2026-06-15 /
committed 2026-07-08).
**Step 3.2: Fixes: tag**
Record: No `Fixes:` tag. Buggy code is the original gfx11 KFD SDMA
helper, not a later regression.
**Step 3.3: File history / series**
Record: Standalone for this file. Related siblings:
- `28cc342e2455c` gfx12 same change
- `9f8032604b973` gfx12.1 same change
Part of the June/July 2026 amdgpu `BUG()` cleanup. No extra gfx11
refactor is required for this hunk.
**Step 3.4: Author**
Record: Alex Deucher is the amdgpu maintainer. Around the same dates he
landed many `BUG()`/`BUG_ON()` → `WARN()`/`-EINVAL` conversions across
gfx/sdma/psp.
**Step 3.5: Prerequisites**
Record: None. The function and `BUG()` existed since the file was added.
Applies standalone.
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
Record: `b4 dig -c c24edbd5ae0e4` matched patch-id
`8e42a5ee823a482676f1d117737bc3f4d06296d3`.
Lore/msgid: https://patch.msgid.link/20260615235645.737189-15-
alexander.deucher@amd.com
Series: v1 `[PATCH 15/43]` 2026-06-15; later v2 `[PATCH 02/30]`
2026-07-07. Committed version matches the posted diff. No NAKs found. No
reviewer `Cc: stable` on this patch. Cover-letter fetch from lore
returned 403; mail-archive and Phoronix describe the series as removing
amdgpu `BUG()` so the driver does not panic when it can continue.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: Alex Deucher, `amd-gfx@lists.freedesktop.org`. Kent Russell’s
`Reviewed-by` is on the git commit, not on the v1 mail-archive copy
(review landed later / at commit time).
**Step 4.3: Bug report**
Record: None. No syzbot, bugzilla, or user panic report.
**Step 4.4: Related patches**
Record: Independent per-IP copies. This gfx11 hunk does not depend on
the rest of the 43-patch series.
**Step 4.5: Stable list**
Record: No stable-thread hit found for this subject. UNVERIFIED:
lore.kernel.org/stable search was blocked (Anubis/403).
## Phase 5: Semantic / call graph
**Step 5.1: Functions**
Record: `get_sdma_rlc_reg_offset()` only.
**Step 5.2: Callers (this tree)**
Record:
- `hqd_sdma_load_v11()` — KFD SDMA queue load
- `hqd_sdma_dump_v11()` — dump (debug / dqm)
- `hqd_sdma_is_occupied_v11()`
- `hqd_sdma_destroy_v11()` — preempt/destroy
Those are `gfx_v11_kfd2kgd` ops. Load goes `kfd_load_mqd_sdma()` →
`hqd_sdma_load()`. Dump is used from `kfd_device_queue_manager.c`.
**Step 5.3: Callees**
Record: `SOC15_REG_OFFSET`, register arithmetic, `pr_debug`. Callers
then `RREG32`/`WREG32` at the returned offset.
**Step 5.4: Reachability**
Record: Yes, from `/dev/kfd` queue create/destroy (needs KFD/render
access, not a raw unprivileged syscall). `engine_id` comes from
`v11_sdma_mqd.sdma_engine_id`, set in `kfd_mqd_manager_v11.c` from
`q->sdma_engine_id`.
Kernel assignment (`kfd_device_queue_manager.c`):
- normal SDMA: `sdma_id % kfd_get_num_sdma_engines()`
- `kfd_get_num_sdma_engines()` is `num_instances/num_nodes`, or
`min(..., 2)` if XGMI
Userspace `KFD_QUEUE_TYPE_SDMA_BY_ENG_ID` is range-checked against
`num_sdma + num_xgmi - 1` in `kfd_ioctl_create_queue()`.
Verified: on typical GFX11 (2 SDMA, no XGMI) the id is 0 or 1, so
`default:` is not the normal path. Unverified: whether any GFX11 SKU
with XGMI and >2 SDMA instances can produce `engine_id >= 2` and hit
`BUG()`.
**Step 5.5: Similar patterns**
Record: gfx9 and gfx10.3 already `dev_warn` + fallthrough to engine 0.
gfx11/12/12.1 used `BUG()` until this series. This is aligning gfx11
with the safer sibling.
## Phase 6: This tree
**Step 6.1: Buggy code in this checkout?**
Record: Local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). File
exists. Current `get_sdma_rlc_reg_offset()` already has `WARN(1, ...)`.
`git merge-base --is-ancestor c24edbd5ae0e4 HEAD` succeeds. The panic
path is already gone here; the pre-fix `BUG()` is in the parent of that
commit.
**Step 6.2: Backport difficulty**
Record: Clean apply. Hunk matches the original function from 2022; no
conflicting refactor in that switch.
**Step 6.3: Related fixes already here**
Record: This exact fix is already ancestor of HEAD. Sibling gfx12/12.1
conversions are also present. No alternate gfx11 SDMA `BUG()` fix.
## Phase 7: Subsystem
**Step 7.1**
Record: `drivers/gpu/drm/amd/amdgpu` KFD GFX11. Criticality:
**IMPORTANT** (RDNA3 / RX 7000 / Phoenix, not core mm/vfs).
**Step 7.2**
Record: amdgpu/KFD is actively developed; this helper itself has been
stable since 2022.
## Phase 8: Impact and risk
**Step 8.1: Who**
Record: Users of AMD GFX11 + KFD compute (ROCm / `/dev/kfd`), config
`CONFIG_HSA_AMD`. Driver-specific, not universal.
**Step 8.2: Trigger**
Record: Invalid `engine_id` not in `{0,1}` on SDMA HQD
load/dump/destroy. Common path uses kernel-assigned 0/1. Userspace
engine id is validated for `SDMA_BY_ENG_ID`. Trigger is uncommon; not
shown as a day-to-day ROCm failure. Not a fully unprivileged DoS on
typical 2-engine GFX11.
**Step 8.3: Failure mode**
Record: Old: `BUG()` → kernel panic. Severity if hit: **CRITICAL**.
Likelihood: **LOW** on known 2-engine GFX11. After the fix: warning +
possible wrong MMIO if the branch is taken.
**Step 8.4: Risk-benefit**
Record: Benefit: avoid an intentional driver panic on a bad engine id.
Risk: 3 lines, no locking/API change, very low. Ratio: favorable if the
panic is treated as worth preventing; weaker if judged purely
theoretical.
## Phase 9: Synthesis
**Step 9.1: Evidence**
FOR:
- Replaces `BUG()` (panic) with `WARN()` on a real KFD SDMA path.
- 3-line, obviously correct, reviewed by Kent Russell, written by the
amdgpu maintainer.
- GFX11 KFD support has been in the kernel since 2022 (`cc009e613de65`,
ancestor of v6.1).
- gfx9/gfx10.3 already refused to panic here; gfx11 was the harsh
outlier.
- No prerequisites; applies cleanly to this file.
- Prompt’s crash/panic guidance favors inclusion.
AGAINST:
- No user report, syzbot, or demonstrated trigger.
- Official stable rule: not a “this could be a problem” patch without an
exploit/trigger explanation.
- Identical one-line body across a 43-patch cleanup series, not a
targeted production-crash fix.
- On typical GFX11, engine id is 0 or 1, so `default:` is largely
defensive.
- After `WARN()`, execution continues with `base = 0` rather than
failing the ioctl.
UNRESOLVED:
- Whether any GFX11 product can assign `engine_id >= 2` via XGMI extra
SDMA engines.
- Full cover-letter text (lore 403).
- Stable-list discussion (lore/stable blocked).
**Step 9.2: Stable rules checklist**
1. Obviously correct and tested? **PASS** — 3-line substitution,
reviewed, in mainline.
2. Fixes a real bug that affects users? **PASS** with caveat — it fixes
a real panic *if* the branch runs; no evidence users hit it. Still a
driver `BUG()` on a userspace-reachable KFD path.
3. Important (crash/security/corruption/deadlock)? **PASS** for the
failure mode (panic). Likelihood is low.
4. Small and contained? **PASS** — +2/−1, one function.
5. No new features/APIs? **PASS**.
6. Can apply to this tree? **PASS** — file/function exist; hunk is
identical. (Already applied on 7.3-rc4.)
**Step 9.3: Exception category**
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary
robustness fix.
**Step 9.4: Decision**
This tree is 7.3-rc4 and already contains the commit; the evaluation is
whether the change is stable-worthy for this codebase, not whether to
re-apply it.
It should be. `BUG()` in `get_sdma_rlc_reg_offset()` is an intentional
kernel panic on the GFX11 KFD SDMA load/destroy path. Replacing it with
`WARN()` is the same policy older GFX generations already used, it is
three lines, and it cannot introduce a new API or locking scheme. Lack
of a public reproducer makes it a cleanup-shaped patch, but the user-
visible failure if that branch ever runs is still a full panic, which is
what stable is for.
### What it solves for stable users
Stops the GFX11 KFD SDMA helper from taking down the machine on an out-
of-range engine id, instead of asserting.
### Rules
Small, obviously correct, no new API, applies to this file. It addresses
a panic, not a feature.
### Risk vs benefit
Benefit is panic avoidance on AMD RDNA3 compute queues. Risk is
negligible.
### Concerns
Trigger is uncommon; after `WARN()` the function still returns a 0-based
offset. That is acceptable versus `BUG()`. No extra commits are
required.
## Verification
- [Phase 1] Parsed subject/body/tags: one-sentence panic rationale;
`Reviewed-by: Kent Russell`; no `Fixes`/`Reported-by`.
- [Phase 2] Diff: `BUG()` → `WARN(1, ...)` + `break` in
`get_sdma_rlc_reg_offset()`; +2/−1.
- [Phase 3] `git blame`: `BUG()` from `cc009e613de65` (2022-05-04);
ancestor of v6.1 and v6.6.
- [Phase 3] `git show c24edbd5ae0e4`: matches the candidate diff.
- [Phase 3] `git merge-base --is-ancestor c24edbd5ae0e4 HEAD`: yes
(already in this tree).
- [Phase 4] `b4 dig -c c24edbd5ae0e4`: msgid
`20260615235645.737189-15-alexander.deucher@amd.com` (`15/43`).
- [Phase 4] `b4 dig -a`: v1 43-patch series 2026-06-15; v2 30-patch
2026-07-07.
- [Phase 4] `b4 dig -w`: To/Cc Alex Deucher + amd-gfx; no stable CC.
- [Phase 4] mail-archive: posted diff identical; no NAK in the copies
read.
- [Phase 4] UNVERIFIED: lore.kernel.org cover letter and stable@ archive
(403/Anubis).
- [Phase 5] Callers verified: `hqd_sdma_load_v11` / `dump` /
`is_occupied` / `destroy`; load via `kfd_load_mqd_sdma`.
- [Phase 5] `engine_id` from MQD ← `q->sdma_engine_id`; ioctl range
check for `SDMA_BY_ENG_ID`; typical GFX11 stays 0/1.
- [Phase 5] gfx9/gfx10.3 already warn instead of `BUG()`.
- [Phase 6] `git describe HEAD` / Makefile: 7.3.0-rc4; current file
already has `WARN()`.
- [Phase 8] Failure mode if hit: `BUG()` panic; trigger likelihood low
on 2-engine GFX11.
- UNVERIFIED: GFX11 SKU with `engine_id >= 2` in production.
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
index aaccf0b9947d4..d32ea91eeb343 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
@@ -139,7 +139,8 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
regSDMA1_QUEUE0_RB_CNTL) - regSDMA0_QUEUE0_RB_CNTL;
break;
default:
- BUG();
+ WARN(1, "Invalid SDMA engine id %d\n", engine_id);
+ break;
}
sdma_rlc_reg_offset = sdma_engine_reg_base
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] selftests/ftrace: Force C locale in ftracetest
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (37 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] drm/amdgpu/gfx11: WARN() rather than BUG() for invalid SDMA engine Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] nvme: clamp FDP nruhsd to allocated RUH status descriptor count Sasha Levin
` (477 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Rui Qi, Masami Hiramatsu (Google), Sasha Levin, rostedt, shuah,
linux-kernel, linux-trace-kernel, linux-kselftest
From: Rui Qi <qirui.001@bytedance.com>
[ Upstream commit c13fcd3951dcc19524ce0b3e852844b16cd32b22 ]
Some ftracetest test cases parse command output by matching English
field names. Tools such as readelf may localize their output via
gettext, while ftracetest currently inherits the user locale from
the environment.
If a translated field name is printed, parsing can fail even though
the tested kernel behavior is unchanged. For example, add_remove_uprobe
can fail to find the ELF entry point and then write a uprobe event with
a missing offset.
Export LC_ALL=C in the top-level ftracetest runner so every test case
gets stable command output by default.
Link: https://lore.kernel.org/all/20260807081512.2974757-2-qirui.001@bytedance.com/
Signed-off-by: Rui Qi <qirui.001@bytedance.com>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: this is a three-line selftest locale fix, the
companion uprobe offset patch is already in this 6.18 tree, and the
runner still inherits the user locale.
## Phase 1: Commit message forensics
**Step 1.1: Subject line**
- Record: `[selftests/ftrace] [Force] Force C locale in ftracetest so
test parsing is locale-stable`
**Step 1.2: Tags**
- Record:
- `Link: https://lore.kernel.org/all/20260807081512.2974757-2-
qirui.001@bytedance.com/`
- `Signed-off-by: Rui Qi <qirui.001@bytedance.com>` (author)
- `Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>`
(ftrace/probes maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence is expected for this review)
- Upstream SHA: `c13fcd3951dcc19524ce0b3e852844b16cd32b22`
**Step 1.3: Body**
- Record: `[Bug] ftracetest inherits the user locale; tools such as
readelf can print translated field names. Tests that grep English
strings then fail even though kernel behavior is unchanged.`
`[Symptom] add_remove_uprobe fails to parse the ELF entry point and
writes a uprobe event with a missing offset.` `[Versions] none
stated.` `[Root cause] command-output parsing depends on English
gettext strings while LC_ALL is not forced.`
**Step 1.4: Hidden bug fix?**
- Record: `[Not disguised.] This is an explicit robustness fix for
locale-dependent test parsing, not a style cleanup.`
## Phase 2: Diff analysis
**Step 2.1: Inventory**
- Record: `[Files] tools/testing/selftests/ftrace/ftracetest +3 / -0`
`[Functions] none; top-level shell runner` `[Scope] single-file,
surgical]`
**Step 2.2: Code flow**
- Record: `[Before] ftracetest and every sourced `.tc` inherit LANG/LC_*
from the environment.` `[After] `export LC_ALL=C` at runner start,
inherited by all test cases including `readelf` in add_remove_uprobe.`
`[Path] initialization of the test harness, not kernel runtime.`
**Step 2.3: Bug mechanism**
- Record: `[Category] logic/correctness in the test harness (locale-
dependent parsing).` `[Mechanism] `add_remove_uprobe.tc` does `grep
"Entry point"` and `grep LOAD` on `readelf` output. If those strings
are translated, `ENTRY` is empty, `OFFSET` is empty, and the script
writes `p:myevent ${REALBIN}:` with no offset.`
**Step 2.4: Fix quality**
- Record: `[Quality] obviously correct; `LC_ALL=C` is the standard way
to freeze tool output. Three comment+export lines, no API change.`
`[Regression risk] very low. C locale can change collation/number
formatting, but ftrace tests parse English tracefs and ELF field
names. Maintainer asked for runner-wide export rather than
per-`readelf` wrappers.`
## Phase 3: Git history
**Step 3.1: Blame**
- Record: `[Introduced] ftracetest header is from `6e68e6c5e4b67`
(2014). The locale-sensitive parsing was added by `dc4b165855f23`
("Use readelf to find entry point in uprobe test", 2025-02-26) and
tightened by `bd4e5a97edf8c` (already in this tree), which greps
`"Entry point"` with no `LC_ALL=C`.` `[Age] parsing bug present since
v6.15-era code; still present here.`
**Step 3.2: Fixes: tag**
- Record: `[N/A] no Fixes: tag. Companion series patch 2/2
(`bd4e5a97edf8c` / upstream `24aa630f6259`) fixes `dc4b165855f23` and
is already an ancestor of HEAD.`
**Step 3.3: File history**
- Record: `[Related] `bd4e5a97edf8c` already backported here with `Cc:
stable`. That is v2 2/2 of the same series. In v2, per-command
`LC_ALL=C` was removed from the uprobe test because patch 1/2 was
supposed to set it in the runner. This tree has 2/2 without 1/2.`
`[Standalone?] yes as a diff; semantically it completes that series.`
**Step 3.4: Author**
- Record: `[Author] Rui Qi (ByteDance); not the subsystem maintainer.
Only other ftrace selftest commit in this tree is the companion offset
conversion. Maintainer Masami Hiramatsu applied both.`
**Step 3.5: Prerequisites**
- Record: `[Dependencies] none for apply. Insertion is after the
copyright block, which matches this tree. Local `ftracetest` lacks
mainline `--rv`; that is later context only and is not required.`
`[Standalone apply] yes.`
## Phase 4: Mailing list
**Step 4.1: Original discussion**
- Record: `[Lore] https://patch.msgid.link/20260807081512.2974757-2-
qirui.001@bytedance.com` (WebFetch on lore.kernel.org returned 403;
thread recovered via `b4 dig -m`).`
- `[Revisions] v1 (2026-08-06): `LC_ALL=C` only on one `readelf` in
add_remove_uprobe. v2 (2026-08-07): moved to top-level `ftracetest`
per Masami. Applied version is v2, latest.`
- `[Feedback] Masami on v1: force C locale in the top-level runner, not
per test. Author agreed and sent v2. Masami applied v2 2/2 with "Good
catch! OK, let me take it." No NAKs. No reviewer `Cc: stable` on this
patch (2/2 had `Fixes:` and later got `Cc: stable` in the backport).`
**Step 4.2: Recipients**
- Record: `[To/Cc] Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Shuah Khan, Heiko Carstens, linux-trace-kernel, linux-kselftest,
linux-kernel.`
**Step 4.3: Bug report**
- Record: `[No syzbot/bugzilla.] Cover letter: series fixes two ways
add_remove_uprobe can build an invalid uprobe offset. v1 body: if
readelf is translated, ENTRYPOINT is empty and the `uprobe_events`
write is rejected because the offset after `PATH:` is missing. Author
is a real user of a non-C locale (ByteDance).`
**Step 4.4: Series**
- Record: `[v2 0/2] "Fix add_remove_uprobe robustness". Patch 1 = this
commit. Patch 2 = ELF VA→file offset (`bd4e5a97edf8c`), already in
this tree. v2 2/2 dropped inline `LC_ALL=C` and relies on the runner.`
**Step 4.5: Stable list**
- Record: `[No stable-list discussion found] for this subject. Companion
2/2 was taken into this tree with `Cc: stable@vger.kernel.org`.`
## Phase 5: Code semantics
**Step 5.1: Functions**
- Record: `[No C functions.] Change is `export LC_ALL=C` in
`ftracetest`. Affected consumer: `add_remove_uprobe.tc` `readelf`
parsing.`
**Step 5.2: Callers**
- Record: `[ftracetest-ktap] runs `./ftracetest -K -v`. kselftest
Makefile lists `ftracetest` / `ftracetest-ktap`. `__run_test` sources
each `.tc` in a subshell, so `LC_ALL=C` is inherited. Reachable
whenever someone runs ftrace selftests.`
**Step 5.3: Callees**
- Record: `[readelf -hW / -lW, grep, awk, writes to uprobe_events.]
Kernel ABI involved is `uprobe_events`, already exercised by the
test.`
**Step 5.4: Call chain**
- Record: `[kselftest runner → ftracetest-ktap → ftracetest →
add_remove_uprobe.tc → readelf → uprobe_events.] Userspace-only. Not a
syscall bug; it does cause a false test failure and a malformed probe
write.`
**Step 5.5: Similar patterns**
- Record: `[Only this ftrace test greps readelf "Entry point".] Other
selftests (e.g. mptcp) already pin `LC_ALL=C` on individual commands.
No `export LC_ALL=C` in this tree's ftrace runner yet.`
## Phase 6: This tree (pending-6.18 / 6.18.53)
**Step 6.1: Buggy code present?**
- Record: `[Yes.] `tools/testing/selftests/ftrace/ftracetest` has no
`LC_ALL=C`. `add_remove_uprobe.tc` lines 17 and 37 grep English
`readelf` strings. `git describe HEAD` = `p-6.18-1-g03b85e06ca9bf`;
`make kernelversion` = `6.18.53`. Introduced by `dc4b165855f23`
(ancestor of HEAD).`
**Step 6.2: Backport difficulty**
- Record: `[Clean apply.] Copyright-block context matches. `--rv` in the
candidate hunk is later mainline noise, not needed here.`
**Step 6.3: Related fixes already here?**
- Record: `[Partial.] Offset conversion `bd4e5a97edf8c` is here; locale
export is not. No earlier equivalent `LC_ALL=C` in this file.`
## Phase 7: Subsystem context
**Step 7.1**
- Record: `[Subsystem] tools/testing/selftests/ftrace` `[Criticality]
PERIPHERAL for production kernel runtime; IMPORTANT for anyone running
ftrace kselftests on this stable tree (distro CI, KernelCI, vendor
QA).`
**Step 7.2**
- Record: `[Activity] active; recent ftrace selftest fixes already
landed in this 6.18.y tree, including the companion uprobe test fix.`
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
- Record: `[config/test-specific] users/CI running ftracetest with a
non-C locale (zh_CN, de_DE, ja_JP, etc.). No effect on kernel boot or
production tracing if tests are not run.`
**Step 8.2: Trigger**
- Record: `[Trigger] run ftracetest (or kselftest ftrace) with
translated binutils/gettext. Common on non-English developer and QA
machines. Unprivileged users can run the tests if they have tracefs
access; this is not a privilege-escalation bug.`
**Step 8.3: Failure mode**
- Record: `[Failure] false-negative kselftest; possible write of
`p:myevent <path>:` with empty offset, which the kernel rejects. Not a
panic, UAF, or data corruption.` `[Severity] MEDIUM for QA/CI
correctness; LOW for production kernel runtime.`
**Step 8.4: Risk-benefit**
- Record: `[Benefit] medium for this tree: completes a 2-patch series
whose second half is already here, so add_remove_uprobe stays locale-
broken without it.` `[Risk] very low (3 lines, userspace test runner
only).` `[Ratio] favorable.`
## Phase 9: Synthesis
**Step 9.1: Evidence**
For:
- Real, reproducible test failure when `readelf` is localized.
- Companion v2 2/2 is already in this 6.18 tree and depends on runner
`LC_ALL=C` (inline `LC_ALL=C` was removed in v2).
- Tiny, obviously correct, maintainer-directed.
- Applies cleanly; no kernel ABI/feature change.
- kselftest false failures on stable are used by distros and CI.
Against:
- Not a kernel crash, security hole, deadlock, or data corruption.
- Only hits people who run ftrace selftests under a non-C locale.
- This patch itself was not `Cc: stable` (not used as a NO vote per the
review rules).
Unresolved:
- Could not fetch lore.kernel.org over HTTP (403); discussion was
recovered from `b4 dig` mbox. No stable-list thread found.
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — 3-line export; maintainer
requested and applied; author ran `checkpatch` and `sh -n`.
2. Real bug affecting users? **PASS** — false ftracetest failure and
malformed uprobe write on localized systems.
3. Important issue? **PASS** — not a kernel oops, but it is a real
kselftest break, and this tree already took the paired functional
fix. Leaving this out keeps that test locale-fragile.
4. Small and contained? **PASS** — +3 lines, one file.
5. No new features/APIs? **PASS**.
6. Can apply to this tree? **PASS**.
**Step 9.3: Exception category**
- Record: `[Not a device-ID/quirk/DT/build/docs exception.] Closest
analogue is a kselftest robustness/false-failure fix, which stable
trees routinely take when the test exists in-tree.`
**Step 9.4: Decision**
This should be backported to **this** 6.18.y tree. The bug exists here,
the patch is surgical, and it finishes a series that is already half-
applied.
### What the commit solves for stable users
On a non-C locale, `readelf` can translate `"Entry point"`, so
`add_remove_uprobe` computes an empty offset and fails even though
uprobes work. Distros and CI that run ftrace kselftests against 6.18.y
get a false failure. The offset-conversion fix already in this tree
still greps English `readelf` text and assumed this runner change.
### Risk vs benefit
Benefit is restoring a test that this tree already ships. Risk is
negligible: `LC_ALL=C` only affects the ftracetest process tree.
### Concerns
None material. `--rv` in the original hunk context is not in this tree
and is not required. No further commits are needed for the export to
work.
## Verification
- [Phase 1] Parsed tags: Link to lore msgid `20260807081512.2974757-2`;
SOBs Rui Qi and Masami Hiramatsu; no Fixes/Reported-by/Cc: stable.
- [Phase 2] Diff: +3 lines in `ftracetest` (`export LC_ALL=C`);
confirmed local file lacks it.
- [Phase 3] `git describe HEAD` → `p-6.18-1-g03b85e06ca9bf`; `make
kernelversion` → `6.18.53`.
- [Phase 3] `git merge-base --is-ancestor c13fcd3951dcc1 HEAD` → not an
ancestor (fix not in tree).
- [Phase 3] `git merge-base --is-ancestor bd4e5a97edf8c HEAD` → yes
(companion 2/2 is in tree).
- [Phase 3] `git merge-base --is-ancestor dc4b165855f23 HEAD` → yes
(readelf parsing introduced here).
- [Phase 3] `git blame` on ftracetest header: `6e68e6c5e4b67` (2014); no
LC_ALL.
- [Phase 3] Read `add_remove_uprobe.tc`: greps `"Entry point"` and
`LOAD` with no LC_ALL.
- [Phase 4] `b4 dig -c c13fcd3951dcc1` → v2 1/2 msgid link above.
- [Phase 4] `b4 dig -a` → v1 per-readelf LC_ALL, v2 runner-wide
(applied).
- [Phase 4] `b4 dig -w` → Rostedt, Masami, Desnoyers, Shuah, kselftest
and trace lists.
- [Phase 4] mbox: Masami asked to set LC_ALL in the runner; no NAKs;
cover letter describes two invalid-offset paths.
- [Phase 4] lore WebFetch 403; stable-list search found no discussion of
this subject.
- [Phase 5] `ftracetest-ktap` invokes `./ftracetest -K -v`; `__run_test`
sources `.tc` files so export is inherited.
- [Phase 6] Insertion context after copyright block is present; `export
LC_ALL=C` is not.
- [Phase 8] Failure mode verified from v1 message and current test
script: empty ENTRY → `p:myevent path:` write → test fail, not kernel
oops.
- UNVERIFIED: live `readelf` translation under a specific locale was not
executed on this machine; the gettext localization claim is from the
author and is consistent with binutils behavior, but was not
reproduced here.
**YES**
tools/testing/selftests/ftrace/ftracetest | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index cce72f8b03dce..ee3b950e872f6 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -7,6 +7,9 @@
# Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
#
+# Keep command output parsing stable regardless of the user's locale.
+export LC_ALL=C
+
usage() { # errno [message]
[ ! -z "$2" ] && echo $2
echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] nvme: clamp FDP nruhsd to allocated RUH status descriptor count
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (38 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] selftests/ftrace: Force C locale in ftracetest Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] remoteproc: qcom: Check subdev start status in rproc_stop() Sasha Levin
` (476 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Hari Mishal, Christoph Hellwig, Greg Kroah-Hartman, Keith Busch,
Sasha Levin, axboe, sagi, linux-nvme, linux-kernel
From: Hari Mishal <harimishal1@gmail.com>
[ Upstream commit 29261f8bb41662f2a660c479e5cf592942b53f78 ]
nvme_query_fdp_info() allocates the RUH status buffer for at most S8_MAX
- 1 descriptors, and then copies ruhs->ruhsd[] into head->plids[] using
the controller reported ruhs->nruhsd directly as the loop bound.
However, that count wasn't taken into account for the actual buffer's
size, so there was a chance for a controller reporting a larger nruhsd
to cause the copy to overflow the buffer. Clamp nr_plids to the same
bound used for the allocation.
Assisted-by: gkh_clanker_t1000
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line out-of-bounds-read clamp in NVMe FDP setup. The local
tree is **v7.3-rc4** (`7.3.0-rc4`, HEAD `f0100363d8c37`).
`nvme_query_fdp_info()` exists here; the overflow is real; the change is
surgical.
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[nvme]** **[clamp]** clamp FDP `nruhsd` to the allocated RUH
status descriptor count. “Clamp” is a bounds-fix verb.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Reviewed-by:** Christoph Hellwig `<hch@lst.de>`
- **Assisted-by:** gkh_clanker_t1000
- **Signed-off-by:** Hari Mishal (author), Greg Kroah-Hartman
(submitter), Keith Busch (NVMe maintainer)
- **No Fixes:** tag (expected)
- **No Reported-by / Tested-by / Link / Cc: stable**
- Ignore pipeline SOBs; Greg’s SOB is from the actual submission, not a
stable-prep marker
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `nvme_query_fdp_info()` allocates a RUH-status buffer for at
most `S8_MAX - 1` descriptors, then copies `ruhs->ruhsd[]` using
controller-reported `ruhs->nruhsd` as the loop bound.
- **Symptom:** a controller that reports `nruhsd` larger than the
allocated descriptor count overflows that buffer on the copy into
`head->plids[]`.
- **Root cause:** allocation size and copy bound were not the same.
- **Fix:** clamp `nr_plids` to the same bound used for allocation.
- **Version info in message:** none.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. This is an explicit buffer-overflow / OOB-read fix.
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/nvme/host/core.c` — 1 insertion, 1 deletion
- **Function:** `nvme_query_fdp_info()`
- **Scope:** single-file, one-line surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record: Before: `head->nr_plids = le16_to_cpu(ruhs->nruhsd);` then
`kcalloc(head->nr_plids, …)` and `for (i = 0; i < head->nr_plids; i++)
head->plids[i] = le16_to_cpu(ruhs->ruhsd[i].pid);`. After: `nr_plids` is
`min(reported, S8_MAX - 1)`, so the copy cannot walk past the allocated
`ruhs` buffer. Path is namespace-head init when the controller
advertises FDP.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **(g) logic/correctness + (d) memory safety — out-of-bounds
read.** `nruhsd` is a `__le16` from the device (0..65535). Allocation
used `struct_size(ruhs, ruhsd, S8_MAX - 1)` (126 descriptors, 4048
bytes). Verified layout in `include/linux/nvme.h`: 16-byte header +
32-byte `nvme_fdp_ruh_status_desc`. If `nruhsd == 65535`, the loop reads
~2MB past the buffer. `plids` is sized from `nr_plids`, so the overflow
is an OOB **read** of `ruhs`, not a write into `plids`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct: clamp matches the allocation bound. Minimal.
Regression risk is low: extra reported placement IDs are dropped instead
of overflowing. Later mainline commit `53cdaeab2e30e` raised that cap to
`U8_MAX` / `NVME_MAX_PLIDS`; that is a follow-up improvement, not a sign
this clamp is wrong.
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Allocation `struct_size(..., S8_MAX - 1)` introduced in
`30b5f20bb2dda` (“nvme: register fdp parameters with the block layer”,
Keith Busch, 2025-05-06).
- Unclamped `nr_plids` assignment plus the `ruhsd[]` copy loop:
`38e8397dde633` (“nvme: use fdp streams if write stream is provided”).
- Both first appear in **v6.16-rc1** (`git describe --contains --match
'v*'`).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Introducing commits identified by blame, not by
tag.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `29261f8bb4166` — this clamp (candidate)
- `53cdaeab2e30e` — raise cap to `U8_MAX` and introduce `NVME_MAX_PLIDS`
(depends on the clamp being present)
- `56e1c6bbe4bb0` — race on the plids array (independent locking fix)
- Series partner `3c568b35a0d30` — NS descriptor bounds (different
function, not a prerequisite)
Standalone. Labeled `[PATCH 2/2]` but 1/2 is an independent bounds check
in `nvme_identify_ns_descs()`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Hari Mishal also authored sibling overflow fixes (`nvme: bound
ns descriptor header…`, `nvmet: passthru: fix OOB reads…`). Submitted
via Greg; merged by NVMe maintainer Keith Busch. Christoph Hellwig
reviewed.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None for the clamp itself. It only needs `nvme_query_fdp_info()`
with `S8_MAX - 1` allocation and the copy loop — present since v6.16. No
new helpers or APIs.
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 29261f8bb4166` → https://patch.msgid.link/2026070932-fried-
frying-9c36@gregkh
- **v1 only** (`b4 dig -a`): `[PATCH 1/2] nvme: bound ns descriptor…` +
`[PATCH 2/2]` this clamp
- Full thread saved via `b4 dig -m`; lore HTTP fetch returned 403, so
discussion is from the mbox, not lore HTML
- Christoph: “Looks good: Reviewed-by: Christoph Hellwig”
- Keith Busch: “Thanks, series applied to nvme-7.3.”
- No NAK, no stable discussion in-thread, no reviewer risk flags
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): linux-nvme, linux-kernel, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg. Appropriate maintainers were on Cc.
Christoph reviewed; Keith applied.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla/`Reported-by`. Bug is from code review /
static analysis (Greg/clanker-assisted). Still a concrete OOB from
device-provided `nruhsd`.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 2/2 is independent of 1/2. Follow-up `53cdaeab2e30e` changes the
numeric cap but does not replace the need to clamp. Race fix
`56e1c6bbe4bb0` is separate.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned 403. **UNVERIFIED**
whether stable@ already discussed this. No evidence in the nvme thread
of a stable NAK.
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `nvme_query_fdp_info()` only.
**Step 5.2: TRACE CALLERS**
Record: Only caller is `nvme_alloc_ns_head()` in
`drivers/nvme/host/core.c`:
```4043:4047:drivers/nvme/host/core.c
if (ctrl->ctratt & NVME_CTRL_ATTR_FDPS) {
ret = nvme_query_fdp_info(ns, info);
if (ret < 0)
goto out_cleanup_srcu;
}
```
Triggered during namespace-head creation when Identify Controller
`ctratt` has `NVME_CTRL_ATTR_FDPS`. That is probe/scan, not a hot I/O
path, but it runs for every FDP-capable namespace.
**Step 5.3: TRACE CALLEES**
Record: `nvme_get_features()`, `nvme_query_fdp_granularity()`,
`kzalloc`/`kcalloc`, `nvme_submit_sync_cmd()` (device fills `ruhs`),
then the copy loop.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Device probe / namespace scan → `nvme_init_ns_head` →
`nvme_alloc_ns_head` → `nvme_query_fdp_info`. Reachable from attaching
an NVMe device, including NVMe over Fabrics. A malicious or buggy target
can set FDPS and return a huge `nruhsd`. Not a direct unprivileged
syscall, but device/Fabrics-controlled and kernel-reachable.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same author series also bounded NS identify descriptors. Follow-
up kept the clamp and only raised the cap. No second unclamped `nruhsd`
copy found.
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes, in this lineage.** This checkout is **v7.3-rc4** (`make
kernelversion` → `7.3.0-rc4`). FDP query exists. Bug introduced
**v6.16-rc1**, before 7.3. Candidate `29261f8bb4166` is already an
ancestor of HEAD (`git merge-base --is-ancestor` succeeded; first
contained in **v7.3-rc1**). Current HEAD already clamps:
```2371:2371:drivers/nvme/host/core.c
head->nr_plids = min(le16_to_cpu(ruhs->nruhsd), NVME_MAX_PLIDS);
```
That is this fix plus `53cdaeab2e30e` (`NVME_MAX_PLIDS` = `U8_MAX`). The
unclamped assignment is gone at HEAD because the fix landed in 7.3-rc1;
the overflow pattern is still the code this tree maintains.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Against **current HEAD**, the original hunk would not apply
(`S8_MAX - 1` vs `NVME_MAX_PLIDS`). Against the pre-fix function (parent
of `29261f8bb4166` in this history), it is a one-line change on
`head->nr_plids = le16_to_cpu(ruhs->nruhsd)` with matching `S8_MAX - 1`
allocation. **Expected backport difficulty: clean apply** on trees that
still have that allocation; this 7.3 checkout already has the later
form.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This clamp and the `NVME_MAX_PLIDS` follow-up are both in HEAD.
That is this tree already containing the upstream fix, not a different
substitute.
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **NVMe host core** (`drivers/nvme/host/`). **IMPORTANT** —
common storage stack, not staging. Overflow is in host core during
namespace setup.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Active (recent FDP, multipath, scan, SRCU fixes). FDP streams
themselves date to v6.16; this is not brand-new experimental code in
7.3.
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific / config-specific:** NVMe controllers with FDP
(`NVME_CTRL_ATTR_FDPS` + `FDPCFG_FDPE`). Includes local NVMe and Fabrics
targets that advertise FDP.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Namespace scan/probe on an FDP-enabled controller that returns
`nruhsd >` allocated descriptor count. Not every boot. A buggy SSD can
hit it; an untrusted NVMe/TCP target can hit it on purpose. Unprivileged
local users cannot trigger it without a device.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Kernel out-of-bounds read** of `ruhs->ruhsd[]` → KASAN/oops or
infoleak of adjacent heap. **Severity: HIGH.**
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: **Benefit: high** (stops device-triggered OOB). **Risk: very
low** (one `min()`, same bound as allocation). **Ratio: strongly
favorable.**
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real OOB read from device-controlled `nruhsd` vs a 126-descriptor
buffer
- One-line, obviously correct clamp
- Reviewed by Christoph Hellwig; applied by Keith Busch
- No new API/feature
- Self-contained; series 1/2 is not required
- FDP path exists in this tree; bug dates to v6.16
**AGAINST:**
- No public user/syzbot report (code-analysis find)
- Only FDP-capable devices
- HEAD already has this clamp (and a later cap raise), so this exact
hunk is not what HEAD’s source line looks like
- Lore stable@ search could not be fetched (403)
**UNRESOLVED:**
- Whether stable@ already queued it (lore/stable HTTP 403)
- No runtime reproducer in the message (mechanism is still verified in
code)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — clamp equals allocation
bound; reviewed and merged to nvme-7.3
2. Fixes a real bug that affects users? **PASS** — OOB read on FDP
namespace setup
3. Important issue (crash/security/corruption/deadlock)? **PASS** —
HIGH, kernel OOB from device data
4. Small and contained? **PASS** — 1 line, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** for this codebase’s pre-fix
form (`S8_MAX - 1` allocation + unclamped `nruhsd`). HEAD already has
the evolved clamp; that does not make the fix inapplicable to this
lineage.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None (not a device-ID/quirk/DT/build/docs exception). It is a
normal memory-safety fix.
**Step 9.4: MAKE YOUR DECISION**
This tree’s NVMe host core has the FDP RUH-status query, and using the
controller’s `nruhsd` as the copy bound without capping it to the
allocated descriptor count is a real overflow. The fix is the smallest
correct change. This 7.3 checkout already contains that logic (then
raised the cap to `U8_MAX`); that is the upstream landing, not a reason
to treat the overflow as unworthy of stable. Benefit vs risk is strongly
in favor of backporting.
### What the commit solves, and why it matters
A Flexible Data Placement controller returns how many Reclaim Unit
Handle status descriptors it has (`nruhsd`). The driver only allocated
room for 126, then indexed `ruhs->ruhsd[i]` up to the raw reported
count. That is a kernel heap OOB read during namespace setup, including
from a remote NVMe/TCP target.
### Stable rules
Small, obviously correct, no new API, real memory-safety bug.
### Risk vs benefit
One `min()` vs device-triggered OOB: take the fix.
### Concerns
Patch 2/2 does not need patch 1/2. Trees that already switched
allocation to `NVME_MAX_PLIDS` should keep clamp and allocation in sync
(already true here via `53cdaeab2e30e`). Trees still on `S8_MAX - 1`
should get this commit as-is.
Verification:
- [Phase 1] Parsed tags: Reviewed-by Christoph Hellwig; SOBs Hari
Mishal, Greg KH, Keith Busch; no Fixes/Reported-by/Cc stable
- [Phase 2] Diff: 1 line in `nvme_query_fdp_info()`;
`le16_to_cpu(ruhs->nruhsd)` → `min(..., S8_MAX - 1)`
- [Phase 2] Struct sizes verified in `include/linux/nvme.h`: 16-byte
header + 32-byte descriptors; 126 descriptors → 4048-byte buffer;
`nruhsd` up to 65535
- [Phase 3] Blame: allocation `30b5f20bb2dda`, copy loop
`38e8397dde633`; both `git describe --contains --match 'v*'` →
v6.16-rc1
- [Phase 3] `git merge-base --is-ancestor 29261f8bb4166 HEAD` → commit
is in this tree; `describe --contains` → v7.3-rc1
- [Phase 3] Parent of candidate still has `size = struct_size(ruhs,
ruhsd, S8_MAX - 1)` and unclamped `nr_plids`
- [Phase 4] `b4 dig -c` → msgid 2026070932-fried-frying-9c36@gregkh;
`-a` v1 only; `-w` nvme maintainers; `-m` full thread
- [Phase 4] mbox: Christoph R-b; Keith “applied to nvme-7.3”; no NAK
- [Phase 4] lore.kernel.org and patch.msgid.link HTTP 403; LKML mirrors
agree with mbox
- [Phase 5] grep callers: only `nvme_alloc_ns_head()` when
`NVME_CTRL_ATTR_FDPS`
- [Phase 6] `git describe HEAD` / `make kernelversion`: v7.3-rc4 /
7.3.0-rc4; current clamp is `min(..., NVME_MAX_PLIDS)` from
`53cdaeab2e30e`
- [Phase 8] Failure mode: OOB read of `ruhs->ruhsd[]`, severity HIGH
- UNVERIFIED: stable@ mailing-list history (HTTP 403); no runtime
reproducer in the commit message
**YES**
drivers/nvme/host/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 5ed62e070f715..ad725e346c94e 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2313,7 +2313,7 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
goto free;
}
- head->nr_plids = le16_to_cpu(ruhs->nruhsd);
+ head->nr_plids = min(le16_to_cpu(ruhs->nruhsd), S8_MAX - 1);
if (!head->nr_plids)
goto free;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] remoteproc: qcom: Check subdev start status in rproc_stop()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (39 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] nvme: clamp FDP nruhsd to allocated RUH status descriptor count Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] regmap: irq: Free the irqdomain we create Sasha Levin
` (475 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Jingyi Wang, Bjorn Andersson, Sasha Levin, mathieu.poirier,
linux-remoteproc, linux-kernel
From: Jingyi Wang <jingyi.wang@oss.qualcomm.com>
[ Upstream commit f44ae8ce156a387b07d40e2d6a0ef979a2748aa1 ]
For rproc that doing attach, rproc_start_subdevices() is called only when
attach successfully. If rproc_report_crash() is called in the attach
function, rproc_boot_recovery()->rproc_stop()->rproc_stop_subdevices()->
glink_subdev_stop() could be called and cause NULL pointer dereference:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000300
Mem abort info:
...
pc : qcom_glink_smem_unregister+0x14/0x48 [qcom_glink_smem]
lr : glink_subdev_stop+0x1c/0x30 [qcom_common]
...
Call trace:
qcom_glink_smem_unregister+0x14/0x48 [qcom_glink_smem] (P)
glink_subdev_stop+0x1c/0x30 [qcom_common]
rproc_stop+0x58/0x17c
rproc_trigger_recovery+0xb0/0x150
rproc_crash_handler_work+0xa4/0xc4
process_scheduled_works+0x18c/0x2d8
worker_thread+0x144/0x280
kthread+0x124/0x138
ret_from_fork+0x10/0x20
Code: a9be7bfd 910003fd a90153f3 aa0003f3 (b9430000)
---[ end trace 0000000000000000 ]---
Introduce "subdevs_started" flag to indicate rproc_start_subdevices() has
been called successfully. Ensure subdevices are only stopped if they have
been started.
Signed-off-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260623-rproc-attach-issue-v3-2-8e24310707ce@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This tree is **v7.3-rc4** (`7.3.0-rc4`). The change is a real NULL-deref
fix on the remoteproc attach/recovery path, and the triggering code is
present here.
## Phase 1: Commit message forensics
**Step 1.1: Subject**
Record: `[remoteproc/qcom] [Check] Check subdev start status in
rproc_stop()` — despite the `qcom:` prefix, the diff is in remoteproc
core, not a Qualcomm-only file.
**Step 1.2: Tags**
Record:
- `Signed-off-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com>` (author)
- `Link: https://lore.kernel.org/r/20260623-rproc-attach-
issue-v3-2-8e24310707ce@oss.qualcomm.com`
- `Signed-off-by: Bjorn Andersson <andersson@kernel.org>` (subsystem
maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Cc:
stable` (absence is expected for this review)
- Ignore any pipeline `Signed-off-by: Sasha Levin` — none present on
this commit
**Step 1.3: Body**
Record:
- **Bug:** On attach, `rproc_start_subdevices()` runs only after attach
succeeds. If `rproc_report_crash()` fires during attach, recovery
calls `rproc_stop()` → `rproc_stop_subdevices()` →
`glink_subdev_stop()` while GLINK was never started.
- **Symptom:** kernel NULL deref / oops (`qcom_glink_smem_unregister` at
`pc` offset into a NULL `smem` pointer). Full stack in the message.
- **Root cause:** stop is not paired with a successful start.
- **Fix:** `subdevs_started` flag; skip stop unless start completed.
- **Version info:** none in the message. Link id `v3-2` = patch 2 of a
3-patch series.
**Step 1.4: Hidden bug fix?**
Record: Not hidden. Explicit crash + stack trace. Cover letter: “Failure
in rproc_attach() path can cause issues like NULL pointer dereference
when doing recovery.”
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- `drivers/remoteproc/remoteproc_core.c`: +7 (set flag on successful
start; bail/clear on stop)
- `include/linux/remoteproc.h`: +2 (doc + `bool subdevs_started` in
`struct rproc`)
- Functions: `rproc_start_subdevices()`, `rproc_stop_subdevices()`
- Scope: single-subsystem, surgical, 9 insertions
**Step 2.2: Code flow**
Record:
- **Before:** `rproc_stop_subdevices()` always walked `rproc->subdevs`
and called `stop()`. `glink_subdev_stop()` always called
`qcom_glink_smem_unregister(glink->edge)` with `edge` still NULL if
start never ran.
- **After:** flag set only after a full successful start loop; stop is a
no-op until then; flag cleared after stop.
- Path: attach failure + crash recovery (not the normal successful boot
path).
**Step 2.3: Bug mechanism**
Record: **NULL pointer dereference (memory safety).**
Verified in this tree: `qcom_glink_smem_unregister()` does `smem->glink`
with no NULL check. Crash VA `0x300` matches a field access through
NULL. Same pattern in `smd_subdev_stop()`
(`qcom_smd_unregister_edge(smd->edge)`).
**Step 2.4: Fix quality**
Record: Obviously correct. `rproc_alloc()` uses `kzalloc`, so the flag
starts false. Partial start failure already unrolls via
`unroll_registration` and does not set the flag. Start/stop run under
`rproc->lock` (`rproc_boot`, `rproc_trigger_recovery`,
`__rproc_shutdown`). Regression risk is low; the flag is not a new UAPI.
## Phase 3: Git history
**Step 3.1: Blame**
Record: Subdevice start/stop dates to `7bdc9650f03604` (2016, “Introduce
subdevices”). The missing start-vs-stop pairing is old. This commit only
adds the flag.
**Step 3.2: Fixes tag**
Record: No `Fixes:` tag. Concrete trigger in this tree is
`qcom_pas_attach()` from `16472c99f4699` (“Add late attach support”,
2026-07-01), which calls `rproc_report_crash()` when the coprocessor
already crashed. That commit is an ancestor of HEAD.
**Step 3.3: Related file history**
Record: Same series, same author:
- `026a3fada4326` — [PATCH v3 1/3] async attach via `schedule_work()`
(immediate parent)
- `f44ae8ce156a3` — this commit, 2/3
- `0ec167625b4fe` — [PATCH v3 3/3] cancel `crash_handler` on
`rproc_add()` error
This patch does not use `attach_work`; it stands alone. Patch 1 makes
failed attach keep the rproc registered so recovery actually runs; patch
2 stops that recovery from oopsing.
**Step 3.4: Author**
Record: Jingyi Wang (Qualcomm). Subsystem maintainers Bjorn Andersson
and Mathieu Poirier were To:’d; Bjorn applied the series.
**Step 3.5: Dependencies**
Record: No new helpers. Needs existing `rproc_start_subdevices` /
`rproc_stop_subdevices` / `struct rproc` — all present. Can apply
without patch 1. This tree already has patch 1 and late-attach, so the
crash path is live here.
## Phase 4: Mailing list
**Step 4.1: Original discussion**
Record:
- `b4 dig -c f44ae8ce156a3` → https://patch.msgid.link/20260623-rproc-
attach-issue-v3-2-8e24310707ce@oss.qualcomm.com
- Series: `[PATCH v3 0/3] remoteproc: improve robustness for
rproc_attach fail cases`
- v1 used a NULL check; v2 introduced `subdevs_started`; v3 moved the
flag into start/stop. Applied version is v3.
- No NAK in the saved thread. Bjorn: “Applied, thanks!”
**Step 4.2: Recipients**
Record: To Bjorn Andersson and Mathieu Poirier (REMOTEPROC maintainers);
Cc linux-remoteproc. Right people.
**Step 4.3: Bug report**
Record: No syzbot/bugzilla. Evidence is the oops in the commit (Qualcomm
attach/crash). Trigger is also in-tree: `qcom_pas_attach()` reports
crash if fatal IRQ is already high.
**Step 4.4: Series**
Record: 2/3. 1/3 is robustness (async attach). 3/3 is a UAF-style cancel
of crash work on `rproc_add()` failure. This patch is self-contained.
**Step 4.5: Stable list**
Record: lore.kernel.org/stable was blocked (Anubis). UNVERIFIED whether
anyone nominated this on stable@. No `Cc: stable` on the patch itself.
## Phase 5: Semantic / call graph
**Step 5.1: Functions**
Record: `rproc_start_subdevices`, `rproc_stop_subdevices`.
**Step 5.2: Callers**
Record:
- `rproc_start_subdevices`: `rproc_start()` (firmware boot),
`__rproc_attach()` (attach)
- `rproc_stop_subdevices`: `rproc_stop()` (recovery/`__rproc_shutdown`),
`__rproc_detach()` (attach recovery)
**Step 5.3: Callees**
Record: `subdev->start` / `subdev->stop` (GLINK, SMD, SSR, virtio).
**Step 5.4: Reachability**
Record: Yes. Qualcomm PAS attach: `rproc_add` → auto-boot attach work →
`rproc_boot` → `rproc_attach` → `qcom_pas_attach` → `rproc_report_crash`
→ `rproc_crash_handler_work` → `rproc_trigger_recovery` →
`rproc_boot_recovery` → `rproc_stop`. Matches the posted stack.
Coprocessor already crashed at probe is a real boot-time case.
**Step 5.5: Similar patterns**
Record: `smd_subdev_stop()` has the same NULL-edge unregister. Core flag
covers all subdevs, which is why v2 dropped a GLINK-only NULL check.
## Phase 6: This tree
**Step 6.1: Buggy code here?**
Record: Yes. `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion` = `7.3.0-rc4`. Attach, late-attach crash report, GLINK
stop-without-NULL-check, and recovery all exist. The fix is already an
ancestor of HEAD (`git merge-base --is-ancestor f44ae8ce156a3 HEAD`
succeeded); that is apply-evidence, not the reason to accept it.
**Step 6.2: Backport difficulty**
Record: Clean apply on this tree (already applied). No conflicting
refactor of those two functions.
**Step 6.3: Alternate fix already here?**
Record: No other start/stop guard. Later commits (`0ec167625b4fe`,
`74ee3b2f57674`) address crash-work vs teardown, not this pairing.
## Phase 7: Subsystem
**Step 7.1:** Record: `drivers/remoteproc` — **IMPORTANT** (Qualcomm
DSP/modem/WiFi remoteprocs; not core mm/vfs, but widely used on
phones/embedded).
**Step 7.2:** Record: Actively developed (late attach, async attach,
crash-handler races in 2026).
## Phase 8: Impact and risk
**Step 8.1:** Record: Qualcomm (and any rproc) users who attach to an
already-running remoteproc. Config: `CONFIG_REMOTEPROC` plus QCOM
PAS/GLINK. Not universal, but a large device population.
**Step 8.2:** Record: Trigger = attach while the remote CPU already
crashed (fatal IRQ high) or crash during attach. Seen in the field (oops
dump). Not a pure theoretical race; crash work vs `rproc->lock` is
ordered, then stop runs on unstarted subdevs.
**Step 8.3:** Record: Kernel oops / NULL deref. **HIGH/CRITICAL**.
**Step 8.4:** Record: Benefit high (avoids oops during subsystem
recovery). Risk very low (9 lines, internal bool, kzalloc-zeroed, lock-
held).
## Phase 9: Synthesis
**Step 9.1: Evidence**
**For:**
- Real oops with stack; `qcom_glink_smem_unregister(NULL)` is visible in
code
- In-tree trigger: `qcom_pas_attach()` + recovery
- This tree has late attach and async attach, so the path is reachable
- Small, obviously correct, maintainer-applied (v3)
- No new UAPI
**Against:**
- Part of a 3-patch series (1/3 is behavioral); this hunk does not need
1/3
- No `Fixes:` / `Cc: stable` (not a negative per rules)
- Adds a `struct rproc` field (in-tree only; kzalloc-safe)
**Unresolved:** Stable mailing-list discussion (lore/stable fetch
blocked).
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — pairing is clear; oops is
the test evidence; maintainer applied v3
2. Real user-visible bug? **PASS** — NULL deref oops
3. Important (crash/security/corruption/deadlock)? **PASS** — oops on
attach/recovery
4. Small and contained? **PASS** — 9 lines, two functions + one bool
5. No new features/APIs? **PASS** — internal flag
6. Applies to this tree? **PASS** — files and call paths exist; would
apply cleanly
**Step 9.3: Exception category**
Record: None. Ordinary crash fix.
**Step 9.4: Decision**
This tree needs the fix: attach can report a crash before subdevices
start, and `rproc_stop_subdevices()` would then oops. The change is
minimal and correct.
### What it solves for this tree
If a Qualcomm remoteproc is already crashed when Linux attaches (or
crashes during attach), recovery calls `rproc_stop()` while GLINK/SMD
were never started. That is a kernel oops, not a soft failure. The flag
makes stop a no-op until start has succeeded.
### Risk vs benefit
Benefit: prevent a boot/recovery oops on common Qualcomm attach
hardware. Risk: negligible; flag is zero-initialized and only mutated
under `rproc->lock`.
### Concerns
Patch 1/3 is not required for this hunk. Patch 3/3 is a separate
teardown UAF. Neither blocks applying this commit here. No `Fixes:` tag;
the late-attach crash report (`16472c99f4699`) is in this tree and is
the practical introducer of the reported path.
## Verification
- [Phase 1] Parsed tags: author SOB, maintainer SOB, lore Link v3-2; no
Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: +7 core, +2 header; flag on successful start; early
return in stop
- [Phase 2] `qcom_glink_smem_unregister()`: `smem->glink` with no NULL
check — matches oops at VA `0x300`
- [Phase 3] `git describe HEAD`: `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion`: `7.3.0-rc4`
- [Phase 3] `git merge-base --is-ancestor f44ae8ce156a3 HEAD`: yes
(applies/is present)
- [Phase 3] Parent `026a3fada4326` is series 1/3 (async attach); 3/3 is
`0ec167625b4fe`
- [Phase 3] Blame: start/stop from 2016; flag from this commit
- [Phase 3] Trigger `qcom_pas_attach` crash report from `16472c99f4699`
(in this tree, before this fix)
- [Phase 4] `b4 dig -c f44ae8ce156a3`: lore thread; v1→v3; Bjorn
applied; no NAK
- [Phase 4] `b4 dig -w`: To Andersson + Poirier
- [Phase 4] Cover letter v2: flag replaced a GLINK-only NULL check
- [Phase 4] UNVERIFIED: stable@ discussion (lore/stable Anubis 403)
- [Phase 5] Call chain verified: `qcom_pas_attach` →
`rproc_report_crash` → `rproc_crash_handler_work` →
`rproc_trigger_recovery` → `rproc_stop` → `rproc_stop_subdevices`
- [Phase 5] `rproc_alloc()` uses `kzalloc` — flag starts false
- [Phase 5] `rproc_boot` / `rproc_trigger_recovery` / `__rproc_shutdown`
hold `rproc->lock` around start/stop
- [Phase 6] Buggy stop-without-start exists conceptually; this tree has
attach + late-attach trigger
- [Phase 8] Failure mode: NULL deref oops, severity HIGH/CRITICAL
**YES**
drivers/remoteproc/remoteproc_core.c | 7 +++++++
include/linux/remoteproc.h | 2 ++
2 files changed, 9 insertions(+)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 2336c55eb021d..068a3ef467f78 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1104,6 +1104,8 @@ static int rproc_start_subdevices(struct rproc *rproc)
}
}
+ rproc->subdevs_started = true;
+
return 0;
unroll_registration:
@@ -1119,10 +1121,15 @@ static void rproc_stop_subdevices(struct rproc *rproc, bool crashed)
{
struct rproc_subdev *subdev;
+ if (!rproc->subdevs_started)
+ return;
+
list_for_each_entry_reverse(subdev, &rproc->subdevs, node) {
if (subdev->stop)
subdev->stop(subdev, crashed);
}
+
+ rproc->subdevs_started = false;
}
static void rproc_unprepare_subdevices(struct rproc *rproc)
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index de98462d58889..ef711a5b1a7f2 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -273,6 +273,7 @@ enum rproc_features {
* @has_iommu: flag to indicate if remote processor is behind an MMU
* @auto_boot: flag to indicate if remote processor should be auto-started
* @sysfs_read_only: flag to make remoteproc sysfs files read only
+ * @subdevs_started: flag to indicate if subdevs have started
* @dump_segments: list of segments in the firmware
* @nb_vdev: number of vdev currently handled by rproc
* @elf_class: firmware ELF class
@@ -317,6 +318,7 @@ struct rproc {
bool has_iommu;
bool auto_boot;
bool sysfs_read_only;
+ bool subdevs_started;
struct list_head dump_segments;
int nb_vdev;
u8 elf_class;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] regmap: irq: Free the irqdomain we create
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (40 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] remoteproc: qcom: Check subdev start status in rproc_stop() Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] tty: serial: pch_uart: add check for pci_get_slot() Sasha Levin
` (474 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Mark Brown, Farhad Alemi, Thomas Gleixner, Sasha Levin, gregkh,
rafael, dakr, linux-kernel, driver-core
From: Mark Brown <broonie@kernel.org>
[ Upstream commit 2e42cade8ff1ff579e77976d9869db4df1feaf74 ]
When domain support was added to regmap-irq it was not possible to
remove domains, this was added later by 8ee99ada293b (irqdomain: Support
removal of IRQ domains.). We did update the main removal path to free
the domain but forgot the error unwinding case during creation that is
now in regmap_add_irq_chip_fwnode() after some code motion, meaning that
errors during instantiation result in an unused irqchip being left
hanging around. Add the missing irq_remove_domain() call where the
comment says it should be.
Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>
Reported-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260901-regmap-irq-deallocate-domain-v1-1-4bfed4aff559@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.18.57**. At that base,
`regmap_add_irq_chip_fwnode()` still has the “Should really dispose of
the domain but...” stub, so the leak exists here and the one-line
`irq_domain_remove()` change applies cleanly.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[regmap: irq:] [Free] [Release the irqdomain created during
chip setup]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>` (researcher
report)
- `Reported-by: Thomas Gleixner <tglx@kernel.org>` (irq subsystem
maintainer)
- `Link: https://patch.msgid.link/20260901-regmap-irq-deallocate-
domain-v1-1-4bfed4aff559@kernel.org`
- `Signed-off-by: Mark Brown <broonie@kernel.org>` (regmap maintainer;
author)
- No `Fixes:` tag (expected)
- No `Cc: stable` (expected)
- Pipeline-added `[Upstream commit 2e42cade8ff1...]` and Sasha Levin SOB
ignored per instructions
- Notable: two reporters, one of them tglx
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: when irqdomain support was added to regmap-irq, domains could not
be removed. `irq_domain_remove()` was added later (`58ee99ada293b`;
the message cites `8ee99ada293b`, missing the leading `5`). The
success teardown path was updated; the **creation error-unwind** path
was not.
- Symptom: failed instantiation leaves an unused irqchip/domain hanging
around.
- Failure mode: resource leak of a published irq domain on
`request_threaded_irq()` failure after `regmap_irq_create_domain()`.
- Root cause (author): missing `irq_domain_remove()` at the
`err_domain:` label (the comment already said it should be there). The
message says `irq_remove_domain()`; the actual API is
`irq_domain_remove()`.
- Version info: none beyond the historical API gap.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. This is an explicit error-path resource-leak fix.
External reporting (KASAN during CPU hotplug) shows the leaked objects
can become a use-after-free, not only a leak.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/base/regmap/regmap-irq.c` (`1` insertion, `1` deletion)
- Function: `regmap_add_irq_chip_fwnode()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: domain created → `request_threaded_irq()` fails → `goto
err_domain` → comment only → mutex/key teardown → `kfree(d)` while
`d->domain` stays published with `host_data = d`.
- After: same path calls `irq_domain_remove(d->domain)` before freeing
`d`.
- Path affected: probe error path only, after successful domain
creation.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- Category: error-path resource leak; can escalate to UAF because the
domain is published (`irq_domain_list` / fwnode) with `host_data`
pointing at memory that is then freed.
- Mechanism: missing counterpart to the existing `irq_domain_remove()`
in `regmap_del_irq_chip()`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- For `irq_base == 0` (most DT callers): obviously correct. Domain has
no mappings yet; `irq_domain_remove()` is the right unwind and matches
the del path.
- For `irq_base != 0` (legacy/`irq_alloc_descs()` path, including
callers passing `-1`): incomplete. Domain creation associates IRQs up
front. `irq_domain_remove()` does not dispose those mappings. tglx
said the descriptor chip/domain pointers remain and the UAF remains.
- Regression risk: low for `irq_base == 0`. For `irq_base > 0`, the
domain object is freed while descriptors still reference it (already a
UAF on `desc->chip` before this patch). The change is still a subset
of the correct unwind, not a new feature.
- Red flags: none on APIs/scope. Completeness gap is real but does not
make the one-line change wrong for the common path.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Comment/label introduced by `4af8be67fd9989` (“regmap: Convert
regmap_irq to use irq_domain”, 2012).
- Domain remove on the **del** path: `b5ab3e5cae097` (“regmap: irq:
Remove domain on exit”, 2014).
- `err_domain:` still only had the comment at **v6.18.57**.
- This is long-lived error-path debt, not a brand-new 6.18-only bug.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Historical introducer is `4af8be67fd9989`; that
commit **is** an ancestor of this tree.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Nearby: `1da33858af625` (mutex destroy on error), `76b6e14aa7b08`
(lockdep key). Both already in v6.18.57; this patch’s context matches.
- Domain creation helper: `dde286ee57704` / `regmap_irq_create_domain()`
already in this tree.
- Standalone 1-line fix, not patch X/Y.
- No follow-up in this tree adding `irq_dispose_mapping()` on
`err_domain`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Author is Mark Brown, **regmap maintainer**. He applied his own
patch to `broonie/regmap.git for-7.3` the same day.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Needs `irq_domain_remove()`: present (`58ee99ada293b`, exported in
this tree).
- Needs `d->domain` and `err_domain:`: present.
- Can apply standalone to v6.18.57. No missing helpers.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore/msgid: https://patch.msgid.link/20260901-regmap-irq-deallocate-
domain-v1-1-4bfed4aff559@kernel.org
- Only v1 (`b4 dig -a`); no v2 in that thread.
- Thread:
1. Mark posts the 1-line patch (1 Sep 2026).
2. Mark applies it to for-7.3 ~1 hour later.
3. tglx (4 Sep): “That won’t work” for the `irq_alloc_descs()` /
`virq_base > 0` case; descriptors keep chip/domain pointers; UAF
remains. First suggestion: `irq_domain_free_irqs()`.
4. tglx follow-up: `irq_domain_free_irqs()` only works with
hierarchical domains; use `irq_dispose_mapping(irq_base + i)` then
remove the domain.
5. Mark: “Ah, thanks - I’d expected removing the domain to clean
everything up.”
- No NAK of calling `irq_domain_remove()` itself; the request is
additional dispose before remove.
- No reviewer `Cc: stable` in the thread.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Recipients were linux-kernel, Farhad Alemi, tglx, Mark Brown.
tglx reviewed after apply. No Acked-by/Reviewed-by on the committed
patch.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record:
- Public write-up (31 Aug 2026): KASAN invalid read in
`irq_migrate_all_off_this_cpu` during CPU offline. tglx traced it to
this failed-setup path: descriptors remain mapped to a caller-owned
`irq_chip` after that chip/`regmap_irq_chip_data` is freed.
- Trigger: device IRQ setup fails, then CPU hotplug walks descriptors.
- Radu Rendec mentioned a similar syzbot hotplug stack; tglx criticized
allocation info in that report. Overlap is suggestive, not proven
identical.
- Unprivileged exploit/CVE: not established.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone v1. tglx’s dispose-mapping addition was not in this
series and is not in this tree. GitHub `master` snapshot still showed
the old comment, consistent with this being a 7.3-era fix not yet
universal.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No useful stable-list hit that this was previously rejected or
requested. UNVERIFIED beyond search noise.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `regmap_add_irq_chip_fwnode()` only. Callees of interest:
`regmap_irq_create_domain()`, `request_threaded_irq()`,
`irq_domain_remove()`.
**Step 5.2: TRACE CALLERS**
Record:
- `regmap_add_irq_chip()` → `regmap_add_irq_chip_fwnode()`
- `devm_regmap_add_irq_chip_fwnode()` → same
- `git grep -l "regmap_add_irq_chip"` → **87** `.c` files
- Call context: driver probe (MFD/PMIC, ASoC codecs, power, GPIO, RTC,
DSA). Not a syscall hot path; boot/enumeration and probe-retry.
- `irq_base != 0` callers exist, including popular PMICs: `rk8xx-core.c`
(`-1`), `retu-mfd.c`, `88pm800.c`, `88pm805.c`, `mt6370.c`, plus board
`irq_base` in tps65910/wm8994/tps65090.
**Step 5.3: TRACE CALLEES**
Record:
- `regmap_irq_create_domain()` → `irq_domain_instantiate()` with
`virq_base = irq_base`, `host_data = d`. If `virq_base > 0`,
`__irq_domain_instantiate()` runs `irq_domain_associate_many()`.
- `if (irq_base)` also calls `irq_alloc_descs()` first (`-1` is truthy).
- `irq_domain_remove()` unpublishes and `kfree`s the domain; comment
requires mappings already disposed.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record:
- Reachable from device probe of many PMICs/codecs.
- Userspace does not call this directly. Probe failure + later CPU
offline is the documented KASAN path.
- Deferred probe retry can also leave a stale fwnode domain if the
domain is not removed.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: `regmap_del_irq_chip()` already disposes mappings then calls
`irq_domain_remove()`. That is the model tglx wants on `err_domain` when
`irq_base > 0`. This patch only adds the remove.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes, at v6.18.57 `drivers/base/regmap/regmap-irq.c`
`err_domain:` still has `/* Should really dispose of the domain but...
*/`. Introduced 2012; never unwound on this error path here.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Expected **clean apply** to v6.18.57. Surrounding
`mutex_destroy` / `lockdep_unregister_key` already match.
`irq_domain_remove()` already used in the same file’s del path.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Del-path domain remove is here (`b5ab3e5cae097`). No other fix
of this `err_domain` leak. No `irq_dispose_mapping` follow-up on that
label.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/base/regmap` IRQ helper. **IMPORTANT** (shared by many
PMICs/MFDs, not core mm/sched, but widely used on ARM/embedded and
laptops).
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature (2011+). Recent work is lockdep nesting, mutex free,
domain suffix. This is leftover unwind, not churn from a new subsystem.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific / config-specific (`CONFIG_REGMAP_IRQ`), but
that config is selected by many common PMICs. Affects anyone whose
regmap-irq probe fails after domain create.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Trigger: `regmap_irq_create_domain()` succeeds, then
`request_threaded_irq()` fails (bad/missing IRQ, busy IRQ, probe
deferral, etc.).
- Not every boot. Realistic on flaky firmware, wrong DT IRQ, deferred
probe.
- Unprivileged trigger: not verified. CPU hotplug typically needs
privilege. KASAN still shows a real kernel UAF.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Always: leaked published irq domain; `d` freed while domain
`host_data` dangles.
- With `irq_base != 0`: leaked associated IRQ descriptors; `desc->chip`
can UAF on CPU offline (`irq_migrate_all_off_this_cpu`). **HIGH** (UAF
/ KASAN).
- This patch fully fixes the domain leak; it does **not** fully fix the
descriptor UAF when `irq_base > 0`.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: high for a 1-line unwind of a published irq domain used by
dozens of drivers; needed for probe retry and to stop leaking domain
objects.
- Risk: very low for `irq_base == 0`. For `irq_base > 0`, incomplete;
not a new feature; same class of UAF already existed.
- Ratio: benefit > risk. Follow-up dispose-mapping should also be
backported when it exists; that is not a reason to keep the domain
leak.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real error-path leak of a published irq domain; comment admitted the
gap since 2012.
- Reported by tglx; KASAN UAF on CPU hotplug is a serious failure mode.
- 1 line, same API already used in `regmap_del_irq_chip()`.
- Buggy code is in v6.18.57; `irq_domain_remove()` is in this tree;
applies cleanly.
- Author is the regmap maintainer; 87 in-tree callers.
- Probe-path resource leaks are standard stable material.
AGAINST:
- Incomplete vs the reported `irq_base > 0` UAF; tglx asked for
`irq_dispose_mapping()` first; Mark agreed the remove-alone assumption
was wrong.
- No `Fixes:`/`Cc: stable` (not a negative by itself).
- Applied to for-7.3 before tglx’s review; no v2 in that thread.
UNRESOLVED:
- Whether a later mainline follow-up with `irq_dispose_mapping()` landed
after this tree’s branch.
- Whether the KASAN report was reproduced on 6.18.y specifically (code
path is present).
- No stable-list discussion found.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** for the domain leak (`irq_base
== 0` and domain object itself). Incomplete for preassociated
descriptors, but the added call is the correct API and is already
used on the del path.
2. Fixes a real bug that affects users? **PASS** — leaked irq domain on
failed probe; KASAN UAF documented on related leftover mappings.
3. Important issue? **PASS** — UAF / resource leak of irq core objects,
not cosmetic.
4. Small and contained? **PASS** — 1 line, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — v6.18.57 has the exact hunk
context.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not ID/quirk/DT/docs. Ordinary error-path leak fix. Build-fix
exception N/A.
**Step 9.4: MAKE YOUR DECISION**
This should be backported to **this** 6.18.y tree. The bug is here, the
helper is here, and the change is the missing unwind the code has
documented for years. Incompleteness for `irq_base > 0` means a later
dispose-mapping patch is still needed for the full KASAN UAF; it does
not make this line a net negative.
### What the commit solves, and why it matters here
`regmap_add_irq_chip_fwnode()` publishes an irq domain, then on
`request_threaded_irq()` failure frees `struct regmap_irq_chip_data`
without removing that domain. Stable 6.18.57 still does this. The
leftover domain stays on the global list with dangling `host_data`, and
on the legacy `irq_base != 0` path associated descriptors can later be
walked during CPU hotplug (KASAN UAF). Many PMICs/MFDs use this helper,
including rk8xx with `irq_base = -1`.
### Stable rules / risk
Small, obviously intended, no new API, applies cleanly. Benefit is
fixing a real leak/UAF-adjacent unwind; risk is a 1-line call that the
same file already uses on teardown.
Verification:
- [Phase 1] Tags: Farhad Alemi + tglx Reported-by; lore msgid link; Mark
Brown SOB; no Fixes/Cc stable
- [Phase 1] Body describes creation-path domain leak after
`8ee99ada293b`; actual SHA in this tree is `58ee99ada293b`
- [Phase 2] Diff is 1 line in `regmap_add_irq_chip_fwnode()`
`err_domain:`: comment → `irq_domain_remove(d->domain)`
- [Phase 3] `git blame` at v6.18.57: comment from `4af8be67fd9989`
(2012); del-path remove `b5ab3e5cae097` (2014)
- [Phase 3] `git merge-base --is-ancestor 4af8be67fd9989 HEAD` yes;
`58ee99ada293b` is ancestor of v6.18.57
- [Phase 3] No follow-up dispose-mapping commit on this file in this
tree
- [Phase 4] `b4 dig -c 4784831655ab5`: v1 only, applied to for-7.3 same
day
- [Phase 4] tglx: remove-alone does not clear associated descriptors
when `virq_base > 0`; use `irq_dispose_mapping` then remove
- [Phase 4] Mark acknowledged he expected remove to clean everything up
- [Phase 4] External write-up: KASAN in `irq_migrate_all_off_this_cpu`
after failed regmap IRQ setup
- [Phase 5] 87 files call `regmap_add_irq_chip*`; probe of
MFD/PMIC/codec/etc.
- [Phase 5] `if (irq_base) irq_alloc_descs()` plus `virq_base`
associate_many confirmed in this tree
- [Phase 6] `git describe HEAD` → `v6.18.57-155-gcdf239ca885b2`; `make
kernelversion` → 6.18.57
- [Phase 6] v6.18.57 still has the dispose comment;
`irq_domain_remove()` already in `regmap_del_irq_chip()`
- [Phase 8] Failure mode: leaked irq domain; UAF on CPU hotplug for
preassociated IRQs; severity HIGH
- UNVERIFIED: later mainline follow-up with `irq_dispose_mapping` on
`err_domain`; whether syzbot report is the same bug; stable-list
history beyond unsuccessful search
**YES**
drivers/base/regmap/regmap-irq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 6112d942499be..8c297156ea402 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -941,7 +941,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
return 0;
err_domain:
- /* Should really dispose of the domain but... */
+ irq_domain_remove(d->domain);
err_mutex:
mutex_destroy(&d->lock);
lockdep_unregister_key(&d->lock_key);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] tty: serial: pch_uart: add check for pci_get_slot()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (41 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] regmap: irq: Free the irqdomain we create Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:06 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] nvme: ratelimit the completion-path messages driven by device data Sasha Levin
` (473 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Haoxiang Li, Andy Shevchenko, Greg Kroah-Hartman, Sasha Levin,
jirislaby, linux-kernel, linux-serial
From: Haoxiang Li <haoxiang_li2024@163.com>
[ Upstream commit 970ede67de0e3f6a1e707ec99ae49d80bf3f2966 ]
Add check for pci_get_slot() to prevent a potetial
null pointer dereference in pch_request_dma().
Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260623140539.2272473-1-haoxiang_li2024@163.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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: `[tty: serial: pch_uart] [add] [NULL check on pci_get_slot() in
pch_request_dma()]`
**Step 1.2: Tags** (from the candidate message; original mail had extra
tags — see Phase 4)
- Reviewed-by: Andy Shevchenko `<andriy.shevchenko@linux.intel.com>`
(serial/PCI reviewer; author of the `pci_get_slot()` call)
- Link: `https://patch.msgid.link/20260623140539.2272473-1-
haoxiang_li2024@163.com`
- Signed-off-by: Haoxiang Li (author); Greg Kroah-Hartman (tty
maintainer)
- No Reported-by, Tested-by, Acked-by in the committed message
- No Fixes:/Cc: stable in the committed message (expected for this
review queue)
**Step 1.3: Body**
Record:
- Bug: `pci_get_slot()` can return NULL; the caller then does
`param->dma_dev = &dma_dev->dev`.
- Symptom: potential NULL pointer dereference in `pch_request_dma()`.
- No stack trace, reproducer, or version range. Typo “potetial”.
- Root cause as stated: missing return-value check.
**Step 1.4: Hidden bug fix?**
Record: Not hidden. Explicit defensive NULL check. Same pattern as other
static-analysis “add check for X()” patches from this author.
---
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/tty/serial/pch_uart.c` (+5 / −0)
- Function: `pch_request_dma()`
- Scope: single-file surgical fix
**Step 2.2: Flow**
Record: After `pci_get_slot(priv->pdev->bus,
PCI_DEVFN(PCI_SLOT(priv->pdev->devfn), 0))`, the code used `dma_dev`
unconditionally. After the patch, NULL returns with `dev_err` and no
`pci_dev_put` (correct: no reference was taken). Later failures still
use `goto err_pci_get` → `pci_dev_put(dma_dev)`.
**Step 2.3: Bug mechanism**
Record: **NULL pointer dereference.** `pci_get_slot()` is documented to
return NULL when the slot/function is absent (`drivers/pci/search.c`).
The next statement dereferences `dma_dev`.
**Step 2.4: Fix quality**
Record: Obviously correct, minimal, no API/lock/structure changes.
Regression risk is very low. Early return leaves DMA unset;
`pch_uart_verify_port()` only sets `use_dma` if `priv->chan_rx` is set,
so PIO fallback still works on that path.
---
## Phase 3: Git history
**Step 3.1: Blame**
Record:
- Driver added in `3c6a483275f47` (2010, “Serial: EG20T: add PCH_UART
driver”) using hardcoded `pci_get_bus_and_slot()`.
- Current lookup introduced in `8368d6a2b73900` (Andy Shevchenko,
2014-07-30, v3.17-rc1).
- NULL check added by this commit `970ede67de0e3` (2026-06-23).
- Bug has been in tree for ~12 years.
**Step 3.2: Fixes: tag**
Committed message has none. Original mail (Phase 4) had
`Fixes: 8368d6a2b739 ("pch_uart: don't hardcode PCI slot to get DMA
device")`.
Record: `8368d6a2b739` **is** an ancestor of this checkout (`git merge-
base --is-ancestor` succeeded; contained in v3.17-rc1).
**Step 3.3: Related file history**
Record:
- `8be3a7bf77370` (2022): missing `pci_dev_put()` after `pci_get_slot()`
— confirms the API contract (refcount on success, NULL on failure).
- `6fe472c1bbbe2` (2026): NULL check for `dma_alloc_coherent()` in the
same function, with `Fixes:` + `Cc: stable`.
- `e41c0981213f3` (2013): real NULL deref in this driver when DMA setup
failed.
Standalone 5-line patch, not part of a numbered series.
**Step 3.4: Author**
Record: Haoxiang Li is a regular static-analysis contributor, not the
tty maintainer. One pch_uart commit. Reviewed by Andy Shevchenko;
applied by Greg Kroah-Hartman.
**Step 3.5: Dependencies**
Record: None. Uses existing `pci_get_slot()`, `dev_err`, and
`pch_request_dma()`. Applies standalone.
---
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
Record:
- `b4 dig -c 970ede67de0e3` → https://patch.msgid.link/20260623140539.22
72473-1-haoxiang_li2024@163.com
- `b4 dig -a`: v1 only; that version was applied.
- Original body **did** include `Fixes: 8368d6a2b739` and `Cc:
stable@vger.kernel.org` (stripped in the git commit; that is why this
is in the manual queue, not a reason to reject).
- Andy Shevchenko: *“Not that it's quite possible, but probably you
found this due to AI review which might have considered some cases of
manual binding a PCI device to any PCI driver. Given that is the case,
I'm fine with the change.”*
- No NAK.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: gregkh, jirislaby, andriy.shevchenko, linux-serial, linux-
kernel, **stable@vger.kernel.org**, kees@kernel.org. Right maintainers
were on CC. Andy reviewed; Greg applied.
**Step 4.3: Bug report**
Record: No syzbot, bugzilla, or user report. Static/AI analysis of a
documented NULL return.
**Step 4.4: Series**
Record: Standalone v1. Related in-function fix `6fe472c1bbbe2` is
independent.
**Step 4.5: Stable list**
Record: lore stable search shows the original patch (because it was CCed
there) and Andy’s reply. No follow-up rejecting it for stable. WebFetch
to lore returned 403; thread recovered via `b4 dig -m` and curl.
---
## Phase 5: Semantic / call graph
**Step 5.1: Functions**
Record: `pch_request_dma()` only.
**Step 5.2: Callers**
Record (from this tree):
1. `pch_uart_startup()` — if `priv->use_dma`
2. `pch_uart_verify_port()` — TIOCSSERIAL / setserial path, which this
driver historically runs during install (`af6d17cdc8c89`)
**Step 5.3: Callees**
Record: `pci_get_slot`, `dma_request_channel`, `dma_alloc_coherent`,
`pci_dev_put`.
**Step 5.4: Reachability**
Record: Yes, from userspace serial setup (TIOCSSERIAL) and from UART
startup when DMA was already enabled. Needs `CONFIG_SERIAL_PCH_UART` and
typically `CONFIG_PCH_DMA`. Not a syscall fuzz target for unprivileged
users; admin/boot path on EG20T/ML72xx hardware.
**Step 5.5: Similar patterns**
Record: Same function already checks `dma_request_channel` and
`dma_alloc_coherent`. DMA PCI ID 0x8810 is function-0 sibling of UART
IDs 0x8811–0x8814; lookup is “same slot, function 0”.
---
## Phase 6: This checkout
**Step 6.1: Buggy code in this tree?**
Record: Local tree is **v7.3-rc4-27** (`Makefile` 7.3.0-rc4). Driver and
`pci_get_slot()` lookup are present. Introducing commit `8368d6a2b739`
is an ancestor. Current `pch_request_dma()` already contains the NULL
check from `970ede67de0e3` (first appeared `v7.2-rc1-21`). The bug class
exists in this lineage; the file is not missing.
**Step 6.2: Backport difficulty**
Record: Clean apply. Hunk is independent of the later `goto` ladder.
**Step 6.3: Other fixes already here?**
Record: Refcount leak fix and `dma_alloc_coherent` check are present. No
alternate fix for this NULL case besides this commit.
---
## Phase 7: Subsystem context
**Step 7.1:**
Record: `drivers/tty/serial/pch_uart.c` — Intel EG20T PCH / LAPIS
ML7213/ML7223/ML7831 UART (Atom E6xx-era embedded/IVI). **PERIPHERAL**,
but a real in-tree production driver.
**Step 7.2:**
Record: Low churn; occasional correctness fixes. Mature, not staging.
---
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
Record: Driver/config-specific: `CONFIG_SERIAL_PCH_UART` on 32-bit x86
or MIPS (or `COMPILE_TEST`). Not universal.
**Step 8.2: Trigger**
Record: `pch_request_dma()` when function 0 of the UART’s PCI slot is
not enumerated (firmware hid DMA, sparse multifunction device, or sysfs
bind of this driver to a non-fn0 device with no fn0 sibling). On stock
EG20T, fn0 DMA (0x8810) is normally present, so `pci_get_slot()`
succeeds. Unprivileged users cannot bind PCI drivers. `verify_port` is a
real install/setserial path.
**Step 8.3: Failure mode**
Record: Kernel oops (NULL deref) instead of PIO fallback. Severity:
**HIGH** if it fires, **low likelihood** on intended hardware. Andy
called the trigger unlikely but accepted the case.
**Step 8.4: Risk/benefit**
Record: Benefit: prevent oops, match existing error handling. Risk: very
low (5 lines, error path only). Ratio: favorable.
---
## Phase 9: Synthesis
**Step 9.1: Evidence**
For:
- Real, documented NULL return from `pci_get_slot()`, immediately
dereferenced.
- 5-line, obviously correct check; UART continues without DMA.
- Reviewed by Andy Shevchenko; applied by Greg KH.
- Original submission asked for stable and cited `Fixes: 8368d6a2b739`
(in tree since v3.17).
- Same function already treats DMA setup failure as a crash-worthy bug
(`e41c0981213f3`, `6fe472c1bbbe2`).
- Applies cleanly; no new API; no prerequisites.
Against:
- Niche ~2010 embedded UART.
- No user/syzbot report; likely AI/static analysis.
- Reviewer: trigger is “not quite possible” except odd PCI bind.
- Committed message dropped `Cc: stable` / `Fixes:` (auto-select would
have needed those tags).
Unresolved: none that change the technical call. Lore WebFetch 403 was
covered by `b4` + curl.
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — reviewed; Greg merged; logic
is local and clear.
2. Real bug affecting users? **PASS** — API can return NULL; oops if DMA
setup runs without fn0. Rare, but not fictional.
3. Important (crash/security/corruption/deadlock)? **PASS** — NULL deref
→ oops; small blast radius.
4. Small and contained? **PASS** — +5 lines, one function.
5. No new features/APIs? **PASS**.
6. Can apply to this tree? **PASS** — driver and call site exist; hunk
is clean.
**Step 9.3: Exception category**
Record: None (not an ID/quirk/DT/build/docs exception). Ordinary memory-
safety fix.
**Step 9.4: Decision**
This tree is 7.3-rc4 and already contains the driver. The bug is a NULL
deref on a documented failure path, the patch is a five-line guard with
PIO fallback, and it needs no other commits. Niche hardware and a rare
trigger do not outweigh an oops fix this small. It belongs in this tree.
---
### Problem and why it matters here
`pch_request_dma()` looks up the EG20T/ML72xx DMA function with
`pci_get_slot(..., function 0)` and then uses `dma_dev->dev`. If that
function is missing, the kernel oopses while opening or reconfiguring
the UART. The patch logs and returns so the port can keep running in PIO
mode.
### Stable rules / risk
Meets the rules: real crash, tiny, no features, clean apply on this
checkout. Benefit (avoid oops) dwarfs regression risk.
### Concerns
Trigger is uncommon on real EG20T boards; this is defensive. That is not
a reason to keep a NULL deref. No extra backport work.
---
Verification:
- [Phase 1] Parsed committed tags: Reviewed-by Andy Shevchenko, Link to
msgid, SOBs Haoxiang Li + Greg KH; no Reported-by/syzbot.
- [Phase 2] `git show 970ede67de0e3`: +5 lines in `pch_request_dma()`
after `pci_get_slot()`.
- [Phase 2] Read `pch_request_dma()` in this tree: check +
`err_pci_get`/`pci_dev_put` paths confirmed.
- [Phase 3] `git blame` / `git log -L`: lookup from `8368d6a2b739`
(v3.17-rc1); driver from `3c6a483275f47` (2010).
- [Phase 3] `git merge-base --is-ancestor 8368d6a2b739 HEAD` → yes.
- [Phase 3] Related: `8be3a7bf77370` refcount, `6fe472c1bbbe2` dma_alloc
check, `e41c0981213f3` historical DMA NULL oops.
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 thread; original had
Fixes:+Cc:stable; Andy Reviewed-by; no NAK.
- [Phase 4] WebFetch lore 403; curl on lore stable showed patch + Andy
reply only.
- [Phase 5] Callers: `pch_uart_startup` (line 1267),
`pch_uart_verify_port` (line 1427).
- [Phase 5] `pci_get_slot()` in `drivers/pci/search.c` returns NULL if
not found.
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4.
- [Phase 6] `git merge-base --is-ancestor 970ede67de0e3 HEAD` → yes
(first at v7.2-rc1-21).
- [Phase 7] Kconfig `SERIAL_PCH_UART`: EG20T/ML7213/ML7223/ML7831.
- [Phase 8] DMA ID 0x8810 vs UART 0x8811–0x8814 in `pch_dma.c` /
`pch_uart.c`.
- UNVERIFIED: live crash on real EG20T hardware (no user report).
**YES**
drivers/tty/serial/pch_uart.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index c3f32e0590b7f..9104361ccb14f 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -678,6 +678,11 @@ static void pch_request_dma(struct uart_port *port)
/* Get DMA's dev information */
dma_dev = pci_get_slot(priv->pdev->bus,
PCI_DEVFN(PCI_SLOT(priv->pdev->devfn), 0));
+ if (!dma_dev) {
+ dev_err(priv->port.dev, "%s: failed to get DMA device\n",
+ __func__);
+ return;
+ }
/* Set Tx DMA */
param = &priv->param_tx;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] nvme: ratelimit the completion-path messages driven by device data
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (42 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] tty: serial: pch_uart: add check for pci_get_slot() Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] PCI: switchtec: Add Microchip PCI1008 to NTB DMA alias quirk Sasha Levin
` (472 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Chao Shi, Keith Busch, Sasha Levin, axboe, sagi, linux-nvme,
linux-kernel
From: Chao Shi <coshi036@gmail.com>
[ Upstream commit c05c86681170e381e24498257db3a879deb1ae89 ]
nvme_find_rq() and nvme_handle_cqe() print an unratelimited message for
every completion queue entry whose command id does not resolve to an
in-flight request. Both are reached from the completion interrupt path
(nvme_irq() -> nvme_poll_cq() -> nvme_handle_cqe()) and the decision to
print is made entirely from device-supplied data, so a controller that
posts a stream of bogus command ids drives unbounded printk from hard
interrupt context.
This is not hypothetical. A single boot under an emulated controller
that posts invalid completions produced 846 "could not locate request
for tag 0x0", 846 "invalid id 0 completed on queue 2" and 123 "genctr
mismatch" lines. Once the tag set has been torn down every subsequent
completion resolves to nothing, so the print rate is bounded only by how
fast the device can post entries.
Ratelimit the three messages. The information they carry is diagnostic
and repeats, so the suppression count printed by the ratelimit helpers
is enough to tell that the condition persists. This matches how the
other device-driven error prints in the driver are already handled, for
example the status messages in nvme_log_error() and
nvme_log_err_passthru().
nvme_find_rq() lives in nvme.h and is shared by pci, tcp, rdma, apple and
target-loop, so all transports are covered.
Found by FuzzNvme.
Signed-off-by: Chao Shi <coshi036@gmail.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough local-tree and review evidence to decide. The remaining
work is to write the full nine-phase analysis.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[nvme]** **[ratelimit]** Completion-path messages that fire
from device-supplied command IDs are unbounded; the commit rate-limits
those three prints.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Signed-off-by:** Chao Shi \<coshi036@gmail.com\> (author)
- **Signed-off-by:** Keith Busch \<kbusch@kernel.org\> (NVMe maintainer;
applied the patch)
- **No Fixes:** tag (expected for this review queue)
- **No Cc: stable** (expected; not a negative)
- **No Reported-by / Tested-by / Reviewed-by / Acked-by / Link:**
- Notable: “Found by FuzzNvme” in the body (fuzzer-found, not syzbot)
- Ignore any pipeline “Upstream commit” / “Signed-off-by: Sasha Levin”
markers
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** `nvme_find_rq()` and `nvme_handle_cqe()` print on every CQE
whose command id does not map to an in-flight request. The print
decision is made from device-supplied data.
- **Symptom:** Unbounded `printk` from the completion interrupt path
(`nvme_irq()` → `nvme_poll_cq()` → `nvme_handle_cqe()`). One emulated-
controller boot produced 846 “could not locate request for tag 0x0”,
846 “invalid id 0 completed on queue 2”, and 123 “genctr mismatch”
lines. After the tag set is torn down, every later completion prints;
rate is limited only by how fast the device posts entries.
- **Version info:** None in the message. The prints have been in-tree
since v5.15 / v5.9 (verified in Phase 3).
- **Root cause:** Device-controlled, unratelimited diagnostics on the
hard-IRQ completion path. Other device-driven NVMe error prints
(`nvme_log_error()`, `nvme_log_err_passthru()`) are already
ratelimited.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit fix for IRQ-context
log flood. The subject uses “ratelimit” rather than “fix”, but the body
states the failure mode and a concrete reproduction.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- `drivers/nvme/host/nvme.h`: `nvme_find_rq()` — `pr_err` →
`pr_err_ratelimited`; `dev_err` → `dev_err_ratelimited` (~5 lines net
churn)
- `drivers/nvme/host/pci.c`: `nvme_handle_cqe()` — `dev_warn` →
`dev_warn_ratelimited` (3 lines)
- Scope: **single-purpose surgical fix**, two files, ~9 insertions / 8
deletions. No logic, locking, or API changes.
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Hunk 1 (`nvme_find_rq`, missing request): same `return NULL`; only the
error print is ratelimited.
- Hunk 2 (`nvme_find_rq`, genctr mismatch): same `return NULL`; only the
error print is ratelimited.
- Hunk 3 (`nvme_handle_cqe`, invalid id): same early return; only the
warning is ratelimited.
- Affected path: completion / IRQ / poll error path when the device
posts a bad command id. Success path is unchanged.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- **Category:** Logic / correctness of diagnostics; IRQ-context
resource/DoS (unbounded `printk` driven by device data).
- **Mechanism:** A malicious or failing controller can post a stream of
CQEs with bogus command ids. Each entry hits
`pr_err`/`dev_err`/`dev_warn` in `nvme_irq()`. After tag-set teardown
the miss path is permanent. `_ratelimited` variants cap volume while
still reporting that the condition persists (suppression count).
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: swap to helpers already used in the same driver
(`nvme_log_error()`, PCI timeout path).
- Minimal: three call-site changes, no behavior change on the success
path.
- Regression risk: very low. Worst case is fewer repeated log lines for
a persistent fault; first occurrences and the ratelimit “suppressed”
count remain.
- Red flags: none (no API, locking, or data-structure changes).
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- `nvme_find_rq()` and both prints: `e7006de6c23803` (“nvme: code
command_id with a genctr for use-after-free validation”, Sagi
Grimberg, 2021-06-16). Contained in **v5.15-rc1**. Present in this
tree (`git merge-base --is-ancestor` succeeded).
- PCI “invalid id” print: `50b7c24390a53c` (“nvme-pci: fix NULL req in
completion handler”, Xianting Tian, 2020-09-22). Contained in
**v5.9-rc7**. Present in this tree.
- The buggy prints have been in NVMe for years, including all 6.12.y
history.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No `Fixes:` tag. N/A. The introducing commits above are the
functional origin.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- `git log --oneline -15 HEAD -- drivers/nvme/host/nvme.h` shows no
later rewrite of `nvme_find_rq()`.
- `git log --oneline --grep="ratelimit the completion-path" HEAD --
drivers/nvme/` is empty: this fix is **not** in the local tree.
- Standalone one-patch change. Not “patch X/Y”. Keith applied it to
nvme-7.3 with only a line-wrap tweak.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record:
- Chao Shi: only `4298c52252cf6` (“nvme: reject passthrough of driver-
managed Set Features”) in this tree under `drivers/nvme/`. Not a
series dependency.
- Keith Busch is an NVMe maintainer; his SOB is a strong quality signal.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: No new helpers or structs. `pr_err_ratelimited` /
`dev_err_ratelimited` / `dev_warn_ratelimited` exist in this tree
(`include/linux/printk.h`, `include/linux/dev_printk.h`) and are already
used in `drivers/nvme/host/core.c` and `pci.c`. Applies standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c <msgid>` failed: the landed commit is not in this checkout,
so there is no local commit-ish to match.
- Thread recovered from Patchew and Openwall (lore.kernel.org returned
403):
- Submission: https://patchew.org/linux/20260810220258.1960208-1-
coshi036@gmail.com/
- Message-ID: `20260810220258.1960208-1-coshi036@gmail.com`
(2026-08-10)
- Single v1 patch (not a multi-revision series).
- Keith Busch: agreed that dumping every garbage CQE adds no diagnostic
value; **applied to nvme-7.3** with a minor overly-long-line wrap. No
NAK, no stability concern.
- Author replied that later submissions would avoid long lines. That is
style only; Keith already applied the wrap.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: To/Cc on the v1: Keith Busch, Jens Axboe, Christoph Hellwig,
Sagi Grimberg, linux-nvme, linux-kernel. Maintainer applied it. No
separate Reviewed-by on the provided commit text.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No bugzilla/syzbot link. Reproduction is in the commit: FuzzNvme
+ emulated controller, 1815 diagnostic lines in one boot. Severity from
the author’s data: hard-IRQ printk flood, unbounded after tag-set
teardown.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone. Sibling unratelimited prints remain in
apple/tcp/rdma/loop *after* `nvme_find_rq()` fails; those are extra
transport messages, not prerequisites. This patch still covers the
shared `nvme_find_rq()` prints on all of those transports.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search returned 403. Openwall/Patchew
show no stable NAK or “already rejected” discussion. UNVERIFIED: no
evidence this was previously declined for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `nvme_find_rq()` (inline in `nvme.h`); `nvme_handle_cqe()`
(`pci.c`).
Step 5.2: TRACE CALLERS
Record (verified with grep + reads):
- `nvme_find_rq()`:
- `nvme_handle_cqe()` — PCI
- `nvme_tcp_process_nvme_cqe()`, `nvme_tcp_handle_c2h_data()`,
`nvme_tcp_handle_r2t()` — TCP
- `nvme_rdma_process_nvme_rsp()` — RDMA
- `apple_nvme_handle_cqe()` — Apple
- `nvme_loop` completion path — target-loop
- `nvme_handle_cqe()` ← `nvme_poll_cq()` ← `nvme_irq()` (hard IRQ or
threaded IRQ), `nvme_poll_irqdisable()`, `nvme_poll()`,
`nvme_reap_pending_cqes()`.
- Impact: every NVMe transport’s completion path. PCI hard-IRQ is the
hottest and the one the commit calls out.
Step 5.3: TRACE CALLEES
Record: `blk_mq_tag_to_rq()`, genctr helpers, then `pr_*` / `dev_*`. No
allocation, no new locking.
Step 5.4: FOLLOW THE CALL CHAIN
Record: PCI: device posts CQE → MSI/MSI-X → `nvme_irq()` →
`nvme_poll_cq()` → `nvme_handle_cqe()` → `nvme_find_rq()`. Reachable
whenever an NVMe controller is attached, including VMs/emulators and
failing real devices. Userspace does not need a special syscall; a bad
device is enough. FuzzNvme reached it.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same driver already ratelimits device-driven errors
(`nvme_log_error`, `nvme_log_err_passthru`, PCI timeout
`dev_warn_ratelimited`). Apple still has an unratelimited “invalid id”
`dev_warn`; TCP/RDMA/loop have their own unratelimited “bad command_id”
prints. Those leftovers do not block this fix.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes.** Local tree is **6.12.111** (`git describe HEAD` →
`p-6.12-3-gc504cf0baa3d8`, `make kernelversion` → 6.12.111).
- `drivers/nvme/host/nvme.h:598-607` still uses `pr_err` / `dev_err`.
- `drivers/nvme/host/pci.c:1128-1130` still uses `dev_warn`.
- Introducing commits are ancestors of HEAD. Bug present since v5.15
(find_rq) / v5.9 (PCI invalid-id print).
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **Clean apply (line-number offset only).** The 6.12
`nvme_find_rq()` body matches the hunk. `nvme_handle_cqe()` differs
later (`trace_nvme_sq` lacks the newer `data_race()` comment in this
tree), but that is after the changed warn. No conflicting refactor.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No commit in this tree ratelimits these three messages. No
alternate fix found.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **NVMe host** (`drivers/nvme/host/`). **IMPORTANT** — primary
block storage on servers, workstations, and many embedded/Android
platforms. Not core mm/VFS, but a very common production driver.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Active in this 6.12 branch (recent PCI IRQ, doorbell, quirk, and
core lifetime fixes). The buggy prints themselves have been unchanged
since 2021.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific**, all NVMe host transports via
`nvme_find_rq()`; PCI users are the main hard-IRQ case. Large user
population whenever a controller posts invalid completions (faulty
firmware, reset/teardown, emulator, fuzzer, passthrough VM).
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Trigger: CQE with a command id that does not resolve, or genctr
mismatch; also every completion after tag-set teardown.
- Commonness: rare on healthy hardware; realistic on failing devices,
resets, and VMs. FuzzNvme hit it in one boot.
- Unprivileged userspace: not via a normal syscall on a healthy disk. A
VM user with an emulated/passthrough NVMe device, or a malicious
controller, can drive it. Device-controlled printk from IRQ is a host
DoS vector in those setups.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- **Failure mode:** Unbounded `printk` from hard IRQ / completion
context. Can stall on `console_lock`, flood the log, and contribute to
soft lockups on slow consoles. Not a UAF/oops by itself.
- **Severity: HIGH** (IRQ-context flood / hang risk), not CRITICAL (no
panic/corruption on the success path).
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** High for NVMe users who hit a dying, resetting, or
emulated controller — stops IRQ printk storms that have been
demonstrated in practice.
- **Risk:** Very low (3 call-site swaps to existing ratelimit helpers).
- **Ratio:** Strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
**FOR:**
- Real, reproduced bug (1815 lines in one boot; FuzzNvme).
- Hard-IRQ, device-controlled printk — known lockup/DoS class.
- After tag-set teardown the miss path is permanent; print rate = device
CQE rate.
- Tiny, obviously correct, matches existing NVMe style.
- Maintainer (Keith Busch) applied it with agreement, no NAK.
- Buggy code present in this 6.12.111 tree since v5.15/v5.9.
- Applies cleanly; no prerequisites.
- `nvme_find_rq()` is shared across PCI/TCP/RDMA/Apple/loop.
**AGAINST:**
- Not a crash, UAF, or data-corruption fix.
- Healthy devices rarely hit the path.
- Transport-local “bad command_id” prints in tcp/rdma/apple/loop stay
unratelimited (incomplete sibling coverage, not a dependency).
**UNRESOLVED:**
- lore.kernel.org 403; discussion recovered from Patchew/Openwall.
- `b4 dig -c` could not run against a local SHA (commit not in this
tree).
- No stable-list discussion found (search blocked).
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — three `_ratelimited` swaps;
maintainer applied; FuzzNvme reproduction.
2. Fixes a real bug that affects users? **PASS** — documented IRQ printk
flood; teardown path makes it unbounded.
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
IRQ-context flood can stall the console / soft-lockup; device-driven
DoS. Severity HIGH.
4. Small and contained? **PASS** — ~9/+8 lines, two files, error prints
only.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — buggy code present; helpers
present; clean apply expected.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID / quirk / DT / build / docs exception. Qualifies
as a normal small stability fix.
Step 9.4: MAKE YOUR DECISION
This belongs on 6.12.y. The tree still has the unratelimited IRQ prints,
the fix is surgical, and the failure mode is a real host-stability
problem on failing or emulated NVMe — not a feature or cleanup.
Detailed explanation:
The problem is unbounded `printk` from NVMe completion handling when the
device supplies a command id that does not map to an in-flight request.
That path runs from `nvme_irq()` in hard interrupt context (or the
equivalent completion callbacks on other transports). After the tag set
is torn down, every CQE misses, so a broken controller can print as fast
as it can post completions. That is a real production concern during
reset/remove of a failing disk and in VMs; FuzzNvme already produced
thousands of lines in one boot. Rate-limiting those three diagnostics
matches `nvme_log_error()` and does not change I/O completion logic.
Risk is negligible; benefit is avoiding IRQ-context log storms on a
widely deployed storage stack.
Verification:
- [Phase 1] Parsed tags: author SOB Chao Shi; maintainer SOB Keith
Busch; no Fixes/Cc stable/Reported-by (expected).
- [Phase 1] Body: concrete counts (846/846/123) and IRQ path `nvme_irq`
→ `nvme_poll_cq` → `nvme_handle_cqe`.
- [Phase 2] Diff: `pr_err`/`dev_err`/`dev_warn` → `_ratelimited` in
`nvme_find_rq` and `nvme_handle_cqe` only.
- [Phase 3] `git blame drivers/nvme/host/nvme.h`: prints from
`e7006de6c23803` (v5.15-rc1).
- [Phase 3] `git blame drivers/nvme/host/pci.c`: invalid-id print from
`50b7c24390a53c` (v5.9-rc7).
- [Phase 3] `git merge-base --is-ancestor e7006de6c23803 HEAD` and
`50b7c24390a53c HEAD`: both ancestors.
- [Phase 3] `git log --grep="ratelimit the completion-path" HEAD --
drivers/nvme/`: empty; fix not in this tree.
- [Phase 4] `b4 dig` needs a local commit-ish; candidate is not in this
checkout — UNVERIFIED via b4.
- [Phase 4] Patchew + Openwall: v1 applied by Keith Busch to nvme-7.3;
no NAK.
- [Phase 4] lore.kernel.org fetch: 403 — discussion taken from
Patchew/Openwall instead.
- [Phase 5] Callers of `nvme_find_rq`: pci, tcp, rdma, apple,
target/loop (grep).
- [Phase 5] `nvme_poll_cq` called from `nvme_irq`,
`nvme_poll_irqdisable`, `nvme_poll`, `nvme_reap_pending_cqes`.
- [Phase 5] `queue_request_irq()` registers `nvme_irq` as the hard-IRQ
handler (or thread fn).
- [Phase 5] Ratelimit macros present in `include/linux/printk.h` and
`include/linux/dev_printk.h`; already used in `nvme_log_error()`.
- [Phase 6] `git describe HEAD` / `make kernelversion`: 6.12.111
(`p-6.12-3-gc504cf0baa3d8`).
- [Phase 6] Read `nvme.h:598-607` and `pci.c:1126-1131`: unratelimited
prints still present.
- [Phase 8] Failure mode: device-driven printk flood from hard IRQ;
severity HIGH (lockup/DoS), not oops/UAF.
- UNVERIFIED: whether this SHA already exists on some other remote
branch (not required; local tree does not have the fix).
- UNVERIFIED: stable mailing-list history (lore/stable 403).
**YES**
drivers/nvme/host/nvme.h | 6 +++---
drivers/nvme/host/pci.c | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index ec03a07617af1..b28c1a82f79e6 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -672,12 +672,12 @@ static inline struct request *nvme_find_rq(struct blk_mq_tags *tags,
rq = blk_mq_tag_to_rq(tags, tag);
if (unlikely(!rq)) {
- pr_err("could not locate request for tag %#x\n",
- tag);
+ pr_err_ratelimited("could not locate request for tag %#x\n",
+ tag);
return NULL;
}
if (unlikely(nvme_genctr_mask(nvme_req(rq)->genctr) != genctr)) {
- dev_err(nvme_req(rq)->ctrl->device,
+ dev_err_ratelimited(nvme_req(rq)->ctrl->device,
"request %#x genctr mismatch (got %#x expected %#x)\n",
tag, genctr, nvme_genctr_mask(nvme_req(rq)->genctr));
return NULL;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 4efb55f1e3833..6e4261b0a0821 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1375,9 +1375,9 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
req = nvme_find_rq(nvme_queue_tagset(nvmeq), command_id);
if (unlikely(!req)) {
- dev_warn(nvmeq->dev->ctrl.device,
- "invalid id %d completed on queue %d\n",
- command_id, le16_to_cpu(cqe->sq_id));
+ dev_warn_ratelimited(nvmeq->dev->ctrl.device,
+ "invalid id %d completed on queue %d\n",
+ command_id, le16_to_cpu(cqe->sq_id));
return;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] PCI: switchtec: Add Microchip PCI1008 to NTB DMA alias quirk
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (43 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] nvme: ratelimit the completion-path messages driven by device data Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:06 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] net: stmmac: fix device node reference leaks in stmmac_mtl_setup() Sasha Levin
` (471 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Logan Gunthorpe, Bjorn Helgaas, Sasha Levin, linux-pci,
linux-kernel
From: Logan Gunthorpe <logang@deltatee.com>
[ Upstream commit 00a479ba1d01249d43ca5e453380d1ed60946f8a ]
Add the PCI1008 device ID to the quirk_switchtec_ntb_dma_alias PCI fixup
table. Without it, DMA transactions from a PCI1008 switch's NTB function
are not given the correct requester ID alias, which can misdirect them
under an IOMMU.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260714212010.230606-4-logang@deltatee.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line PCI ID addition to an existing NTB DMA-alias quirk.
The local tree is **v7.3-rc4** (`7.3.0-rc4`, HEAD `f0100363d8c37`). The
`SWITCHTEC_PCI100X_QUIRK` table is present, so the change belongs here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[PCI: switchtec:] [Add] [PCI1008 device ID to the existing NTB
DMA alias quirk table]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Fixes:` — none (expected)
- `Reported-by:` — none
- `Tested-by:` — none
- `Reviewed-by:` — none
- `Acked-by:` — none on this patch; Vinod Koul acked series patch 1/3
(dmaengine ID)
- `Link:`
https://patch.msgid.link/20260714212010.230606-4-logang@deltatee.com
(series 3/3)
- `Cc: stable@vger.kernel.org` — none (expected)
- `Signed-off-by: Logan Gunthorpe <logang@deltatee.com>` (author;
SWITCHTEC DMA maintainer)
- `Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>` (PCI subsystem
maintainer)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** PCI1008 is missing from `quirk_switchtec_ntb_dma_alias`.
Switchtec NTB replaces the original requester ID with a hardware proxy
ID. Without an IOMMU alias, those TLPs are not attributed to the NTB
device.
- **Symptom:** DMA from a PCI1008 NTB function can be misdirected or
blocked when an IOMMU is on (IOMMU faults / failed peer DMA).
- **Versions:** none named. Series cover letter says the patches were
based on v7.2-rc3; Bjorn applied them for v7.3.
- **Root cause:** the PCI100X quirk table lists 0x1001–0x1006 only;
PCI1008 (0x1008) was never added.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. It is an explicit hardware-quirk / device-ID
addition. That is a documented stable exception, not cleanup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pci/quirks.c` — **+1 / −0**
- Function: none changed; one `SWITCHTEC_PCI100X_QUIRK(0x1008)` entry
added next to 0x1001–0x1006
- Scope: single-file, one-line surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_EFAR, 0x1008,
PCI_CLASS_BRIDGE_OTHER, 8, quirk_switchtec_ntb_dma_alias)` is not
registered. A PCI1008 NTB function never runs the quirk.
- **After:** the same FINAL-class fixup used for PCI1001–PCI1006 is
registered for 0x1008. Enumeration of a matching device calls
`quirk_switchtec_ntb_dma_alias()`, which reads the NTB proxy-ID tables
and calls `pci_add_dma_alias()`.
- Path: PCI enumeration / class fixup FINAL (init), not a hot path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** (h) Hardware workaround — PCI ID added to an existing
quirk table
- **Mechanism:** Switchtec NTB DMA uses proxy requester IDs. IOMMU
groups are built from those aliases. Missing 0x1008 means PCI1008
proxy IDs are not aliased, so IOMMU policy does not match the
requester ID on the wire.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: same macro and comment style as PCI1001–PCI1006.
- Minimal: one line, no API or structure change.
- Regression risk: very low. The new fixup only matches vendor EFAR +
device 0x1008 + class `PCI_CLASS_BRIDGE_OTHER`. Other devices are
unchanged. `quirk_switchtec_ntb_dma_alias()` already bounds `table_sz`
(skip 0, reject >512).
- Red flags: none. A pre-existing `ep_map + 4` pointer-arithmetic issue
in the quirk function was flagged on the list; it is not introduced by
this line.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Surrounding `SWITCHTEC_PCI100X_QUIRK` entries: `a3282f84b2151` (“PCI:
switchtec: Add Microchip PCI100X device IDs”, 2025-01-21). Present in
v6.14, not in v6.13.
- Original Switchtec NTB DMA alias quirk: `ad281ecf1c7d4` (“PCI: Add DMA
alias quirk for Microsemi Switchtec NTB”, 2018-06-29). Present in this
tree.
- The 0x1008 line itself is this commit (`00a479ba1d012`).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The omission is the PCI1008 ID never being
added when PCI100X support landed in `a3282f84b2151` (six SKUs
1001–1006). PCI1008 is a later part.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Same series (msgid `20260714212010.230606-*`, based on v7.2-rc3,
applied to pci/switchtec for v7.3):
1. `8b326de3cc02c` dmaengine: switchtec-dma: Add PCI1008 device ID
(`-2`)
2. `0d8a6306c680e` PCI: switchtec: Add Microchip PCI1008 device ID
(`-3`)
3. `00a479ba1d012` this patch (`-4`, submitted as 3/3)
- This patch is standalone. The quirk is a PCI fixup, not a driver ID
table. It does not need the switchtec or switchtec-dma ID additions.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Logan Gunthorpe is listed maintainer of SWITCHTEC DMA
(`MAINTAINERS`) and a long-time switchtec contributor. Bjorn Helgaas
(PCI maintainer) signed off and applied the series.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Prerequisite in this tree: `SWITCHTEC_PCI100X_QUIRK` /
`PCI_VENDOR_ID_EFAR` table from `a3282f84b2151` — present.
- `quirk_switchtec_ntb_dma_alias()` and `pci_add_dma_alias()` — present.
- No other structural dependency. Can apply standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 00a479ba1d012` →
https://patch.msgid.link/20260714212010.230606-4-logang@deltatee.com
- Subject on list: `[PATCH v1 3/3] PCI: Add PCI1008 to switchtec NTB DMA
alias quirk`
- `b4 dig -a`: only v1. Cover letter `[PATCH v1 0/3] switchtec: add new
device IDs`.
- Direct lore.kernel.org HTTP fetch returned 403/Anubis; the thread was
recovered via `b4 dig -m`.
- Review: no NAKs. Sashiko noted a pre-existing `ep_map + 4` pointer
issue; Logan said it is unrelated and should not gate the series.
Bjorn: “Applied to pci/switchtec for v7.3, thanks!”
- No reviewer asked for `Cc: stable`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): Logan Gunthorpe, linux-pci, linux-kernel,
dmaengine, Vinod Koul, Bjorn Helgaas, Frank Li, Kelvin Cao (Microchip /
SWITCHTEC DMA co-maintainer). PCI and dmaengine maintainers were on the
original To/Cc.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot link. Cover letter: Logan originally had only
the dmaengine ID; Sashiko reminded him to add the management ID and the
NTB quirk, then he sent this 3-patch series. Hardware impact is
described in the patch, not in a separate user report.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Three independent 1-line ID additions (dmaengine, switchtec
management, NTB quirk). This quirk patch is self-contained. The other
two enable management/NTB userspace and the DMA engine; they are not
required for the IOMMU alias.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search for PCI1008 returned HTTP 403. No
stable discussion in the linux-pci mbox. UNVERIFIED whether anyone
requested this on stable@ after merge.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: No function body edited. New fixup entry invokes existing
`quirk_switchtec_ntb_dma_alias()`.
**Step 5.2: TRACE CALLERS**
Record: Not called in C. Registered with
`DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_EFAR, 0x1008,
PCI_CLASS_BRIDGE_OTHER, 8, ...)`. PCI core runs class FINAL fixups
during device setup, before typical driver probe. Context: boot/hotplug
enumeration, not IRQ.
**Step 5.3: TRACE CALLEES**
Record: `quirk_switchtec_ntb_dma_alias()` uses `pci_enable_device`,
`pci_iomap`, MMIO reads of NTB partition/proxy tables,
`pci_add_dma_alias()`, then unmap/disable. `pci_add_dma_alias()` sets
`dma_alias_mask` bits used to program IOMMU source IDs.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: PCI enumeration → class FINAL fixup → alias programming → IOMMU
group creation. Reachable only with PCI1008 hardware present.
Unprivileged userspace cannot trigger the quirk directly; a user of that
NTB/IOMMU path sees DMA failures if it is missing.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same pattern as PCI1001–PCI1006 in this file, and as many other
`pci_add_dma_alias` quirks (PLX NTB, Ricoh, Marvell, etc.). Adding
0x1008 is consistent with how every prior Switchtec/PCI100X ID was
handled.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `drivers/pci/quirks.c` has `SWITCHTEC_PCI100X_QUIRK` for
0x1001–0x1006. Without 0x1008, a PCI1008 NTB function would not get
aliases. `a3282f84b2151` (v6.14) added the table; this tree is 7.3-rc4,
so the table is present. `git merge-base --is-ancestor 00a479ba1d012
HEAD` is true (commit is already in 7.3-rc1); that is not treated as
“already selected for stable.”
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Expected apply: **clean**. Context is the existing PCI100X quirk
block, unchanged except for the new line. No refactor of this table
since it was added.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No alternate PCI1008 NTB alias fix. Companion IDs in
`switchtec.c` and `switchtec_dma.c` are the sibling series patches, not
substitutes for this quirk.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `[PCI quirks / Switchtec NTB DMA alias] [IMPORTANT]` — not core
mm/scheduler, but PCI IOMMU correctness for NTB. Affects systems with
this Microchip switch and IOMMU enabled.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: PCI quirks and switchtec are actively maintained (recent
pci/switchtec and pci/virtualization merges on this tree). The quirk
function itself has been stable since 2018; PCI100X IDs since v6.14.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver/hardware-specific: Microchip PCI1008 (vendor EFAR 0x1055,
device 0x1008) with NTB and IOMMU. Not universal.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Present whenever that device is enumerated with IOMMU on. Not a
race. Not triggerable by an unprivileged syscall on machines without the
hardware. Common for any PCI1008 NTB + IOMMU deployment.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: IOMMU rejects or mis-groups DMA from NTB proxy IDs → DMA
failures, IOMMU faults, broken peer NTB DMA. **HIGH** for that hardware;
not a generic panic.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** HIGH for PCI1008+IOMMU users (device works correctly
under IOMMU). Classic device-ID/quirk enablement.
- **Risk:** VERY LOW (1 line, existing macro, match is device-specific).
- **Ratio:** strongly favors backporting.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- PCI ID / hardware quirk on an existing table (stable exception).
- Real IOMMU DMA misdirection without the alias.
- 1 line, obviously correct, same pattern as PCI1001–1006.
- Prerequisite table exists in this 7.3 tree.
- Author is switchtec maintainer; PCI maintainer applied it.
- Standalone; no API change.
AGAINST:
- No `Reported-by` / production crash log (typical for ID additions).
- Audience is PCI1008 NTB + IOMMU, not all machines.
- Unrelated pre-existing `ep_map` pointer issue in the quirk function
(not caused by this line).
- Stable@ discussion could not be fetched (403).
UNRESOLVED:
- Whether stable@ discussed this after merge (lore.kernel.org/stable
403).
- Whether Logan later sent an `ep_map` fix (explicitly out of scope).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one-line ID, applied by PCI
maintainer after list review.
2. Fixes a real bug that affects users? **PASS** — PCI1008 NTB DMA under
IOMMU is wrong without the alias.
3. Important issue? **PASS** — IOMMU DMA correctness (faults /
misdirected DMA), HIGH for that hardware.
4. Small and contained? **PASS** — +1 line in `drivers/pci/quirks.c`.
5. No new features or APIs? **PASS** — device ID on an existing quirk;
allowed exception.
6. Can apply to the local tree? **PASS** — `SWITCHTEC_PCI100X_QUIRK` is
present; apply is clean.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Device ID addition** and **hardware quirk/workaround** (PCI
DMA alias quirk). These are listed as YES for stable.
**Step 9.4: MAKE YOUR DECISION**
This tree has the PCI100X quirk table. Adding PCI1008 is the same class
of change already used for PCI1001–1006. Without it, PCI1008 NTB DMA can
be misdirected under an IOMMU. The patch is one line, applies cleanly,
and does not need the rest of the series.
Verification:
- [Phase 1] `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion` → `7.3.0-rc4`. Tags: SOB Logan + Bjorn; Link to patch
3/3; no Fixes/stable/Reported-by.
- [Phase 2] `git show 00a479ba1d012`: +1 line
`SWITCHTEC_PCI100X_QUIRK(0x1008)` in `drivers/pci/quirks.c`.
- [Phase 2] Read `quirk_switchtec_ntb_dma_alias()`: enable, iomap, read
proxy IDs, `pci_add_dma_alias()`, table_sz 0/512 guards.
- [Phase 3] `git blame -L 6087,6096`: table from `a3282f84b2151`
(v6.14); 0x1008 from this commit.
- [Phase 3] `git merge-base --is-ancestor a3282f84b2151 v6.14` true; not
ancestor of v6.13. Original quirk `ad281ecf1c7d4` (2018) is in HEAD.
- [Phase 3] `git merge-base --is-ancestor 00a479ba1d012 v7.2` false;
ancestor of v7.3-rc1/rc4.
- [Phase 3] Series patches `8b326de3cc02c`, `0d8a6306c680e` are sibling
ID adds, not prerequisites of this quirk.
- [Phase 4] `b4 dig -c 00a479ba1d012` / `-a` / `-w` / `-m`: v1-only
3-patch series; Bjorn applied for v7.3; Vinod acked 1/3; no NAK;
Sashiko `ep_map` note treated as unrelated.
- [Phase 4] lore.kernel.org HTTP 403/Anubis; thread recovered via b4
mbox. stable@ search 403 — UNVERIFIED.
- [Phase 5] No C callers; `DECLARE_PCI_FIXUP_CLASS_FINAL` in
`include/linux/pci.h`; `pci_add_dma_alias` in `drivers/pci/pci.c`.
- [Phase 6] Local `quirks.c` has PCI100X table and (in this checkout)
the 0x1008 line. Companion IDs exist in `switchtec.c:1877` and
`switchtec_dma.c:1426`.
- [Phase 7] PCI subsystem maintainer Bjorn Helgaas; Logan maintains
SWITCHTEC DMA.
- [Phase 8] Failure mode: IOMMU DMA misdirection for PCI1008 NTB — HIGH
for that hardware; patch risk very low.
The change is a one-line PCI quirk ID. That is the standard stable
exception, it is obviously correct, and this tree already has the table
it extends.
**YES**
drivers/pci/quirks.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e8067ff59e2a5..e03a3831bcc00 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -6045,6 +6045,7 @@ SWITCHTEC_PCI100X_QUIRK(0x1003); /* PCI1003XG4 */
SWITCHTEC_PCI100X_QUIRK(0x1004); /* PCI1004XG4 */
SWITCHTEC_PCI100X_QUIRK(0x1005); /* PCI1005XG4 */
SWITCHTEC_PCI100X_QUIRK(0x1006); /* PCI1006XG4 */
+SWITCHTEC_PCI100X_QUIRK(0x1008); /* PCI1008XG4 */
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] net: stmmac: fix device node reference leaks in stmmac_mtl_setup()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (44 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] PCI: switchtec: Add Microchip PCI1008 to NTB DMA alias quirk Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/amdgpu: Validate ATPX buffer length before use Sasha Levin
` (470 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Md Rabbani, Jakub Kicinski, Sasha Levin, maxime.chevallier,
andrew+netdev, davem, edumazet, pabeni, mcoquelin.stm32,
alexandre.torgue, netdev, linux-stm32, linux-arm-kernel,
linux-kernel
From: Md Rabbani <rabbanyhmm@gmail.com>
[ Upstream commit 317fe168f4c0fc30e5c375c22d9c8911940aea9b ]
In stmmac_mtl_setup(), q_node is shared across the RX and TX queue
parsing loops. When the RX queue loop breaks early because the number
of parsed queues reaches plat->rx_queues_to_use, q_node retains an
acquired reference count. If the error check passes
(queue == plat->rx_queues_to_use), execution proceeds directly to the
TX queue loop, where of_get_next_child() immediately overwrites q_node
with the first TX child, permanently leaking the retained RX child
device node reference.
Switch both loops to for_each_child_of_node_scoped() so child node
references are automatically dropped upon loop exit or early break,
and remove the now-unnecessary function-scoped q_node variable and
its manual of_node_put() at the exit label.
Signed-off-by: Md Rabbani <rabbanyhmm@gmail.com>
Link: https://patch.msgid.link/20260821055718.57-1-rabbanyhmm@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The leak is real in this 6.12 tree: `stmmac_mtl_setup()` can drop an OF
child reference when RX queue parsing breaks early, and in-tree DTs
actually hit that path.
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: `[net: stmmac:] [fix] [OF device-node reference leaks in
stmmac_mtl_setup()]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- `Signed-off-by: Md Rabbani <rabbanyhmm@gmail.com>` (author)
- `Link:
https://patch.msgid.link/20260821055718.57-1-rabbanyhmm@gmail.com`
- `Signed-off-by: Jakub Kicinski <kuba@kernel.org>` (netdev
maintainer; applied to `netdev/net`)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence of Fixes/Cc-stable is expected for
this review)
- Upstream SHA (from patchwork bot):
`317fe168f4c0fc30e5c375c22d9c8911940aea9b`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record: [Bug] Shared `q_node` is used by both RX and TX
`for_each_child_of_node()` loops. An early `break` in the RX loop
leaves `q_node` holding a live OF reference. If `queue ==
plat->rx_queues_to_use`, the function continues into the TX loop,
which calls `of_get_next_child(tx_node, NULL)` and overwrites `q_node`
without putting the RX child.
- [Symptom] Permanent `device_node` refcount leak (kobject/`device_node`
never released).
- [Version info] None in the message. The loops date to 2017
(`d976a525c37127`, v4.12-rc1).
- [Root cause] Early-break + reused iterator; `of_get_next_child(parent,
NULL)` does not drop the previous pointer.
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: Not hidden. Subject/body explicitly describe a refcount leak.
The `_scoped` conversion is the fix mechanism, not a style-only
cleanup.
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- Record: Single file
`drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c`. Actual commit
is **+2 / -4**. Functions: `stmmac_mtl_setup()` only. Surgical,
single-file.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record:
- RX loop: `for_each_child_of_node(rx_node, q_node)` →
`for_each_child_of_node_scoped(...)`. Early `break` now auto-drops
the current child via `__free(device_node)`.
- TX loop: same conversion.
- Function-scope `struct device_node *q_node` removed;
`of_node_put(q_node)` at `out:` removed (would not compile with the
loop-scoped iterator).
- Probe/DT parse path only; no datapath change.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record: [Category] Reference counting / resource leak.
- [Mechanism] `for_each_child_of_node` is `of_get_next_child()`, which
gets `next` and puts `prev`. `break` skips the put of the current
node. Reusing the same pointer in the TX loop with `prev=NULL` leaks
that RX child. TX extra children were previously dropped by the
trailing `of_node_put(q_node)`; RX extra children were not.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record: Obviously correct. `for_each_child_of_node_scoped` exists in
this tree and is already used widely. `__free(device_node)` is `if
(_T) of_node_put(_T)`, so NULL at loop end is safe. Regression risk is
very low: no locking, no ABI, no behavior change besides dropping the
leaked ref. The `_scoped` form is stronger than a one-off
`of_node_put()` before the TX loop because it also covers TX early-
break without a manual put.
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Record: Buggy loops introduced by `d976a525c37127` ("net: stmmac:
multiple queues dt configuration", Joao Pinto, 2017-03-10), first in
**v4.12-rc1**. Present for many years. `goto out` / extra
`of_node_put(q_node)` added by `2ee2132ffb83e` (2018), which still
leaves the RX-then-TX overwrite leak.
**Step 3.2: FOLLOW THE FIXES: TAG**
- Record: No `Fixes:` tag. Introducer is `d976a525c37127`, and `git
merge-base --is-ancestor d976a525c37127 HEAD` succeeds. That code is
in this tree.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
- Record: Recent `stmmac_platform.c` work is unrelated (bus_id, probe
error path, IRQ). Historical OF leak fixes in this driver:
`a249708bc2aa1`, `d2ed0a7755fe1`, `4613b279bee79`. Standalone
`[PATCH]`, not `X/Y`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
- Record: `git log --author="Md Rabbani"` on this path is empty in this
tree (new contributor). Applied by Jakub Kicinski to `netdev/net.git`
(fixes tree), which is a strong maintainer signal.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
- Record: Depends on `for_each_child_of_node_scoped` /
`DEFINE_FREE(device_node)` (`34af4554fb0ce1` / `9448e55d032d99`,
2024-02-25). Both are already in this 6.12 tree (`git merge-base --is-
ancestor` succeeded). Can apply standalone. `stmmac_platform.c`
already includes `<linux/of.h>`, which includes `<linux/cleanup.h>`.
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record: `b4 dig -c <sha>` cannot match because `317fe168f4c0` is not
an ancestor of HEAD. Used msgid instead. Lore thread: `https://lore.ke
rnel.org/netdev/20260821055718.57-1-rabbanyhmm@gmail.com/`
- Series: single v1 `[PATCH]` (2 messages: submission + patchwork-bot).
Applied to `netdev/net.git (main)` as
`https://git.kernel.org/netdev/net/c/317fe168f4c0`. No v2, no NAK.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
- Record: To/Cc included STMMAC maintainers (Torgue, Coquelin,
Chevallier), netdev maintainers (Miller, Dumazet, Kicinski, Abeni),
`netdev@`, `linux-stm32@`, `linux-arm-kernel@`. No written review
comments; Kicinski applied it to the **net fixes** tree.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: No syzbot/bugzilla. Bug is from code inspection. Real in-tree
DTs trigger it (see Phase 6/8).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
- Record: Standalone. No other patches required.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
- Record: lore.kernel.org/stable search for `stmmac_mtl_setup` shows
older stmmac stable backports (probe error-path, MDIO, Tx COE), not
this leak. No prior rejection of this fix.
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
- Record: `stmmac_mtl_setup()` (modified). Helpers:
`for_each_child_of_node_scoped`, `of_get_next_child` /
`__of_get_next_child`, `of_node_put`.
**Step 5.2: TRACE CALLERS**
- Record: Only caller is `stmmac_probe_config_dt()` in the same file
(line 603). That is used via `devm_stmmac_probe_config_dt()` from many
glue drivers: `dwmac-rk`, `dwmac-qcom-ethqos`, `dwmac-imx`, `dwmac-
stm32`, `dwmac-sun8i`, `dwmac-mediatek`, `dwmac-generic`, and others.
Probe/init context, not IRQ/hot path.
**Step 5.3: TRACE CALLEES**
- Record: `of_parse_phandle`, `of_property_read_*`, `of_get_next_child`,
`of_node_put`. DT parse only.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: Userspace cannot trigger it directly. It runs on every DT-
based stmmac probe. Reachable on common ARM/ARM64 SoCs (Rockchip,
i.MX, STM32, Qualcomm, MediaTek). Leak fires when the RX config node
has more children than `snps,rx-queues-to-use`.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
- Record: Same file still has `for_each_child_of_node(np, mdio_node)` in
`stmmac_of_get_mdio()` (line 324); not the same shared-iterator bug.
In-tree DTs with extra RX children:
`arch/arm64/boot/dts/qcom/sa8540p-ride.dts` uses `snps,rx-queues-to-
use = <1>` with `queue0`–`queue3` on both ethernet0 and ethernet1.
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
- Record: Yes. This tree is **6.12.111** (`pending-6.12`,
`p-6.12-3-gc504cf0baa3d8`). Current code at `stmmac_platform.c:177` /
`:240` still uses unscoped loops and `of_node_put(q_node)` at `:293`.
`317fe168f4c0` is **not** an ancestor of HEAD. Bug present since
v4.12.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
- Record: Expected difficulty: **minor context conflicts**. Upstream
context has later `stmmac_axi_blen_to_mask` / `MTL_MAX_*` clamping
that 6.12 does not have. The three functional edits (two loop macros,
drop `q_node` + trailing put) match 6.12 1:1. Needs a small context-
adjusted backport, not a rewrite.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
- Record: No commit with this subject in this tree. Older stmmac
`of_node_put` fixes do not cover this iterator reuse.
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
- Record: [Subsystem] `drivers/net/ethernet/stmicro/stmmac` (Synopsys
DWMAC). [Criticality] **IMPORTANT** — common platform Ethernet on many
SoCs, not core mm/VFS, not staging.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
- Record: Actively maintained (many recent stmmac fixes on this branch).
The leak itself is old (2017), not a new-feature bug.
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
- Record: Driver/config-specific: `CONFIG_STMMAC_ETH` +
`CONFIG_STMMAC_PLATFORM` + DT `snps,mtl-rx-config` with extra child
nodes. Confirmed affected in-tree board: Qualcomm SA8540P Ride
(`sa8540p-ride.dts`). Many other boards have matching child counts and
do not leak.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
- Record: Device probe (and every unbind/rebind). Common on boards whose
DT lists more queue children than `snps,rx-queues-to-use`. Not a
userspace syscall; not a race. Extra TX children were already put at
`out:`; extra RX children leak.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
- Record: [Failure] One `device_node` ref leak per probe when extra RX
children exist. [Severity] **MEDIUM** — not oops/deadlock/corruption,
but a real lifetime leak of an OF kobject. Repeatable on module
reload. Can pin overlay/node teardown.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
- Record: Benefit: medium (fixes a real, DT-triggered leak on a widely
used NIC driver, including an in-tree Qualcomm board). Risk: **very
low** (2 insertions / 4 deletions, existing helper, probe-only). Ratio
favors backport.
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OF refcount leak, mechanism verified against
`of_get_next_child()` / `__of_get_next_child()`.
- Buggy code is in this 6.12 tree and has been since v4.12.
- In-tree DT `sa8540p-ride.dts` has 4 RX queue children with `rx-queues-
to-use = <1>` — the leak path is not theoretical.
- Tiny, obviously correct fix; helper already in 6.12.
- Applied to `netdev/net` (fixes) by Kicinski.
- Same class of bug as prior stmmac `of_node_put` fixes already in
history.
- No new API/feature; no series dependency.
AGAINST:
- Probe-time leak of a single node, not a crash/UAF/security issue.
- Surrounding file context differs slightly from mainline, so `git am`
of the raw mainline diff may need a trivial refresh.
- No user crash report / syzbot.
UNRESOLVED:
- No written mailing-list review beyond maintainer application (v1
accepted as-is).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — scoped put on break/exit is
the intended helper; applied to netdev/net.
2. Fixes a real bug that affects users? **PASS** — leak on probe;
triggered by in-tree Qualcomm DT.
3. Important issue? **PASS** at medium importance — resource leak, not
panic, but a genuine lifetime bug in a common Ethernet driver.
4. Small and contained? **PASS** — +2/-4, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — same loops exist; scoped
macro exists; minor context tweak only.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
- Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary small
bugfix.
**Step 9.4: DECISION**
Backport to this 6.12 tree. The bug exists here, the helper exists here,
the fix is surgical, and at least one in-tree board hits it.
---
### What the commit solves and why it matters here
`stmmac_mtl_setup()` parses `snps,mtl-rx-config` / `snps,mtl-tx-config`
at probe. The RX iterator `break`s once `queue >=
plat->rx_queues_to_use`, leaving `q_node` referenced. The TX loop then
starts with `of_get_next_child(tx_node, NULL)`, which never puts that RX
child. That is a permanent OF node leak.
`arch/arm64/boot/dts/qcom/sa8540p-ride.dts` is written exactly that way
(1 queue in use, 4 queue child nodes).
### Stable rules / risk
Meets the rules: small, obviously correct, no new API, real leak, helper
already in 6.12. Risk is a possible trivial context conflict around
later mainline-only `stmmac_platform.c` edits; the functional change
does not depend on those.
### Verification
- [Phase 1] Parsed tags: author SOB, msgid Link, Kicinski SOB; no
Fixes/Reported-by; upstream `317fe168f4c0`
- [Phase 2] Diff: +2/-4 in `stmmac_mtl_setup()`; two loops to `_scoped`;
drop `q_node` + `of_node_put(q_node)`
- [Phase 2] `__of_get_next_child()` does `of_node_get(next);
of_node_put(prev)` (`drivers/of/base.c:600-603`); `prev=NULL` does not
put the overwritten pointer
- [Phase 3] Blame: loops from `d976a525c37127` (v4.12-rc1); ancestor of
HEAD
- [Phase 3] `34af4554fb0ce1` / `DEFINE_FREE(device_node)` are ancestors
of HEAD
- [Phase 3] `git merge-base --is-ancestor 317fe168f4c0 HEAD` failed (fix
not in this tree)
- [Phase 4] `b4 mbox` msgid: 2-message thread; applied to netdev/net; no
NAK
- [Phase 4] stable lore search: no discussion of this leak
- [Phase 5] Caller: `stmmac_probe_config_dt()` → many `dwmac-*` platform
probes
- [Phase 6] `git describe HEAD` / `make kernelversion`: 6.12.111
`pending-6.12`; buggy loops still present at lines 177 and 240
- [Phase 6] `sa8540p-ride.dts` `ethernet0_mtl_rx_setup` /
`ethernet1_mtl_rx_setup`: `rx-queues-to-use = <1>` with queue0–queue3
- [Phase 8] Failure mode: OF `device_node` leak at probe, severity
MEDIUM
- UNVERIFIED: Could not use `b4 dig -c` against HEAD (commit not in this
checkout); lore HTML fetch returned 403, raw/mbox succeeded
**YES**
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 0cb51935c4056..ceb913a3a6c69 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -131,7 +131,6 @@ static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev)
static int stmmac_mtl_setup(struct platform_device *pdev,
struct plat_stmmacenet_data *plat)
{
- struct device_node *q_node;
struct device_node *rx_node;
struct device_node *tx_node;
u8 queue = 0;
@@ -174,7 +173,7 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
/* Processing individual RX queue config */
- for_each_child_of_node(rx_node, q_node) {
+ for_each_child_of_node_scoped(rx_node, q_node) {
if (queue >= plat->rx_queues_to_use)
break;
@@ -237,7 +236,7 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
queue = 0;
/* Processing individual TX queue config */
- for_each_child_of_node(tx_node, q_node) {
+ for_each_child_of_node_scoped(tx_node, q_node) {
if (queue >= plat->tx_queues_to_use)
break;
@@ -290,7 +289,6 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
out:
of_node_put(rx_node);
of_node_put(tx_node);
- of_node_put(q_node);
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: Validate ATPX buffer length before use
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (45 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] net: stmmac: fix device node reference leaks in stmmac_mtl_setup() Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] remoteproc: core: Full attach detach during recovery Sasha Levin
` (469 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Lijo Lazar, Alex Deucher, Sasha Levin, christian.koenig, airlied,
simona, amd-gfx, dri-devel, linux-kernel
From: Lijo Lazar <lijo.lazar@amd.com>
[ Upstream commit 916867cd75dbbc383aa6cb724556de769912157a ]
Add amdgpu_atpx_buffer_validate() to check that the returned ACPI
buffer is of type ACPI_TYPE_BUFFER, is large enough to hold the u16
size field, and that the BIOS-reported size does not exceed the actual
allocation length or fall below the minimum required by the caller.
Use it in VERIFY_INTERFACE and GET_PX_PARAMETERS callers.
Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Assisted-by: Claude Sonnet (Cursor AI)
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: the 6.18.y tree still has the unvalidated ATPX
ACPI path, and the patch is a small, self-contained memory-safety fix.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: [drm/amdgpu] [Validate] [Check ACPI ATPX response buffer type
and length before reading the BIOS-reported size and memcpy]
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> (author)
- Assisted-by: Claude Sonnet (Cursor AI)
- Acked-by: Alex Deucher <alexander.deucher@amd.com> (amdgpu maintainer)
- Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
- (pipeline) Signed-off-by: Sasha Levin — ignored per instructions
- (pipeline) `[ Upstream commit 916867cd75dbbc383aa6cb724556de769912157a
]` — ignored per instructions
- No Fixes:, Reported-by:, Tested-by:, Link:, or Cc: stable (absence
expected)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: ATPX ACPI responses are used without checking object type, that
the allocation is large enough to hold the leading `u16` size field,
or that the BIOS-reported size is within the real ACPI buffer.
- Symptom/failure mode: out-of-bounds read and/or NULL dereference when
firmware returns a short buffer, a claimed size larger than
`buffer.length`, or a non-buffer object.
- Version information: none in the message. History shows the pattern
dates to the original amdgpu ATPX code (2015).
- Root cause: callers did `size = *(u16 *)info->buffer.pointer` then
`memcpy(..., min(sizeof(output), size))` with only a minimum-size
check on the BIOS-reported value, never on ACPI type/`buffer.length`.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. The subject and body describe a memory-safety
validation fix. It is not cleanup or a feature.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c` (+21 / −12)
- Functions: new `amdgpu_atpx_buffer_validate()`; modified
`amdgpu_atpx_validate()`, `amdgpu_atpx_verify_interface()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Hunk 1: add helper that requires non-NULL object, `ACPI_TYPE_BUFFER`,
`buffer.length >= 2`, `buffer.length >= claimed u16 size`, and
`claimed size >= min_size`. `&&` short-circuit makes the `u16` load
safe.
- Hunk 2 (`amdgpu_atpx_validate` / GET_PX_PARAMETERS): old path zeroed
`output`, loaded claimed size, rejected only `size < 10`, then
`memcpy` of `min(sizeof(output), size)`. New path validates first,
then the same bounded copy. `sizeof(struct atpx_px_params)` is 10
(`u16+u32+u32`, packed), so the minimum is unchanged for valid
firmware.
- Hunk 3 (`amdgpu_atpx_verify_interface`): same, replacing hardcoded
`size < 8` with `sizeof(struct atpx_verify_interface)` which is also
8.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- Category: memory safety — OOB read and possible NULL deref on
firmware-controlled ACPI data
- Mechanism:
1. No type check. `union acpi_object` overlays `integer` and `buffer`.
An INTEGER 0 makes `buffer.length` 0 and `buffer.pointer` NULL →
`*(u16 *)NULL` oops.
2. No `buffer.length >= sizeof(u16)` check → OOB 2-byte read on
empty/short buffers.
3. memcpy used BIOS size capped only by `sizeof(output)`, not by
`buffer.length`. Example: length=4, claimed size=10 → copy 10 bytes
from a 4-byte buffer.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct; check order is right; min sizes match the old
hardcoded 8/10.
- Minimal; no API change.
- Regression risk is low: it only rejects responses that were already
type-confused or out of bounds. A BIOS that “worked” only because
memcpy read extra heap bytes was already relying on undefined
behavior.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Buggy loads/memcpy introduced in `d38ceaf99ed015` (“drm/amdgpu:
add core driver (v4)”, 2015-06-03), first in v4.2-rc1. Present for the
entire life of amdgpu ATPX. printk→pr_err only in `07867a78f88465`
(2023).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag (expected). Introducing commit is in this tree
(`git merge-base --is-ancestor d38ceaf99ed015 HEAD` succeeded).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Sibling series patch 1/2 is `c8373721c3e54` “Validate ATIF
buffer length before use” on `amdgpu_acpi.c`. Independent file. Other
recent ATPX commits are unused-function removal and printk conversion,
not prerequisites. Standalone.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Lijo Lazar is a regular AMD contributor (bounds checks, reset,
ACPI). Maintainer Acked-by/SOB from Alex Deucher.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Submitted as PATCH 2/2 with ATIF 1/2. No shared symbols or
types. ATPX applies alone. radeon still has the old pattern in
`radeon_atpx_handler.c`; that is out of scope, not a dependency.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 916867cd75db...` and local SHA: lore.kernel.org returned
errors; no b4 match.
- Fallback: https://www.mail-archive.com/amd-
gfx@lists.freedesktop.org/msg145005.html (PATCH 2/2, 2026-06-14)
- Review: https://www.mail-archive.com/amd-
gfx@lists.freedesktop.org/msg145042.html — Alex Deucher: “Series is:
Acked-by”
- Series: v1 only; no v2/v3; no NAK; no reviewer Cc: stable
- Freedesktop June 2026 index lists the submission and Deucher’s ack
only
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Maintainer Alex Deucher acked the series. Recipients from mail-
archive: amd-gfx. b4 -w failed (lore error).
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by, syzbot, bugzilla, or CVE found. Code-review
hardening against malformed ACPI, not a user reproducer.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 1/2 ATIF (`amdgpu_acpi.c`) is the same class of fix. ATIF
already had `obj->type != ACPI_TYPE_BUFFER`; ATPX `amdgpu_atpx_call()`
never checked type. ATPX does not need 1/2.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned 403. Web search did not
show a prior stable discussion of this subject. UNVERIFIED whether
anyone already requested or rejected it for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `amdgpu_atpx_buffer_validate` (new), `amdgpu_atpx_validate`,
`amdgpu_atpx_verify_interface`
**Step 5.2: TRACE CALLERS**
Record:
- `amdgpu_atpx_verify_interface` / `amdgpu_atpx_validate` ←
`amdgpu_atpx_init()` ← `amdgpu_atpx_detect()` when ATPX exists and
there are two VGA-class devices ← `amdgpu_register_atpx_handler()` ←
`amdgpu_init()` in `amdgpu_drv.c` (module init)
- Gated by `CONFIG_VGA_SWITCHEROO` (x86 + ACPI + PCI hybrid-laptop GPU
switching)
**Step 5.3: TRACE CALLEES**
Record: `amdgpu_atpx_call()` → `acpi_evaluate_object(...,
ACPI_ALLOCATE_BUFFER)`. On failure other than `AE_NOT_FOUND` it frees
and returns NULL. Success and `AE_NOT_FOUND` return `buffer.pointer`
with **no type check**. Callers only test `if (!info)`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable on amdgpu module load on hybrid PX laptops. Not a
syscall hot path; it is a common boot/probe path for those machines.
Unprivileged users do not trigger it directly; a crash still takes down
the GPU/driver init (and can oops the kernel).
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Identical unvalidated pattern remains in
`drivers/gpu/drm/radeon/radeon_atpx_handler.c`. ATIF now validates type
and both sizes. Confirms a systematic ACPI-buffer issue; this patch
covers amdgpu ATPX only.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: `git describe HEAD` = `v6.18.53-5049-g0f0bdc2b0dffb`;
`Makefile` 6.18.53; branch `autosel`
- Candidate is **not** in `v6.18.53` (`merge-base --is-ancestor` failed)
- `v6.18.53:drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c` still has
`size = *(u16 *) info->buffer.pointer` / `size < 10` / `size < 8`
- `git diff v6.18.53 9d367fab451d9^ -- amdgpu_atpx_handler.c` is empty:
pre-fix file matches 6.18.53
- Bug introduced v4.2; present in this series
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply. Same file content as the commit’s parent. No
refactor since 6.18.53 on these functions.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier ATPX buffer-length fix in this file’s history besides
the candidate. ATIF sibling is also not in v6.18.53; not required.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: [drm/amdgpu ATPX / vga_switcheroo] [IMPORTANT — common x86
hybrid AMD laptop path, not core mm/vfs, not staging]
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: amdgpu is actively developed; this ATPX file is mature (2015)
with occasional quirks. Long-lived bug, not a recent-feature regression.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific + config-specific: `CONFIG_VGA_SWITCHEROO`
amdgpu users on hybrid PX systems (two GPUs, ATPX ACPI method). Typical
of 2008–2010s and some later A+A laptops. Distro kernels usually enable
VGA_SWITCHEROO on x86.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Module init / ATPX detect. Needs ATPX plus a malformed ACPI
return (wrong type, length < 2, or claimed size > actual). No evidence
an unprivileged user can inject ACPI here; buggy/malicious firmware can.
No public reproducer. Severity if it hits is a boot-time oops, not a
rare runtime race.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: NULL deref or OOB read during GPU/hybrid init → kernel oops.
Severity HIGH (crash). Not confirmed privilege escalation. Not data
corruption.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: medium-high for hybrid AMD laptops; prevents oops on bad ATPX
data; completes validation the driver already attempted.
- Risk: very low (one helper, two call sites, min sizes unchanged).
- Ratio: favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB read / possible NULL deref on ACPI ATPX responses
- Incomplete size check since 2015, present in 6.18.53
- Small, obviously correct, maintainer-acked
- Applies cleanly; no new API; no series dependency
- Boot path on hybrid laptops, not dead code
AGAINST:
- No user/syzbot report
- Trigger needs bad firmware
- ATPX is a shrinking hybrid-laptop population
- Same bug still in radeon (unrelated)
UNRESOLVED:
- b4/lore 403; no stable-list discussion confirmed
- No known machine that actually returns a short/wrong-type ATPX object
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — helper logic is sound;
Acked-by amdgpu maintainer
2. Fixes a real bug that affects users? **PASS** — missing type/length
checks; crash if firmware is wrong
3. Important issue? **PASS** — oops/OOB, HIGH; not a feature
4. Small and contained? **PASS** — +21/−12, one file
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — v6.18.53 has the buggy code;
diff would apply cleanly
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. Standard memory-
safety bug fix.
**Step 9.4: MAKE YOUR DECISION**
This belongs on 6.18.y. The tree still trusts BIOS-reported ATPX sizes
without checking ACPI object type or real buffer length. That can oops
at amdgpu init on hybrid systems. The fix is tiny, matches existing
mins, and was acked by the maintainer.
### What the commit solves for this tree
On `v6.18.53`, `amdgpu_atpx_verify_interface()` and GET_PX_PARAMETERS
still do `*(u16 *)info->buffer.pointer` and memcpy without confirming
`ACPI_TYPE_BUFFER` or that `buffer.length` covers the claimed size.
Wrong-type INTEGER 0 is a NULL deref; a short buffer or oversized
claimed length is an OOB read. Stable 6.18 users of hybrid AMD laptops
hit this on module load if firmware is buggy.
### Risk vs benefit
Benefit is avoiding a probe-time oops. Risk is a few lines of stricter
validation that valid ATPX responses already satisfy (`sizeof` 8 and
10). Sibling ATIF patch is not required.
### Concerns
No field report. radeon is still unfixed. Neither blocks backporting
this amdgpu change.
Verification:
- [Phase 1] Tags: author SOB, Assisted-by Claude, Acked-by/SOB Alex
Deucher; no Fixes/Reported-by/Cc stable
- [Phase 2] Diff: +21/−12 in one file; helper plus two call sites; min
8/10 preserved via sizeof
- [Phase 2] `union acpi_object` in `include/acpi/actypes.h`: INTEGER vs
BUFFER overlay confirmed
- [Phase 3] blame: `d38ceaf99ed015` (v4.2-rc1); in this tree
- [Phase 3] parent is ATIF 1/2 on a different file; ATPX standalone
- [Phase 4] b4 dig failed (lore error); mail-archive PATCH 2/2 + Deucher
series ack
- [Phase 4] No stable-list hit (lore 403) — UNVERIFIED
- [Phase 5] Call chain: amdgpu_init → register_atpx_handler → detect →
init → verify/validate; CONFIG_VGA_SWITCHEROO
- [Phase 5] `amdgpu_atpx_call` has no type check (unlike ATIF)
- [Phase 5] Same bug still in `radeon_atpx_handler.c`
- [Phase 6] `git describe HEAD`: v6.18.53-5049; candidate not in
v6.18.53; buggy code present; empty diff vs parent file
- [Phase 8] Failure mode: oops/OOB on ATPX probe, HIGH; trigger = hybrid
PX + bad ACPI
- UNVERIFIED: no concrete BIOS reproducer; no CVE
**YES**
.../gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 33 ++++++++++++-------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 3893e6fc2f037..e2a4644896ca8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -89,6 +89,15 @@ bool amdgpu_is_atpx_hybrid(void)
return amdgpu_atpx_priv.atpx.is_hybrid;
}
+static bool amdgpu_atpx_buffer_validate(const union acpi_object *obj,
+ size_t min_size)
+{
+ return obj && obj->type == ACPI_TYPE_BUFFER &&
+ obj->buffer.length >= sizeof(u16) &&
+ obj->buffer.length >= *(u16 *)obj->buffer.pointer &&
+ *(u16 *)obj->buffer.pointer >= min_size;
+}
+
/**
* amdgpu_atpx_call - call an ATPX method
*
@@ -179,15 +188,15 @@ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
if (!info)
return -EIO;
- memset(&output, 0, sizeof(output));
-
- size = *(u16 *) info->buffer.pointer;
- if (size < 10) {
- pr_err("ATPX buffer is too small: %zu\n", size);
+ if (!amdgpu_atpx_buffer_validate(info, sizeof(output))) {
+ pr_err("Invalid ATPX GET_PX_PARAMETERS response\n");
kfree(info);
return -EINVAL;
}
- size = min(sizeof(output), size);
+
+ memset(&output, 0, sizeof(output));
+
+ size = min(sizeof(output), (size_t)*(u16 *)info->buffer.pointer);
memcpy(&output, info->buffer.pointer, size);
@@ -258,15 +267,15 @@ static int amdgpu_atpx_verify_interface(struct amdgpu_atpx *atpx)
if (!info)
return -EIO;
- memset(&output, 0, sizeof(output));
-
- size = *(u16 *) info->buffer.pointer;
- if (size < 8) {
- pr_err("ATPX buffer is too small: %zu\n", size);
+ if (!amdgpu_atpx_buffer_validate(info, sizeof(output))) {
+ pr_err("Invalid ATPX VERIFY_INTERFACE response\n");
err = -EINVAL;
goto out;
}
- size = min(sizeof(output), size);
+
+ memset(&output, 0, sizeof(output));
+
+ size = min(sizeof(output), (size_t)*(u16 *)info->buffer.pointer);
memcpy(&output, info->buffer.pointer, size);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] remoteproc: core: Full attach detach during recovery
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (46 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/amdgpu: Validate ATPX buffer length before use Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] ksmbd: fix off-by-one rejecting minimal COPYCHUNK query-limits request Sasha Levin
` (468 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Tanmay Shah, Mathieu Poirier, Sasha Levin, andersson,
linux-remoteproc, linux-kernel
From: Tanmay Shah <tanmay.shah@amd.com>
[ Upstream commit d93ffd549fb4df18c934ca7a47d4128a18c718cb ]
Current attach on recovery mechanism loads the clean resource table
during recovery, but doesn't re-allocate the resources. RPMsg
communication will fail after recovery due to this. Fix this
incorrect behavior by doing the full detach and attach of remote
processor during the recovery. This will load the clean resource table
and re-allocate all the resources, which will set up correct vring
information in the resource table.
Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
Link: https://lore.kernel.org/r/20260630004806.3835488-2-tanmay.shah@amd.com
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **v7.3-rc4** (mainline). The buggy attach-on-recovery
path exists here (since v6.1), and the change is a small, real recovery-
path fix: after a remoteproc crash, RPMsg stays dead because vrings are
not reallocated.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [remoteproc/core] [fix disguised as “Full attach detach”] [do a
full detach+cleanup+attach on crash recovery so resources/vrings are
reallocated]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Tanmay Shah \<tanmay.shah@amd.com\> (author)
- Link:
https://lore.kernel.org/r/20260630004806.3835488-2-tanmay.shah@amd.com
- Signed-off-by: Mathieu Poirier \<mathieu.poirier@linaro.org\>
(remoteproc maintainer)
- No Fixes:, Reported-by, Tested-by, Reviewed-by, Acked-by, or Cc:
stable (absence of Fixes/Cc:stable is expected for this review)
- Message-ID numbering `...-2-...` shows this is patch 1/2 of a series
(cover is -1, xlnx crash detection is -3)
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: attach-on-recovery loads a clean resource table but does **not**
re-allocate resources.
- Symptom: **RPMsg communication fails after recovery**.
- Root cause: `__rproc_attach()` only prepares/attaches/starts
subdevices; it does not call `rproc_handle_resources()` /
`rproc_alloc_registered_carveouts()`, so vring addresses in the
resource table stay invalid (0xffffffff after reset).
- Failure mode: IPC to the coprocessor remains broken until Linux is
rebooted, even though recovery “succeeded”.
- Version info: none in the message. Feature dates to v6.1
(`ba194232edc03`).
Step 1.4: DETECT HIDDEN BUG FIXES
Record: This is an explicit functional bug fix, not a disguised cleanup.
The extra teardown lines look like “cleanup” but they are the missing
half of `rproc_detach()` so `rproc_attach()` can rebuild vrings.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/remoteproc/remoteproc_core.c` (+14 / -1)
- Function: `rproc_attach_recovery()` only
- Scope: single-file surgical fix
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record: Before: `__rproc_detach()` then `__rproc_attach()`. After:
`__rproc_detach()`, then the same teardown
`rproc_detach()`/`__rproc_shutdown()` already use
(`rproc_resource_cleanup`, `rproc_unprepare_device`,
`rproc_disable_iommu`, free `cached_table`), then `rproc_attach()` which
re-enables IOMMU, prepares the device, loads the resource table, handles
resources, allocates carveouts, and calls `__rproc_attach()`.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [Logic / correctness] Incomplete recovery left virtio/RPMsg
resources stale. Full resource teardown + `rproc_attach()` rebuilds
vrings. Not UAF/leak/race/overflow.
Step 2.4: ASSESS THE FIX QUALITY
Record: Obviously correct: the new block is copied from `rproc_detach()`
/ `__rproc_shutdown()`. `rproc_attach()` is `static` in this file and
does **not** take `rproc->lock`, so calling it from
`rproc_trigger_recovery()` (which already holds the lock) is not a
deadlock. Regression risk is low-medium: recovery now unregisters virtio
devices and frees carveouts instead of only resetting subdevices; that
is the intended repair. No API/data-structure change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: Buggy `rproc_attach_recovery()` introduced in `ba194232edc03`
(“remoteproc: Support attach recovery after rproc crash”, Peng Fan,
2022-09-28). First appears in **v6.1-rc1**. Present in this tree (`git
merge-base --is-ancestor ba194232edc03 HEAD` → yes).
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. The introducing commit is `ba194232edc03`
(verified by blame and `git show`). Enabled for hardware by
`6eed169c7fefd` (imx_rproc, i.MX8QM/QXP).
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Standalone core fix. Same-series follow-up `5ae3dc0788746`
(“remoteproc: xlnx: Add crash detection mechanism”) is a **new xlnx
feature** and is **not** required for this core change. Later core
commits (`026a3fada4326`, crash/rproc_del races) do not revert or
rewrite this recovery path. Earlier attach error-path leak fixes
(`7692c9fbedd90`, `bcd241230fdbc`) already exist in this tree and make
`rproc_attach()` safer on failure.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Tanmay Shah is the AMD/Xilinx remoteproc contributor, not the
subsystem maintainer. Maintainer Mathieu Poirier merged it. Related work
is xlnx attach/detach and crash detection, not a pile of hidden core
prerequisites.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Needs `rproc_attach()`, `rproc_resource_cleanup()`,
`rproc_unprepare_device()`, `rproc_disable_iommu()`, and
`rproc_attach_recovery()` — all present here. Can apply standalone. Does
**not** need series patch 2.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record: `b4 dig -c d93ffd549fb4d` →
https://patch.msgid.link/20260630004806.3835488-2-tanmay.shah@amd.com
Revisions: RFC (2025-10-02) → several v1–v4 shapes → v5 (2026-06-10) →
**v6 applied** (2026-06-29).
RFC review (Mathieu Poirier): do not mix `__rproc_detach` with
`rproc_attach`; resource-table reset already happens in detach. Author
replied that `__rproc_attach()` never calls `rproc_handle_resources()` /
`rproc_alloc_registered_carveouts()`, so vrings stay unset and RPMsg
cannot start. v3 tried public `rproc_detach()`+`rproc_boot()`
(lock/state mess). v5/v6 inlined `rproc_detach()`’s cleanup and called
`rproc_attach()` (no extra lock). Mathieu applied v6 with “Applied.” No
NAK on the committed version. No reviewer Cc:stable.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: To/Cc: Bjorn Andersson, Mathieu Poirier, linux-remoteproc,
linux-kernel. Maintainer applied it. No extra Reviewed-by.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Author hit it on AMD-Xilinx attach-on-
recovery. Independent in-tree user: i.MX8QM/QXP
(`imx_rproc_partition_notify` → `rproc_report_crash()` on partition
reboot).
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: v6 0/2 “remoteproc: xlnx: remote crash recovery”. Patch 2 adds
xlnx crash reporting via resource table + mailbox. This patch is self-
contained for existing `RPROC_FEAT_ATTACH_ON_RECOVERY` users.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No stable-list discussion of this subject found. UNVERIFIED:
lore.kernel.org HTTP fetch returned 403; used `b4 dig`, mbox, and
openwall instead.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `rproc_attach_recovery()`; callees added:
`rproc_resource_cleanup`, `rproc_unprepare_device`,
`rproc_disable_iommu`, `rproc_attach`.
Step 5.2: TRACE CALLERS
Record:
- `rproc_attach_recovery()` ← `rproc_trigger_recovery()` when
`RPROC_FEAT_ATTACH_ON_RECOVERY` is set
- `rproc_trigger_recovery()` ← `rproc_crash_handler_work()` (automatic),
sysfs `recovery`, debugfs recovery
- Feature set in `imx_rproc.c` (i.MX8QM/QXP, not Linux-owned core) and
`xlnx_r5_remoteproc.c` (this series’ patch 2)
Step 5.3: TRACE CALLEES
Record: Teardown matches `rproc_detach()`. `rproc_attach()` does IOMMU,
prepare, `rproc_set_rsc_table`, `rproc_handle_resources`, carveouts,
`__rproc_attach`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Reachable from userspace (sysfs/debugfs) and from hardware (i.MX
SCU reboot IRQ; xlnx mailbox crash report). Not a theoretical-only path.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Boot recovery still uses `rproc_stop()` + `rproc_start()` and
keeps existing allocations; attach recovery must rebuild host-side
mappings because the remote rebooted itself. No sibling copy-paste bug.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Tree is **Linux 7.3.0-rc4** (`git describe HEAD` →
`v7.3-rc4-27-gf0100363d8c37`). `rproc_attach_recovery()` exists; bug
introduced v6.1. Pre-image of this commit is `__rproc_detach()` +
`__rproc_attach()`.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply on this tree: `rproc_attach()` is already a same-
file static helper; teardown helpers exist. Expected difficulty: clean
apply.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No earlier equivalent fix. This commit is the fix. `git merge-
base --is-ancestor d93ffd549fb4d HEAD` is true because this is mainline
that already merged it; that is not used as circular “already selected”
reasoning.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [drivers/remoteproc] [IMPORTANT for SoCs with coprocessors using
RPMsg; not core mm/VFS]. Affects i.MX8QM/QXP and Xilinx R5 attach-on-
recovery.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature core with ongoing platform work. Attach-on-recovery
itself has been in place since v6.1, so this is a long-standing hole,
not a brand-new API.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver/config-specific: `CONFIG_REMOTEPROC` platforms with
`RPROC_FEAT_ATTACH_ON_RECOVERY` (i.MX8QM/QXP; Xilinx R5 after patch 2).
Not universal.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Remote core crash/watchdog + recovery enabled. i.MX: SCU
partition reboot IRQ. Also sysfs/debugfs `recover`. Unprivileged users
typically cannot trigger unless debugfs/sysfs is exposed.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Host kernel does not oops. RPMsg/virtio IPC stays dead after
“successful” recovery until Linux reboot. Severity: **HIGH** for those
SoCs (recovery feature is non-functional), not CRITICAL host crash.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record: Benefit: restores the documented attach-on-recovery path (real
i.MX and Xilinx users). Risk: ~15 lines, copies existing detach
teardown, no new lock. Ratio: favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real user-visible bug: RPMsg fails after attach-on-recovery (author
reproduced; mechanism verified in `__rproc_attach()` vs
`rproc_attach()`).
- Bug in code since v6.1; i.MX8QM/QXP already uses the feature and
reports crash on partition reboot.
- Small, surgical, mirrors `rproc_detach()` then `rproc_attach()`.
- No deadlock: `rproc_attach()` does not take `rproc->lock`.
- Maintainer applied v6 after RFC/v3 locking mistakes were dropped.
- No new APIs; standalone without series patch 2.
AGAINST:
- Not a host oops/UAF/security issue.
- Series also adds xlnx crash detection (feature); this patch is still a
core correctness fix.
- Recovery path is not universal.
- Initial maintainer concern about mixing `__rproc_detach` and
`rproc_attach`; committed form inlines detach cleanup instead of
taking the public `rproc_detach()` lock/state path (the correct choice
under `rproc_trigger_recovery()`’s mutex).
UNRESOLVED:
- lore.kernel.org HTTP 403; discussion recovered via b4/mbox/openwall.
- No public i.MX user report independent of the Xilinx series (code path
still real).
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — teardown copied from
`rproc_detach()`; author tested RPMsg recovery; maintainer applied
v6.
2. Fixes a real bug that affects users? **PASS** — attach-on-recovery
leaves RPMsg dead; i.MX8 and Xilinx hit this path.
3. Important issue? **PASS** — recovery is supposed to restore IPC;
without this, a coprocessor watchdog forces a Linux reboot. Not a
host panic, but a serious functional break on those SoCs.
4. Small and contained? **PASS** — 15 lines, one function.
5. No new features or APIs? **PASS** — repairs existing recovery.
6. Can apply to the local tree? **PASS** — helpers and
`rproc_attach_recovery()` exist in 7.3-rc4.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID/quirk/DT/build/doc exception). Qualifies
as a normal small bug fix.
Step 9.4: MAKE YOUR DECISION
This tree has the attach-on-recovery bug. The patch is a small, verified
repair of that path. It should be backported here.
Verification:
- [Phase 1] Tags: author SOB, maintainer SOB, lore Link
`20260630004806.3835488-2`; no Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: +14/-1 in `rproc_attach_recovery()`; `__rproc_attach`
→ cleanup + `rproc_attach`
- [Phase 2] Confirmed `rproc_attach()` is static and does not take
`rproc->lock` (no deadlock with `rproc_trigger_recovery()`)
- [Phase 2] Cleanup matches `rproc_detach()` / `__rproc_shutdown()` in
the same file
- [Phase 3] `git blame`: buggy function from `ba194232edc03` (v6.1-rc1)
- [Phase 3] `git merge-base --is-ancestor ba194232edc03 HEAD` → 0
(present)
- [Phase 3] imx enable: `6eed169c7fefd`; crash trigger:
`imx_rproc_partition_notify()` → `rproc_report_crash()`
- [Phase 3] Series patch 2 `5ae3dc0788746` is xlnx crash detection, not
a prerequisite
- [Phase 4] `b4 dig -c d93ffd549fb4d`: msgid.link for v6 1/2; `-a`
RFC→v6; `-w` Andersson/Poirier/linux-remoteproc
- [Phase 4] mbox: Mathieu “Applied.” on v6; RFC explained missing
`rproc_handle_resources()`
- [Phase 4] lore.kernel.org fetch: 403; used b4/openwall
- [Phase 4] stable list search: no discussion of this patch
- [Phase 5] Callers: crash work, sysfs, debugfs
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; `make
kernelversion`: 7.3.0-rc4
- [Phase 8] Failure mode: RPMsg dead after recovery, not host oops
- UNVERIFIED: full lore HTML thread (403); no independent public i.MX
bugzilla report
**YES**
drivers/remoteproc/remoteproc_core.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index bbc781e41a1b8..2336c55eb021d 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1784,7 +1784,20 @@ static int rproc_attach_recovery(struct rproc *rproc)
if (ret)
return ret;
- return __rproc_attach(rproc);
+ /* clean up all acquired resources */
+ rproc_resource_cleanup(rproc);
+
+ /* release HW resources if needed */
+ rproc_unprepare_device(rproc);
+
+ rproc_disable_iommu(rproc);
+
+ /* Free the copy of the resource table */
+ kfree(rproc->cached_table);
+ rproc->cached_table = NULL;
+ rproc->table_ptr = NULL;
+
+ return rproc_attach(rproc);
}
static int rproc_boot_recovery(struct rproc *rproc)
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ksmbd: fix off-by-one rejecting minimal COPYCHUNK query-limits request
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (47 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] remoteproc: core: Full attach detach during recovery Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm: Validate legacy hwmgr PP table offsets Sasha Levin
` (467 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Gael Blivet, Namjae Jeon, Sasha Levin, linux-cifs, linux-kernel
From: Gael Blivet <gael.blivet@gmail.com>
[ Upstream commit d68d4b3293034f549d55f407a23b4c0a6c90e50a ]
The FSCTL_COPYCHUNK/FSCTL_COPYCHUNK_WRITE input length check uses
in_buf_len <= sizeof(struct copychunk_ioctl_req), which rejects a
buffer that is exactly sizeof(struct copychunk_ioctl_req) bytes -- the
minimal, valid request containing only the fixed header with
ChunkCount=0 and no chunk entries, used by clients to query the
server's copy limits before issuing a real copychunk.
Since copychunk_ioctl_req ends in a flexible array member, the correct
minimum is that the buffer covers the fixed header, so use
offsetof(..., Chunks) with '<' instead of '<=' against sizeof(): same
value, but the boundary case is now correctly accepted.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Gael Blivet <gael.blivet@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to judge this as a one-line protocol check against the
6.12 tree: the buggy `<= sizeof` test is present, the handler already
implements ChunkCount=0, and the patch applies cleanly.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[ksmbd]** **[fix]** off-by-one that rejects a minimal
COPYCHUNK query-limits request (ChunkCount=0, header-only).
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Signed-off-by:** Gael Blivet `<gael.blivet@gmail.com>` (author)
- **Signed-off-by:** Namjae Jeon `<linkinjeon@kernel.org>` (ksmbd
maintainer)
- **Assisted-by:** Claude:claude-sonnet-5
- **No Fixes:** tag (expected for this review pipeline)
- **No Cc: stable** (expected)
- **No Reported-by / Tested-by / Reviewed-by / Acked-by / Link:** in the
committed message
- Ignore any pipeline “Upstream commit” / Sasha Levin SOB (none in the
provided message)
Notable: maintainer SOB is a quality signal. No syzbot/KASAN tags.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `in_buf_len <= sizeof(struct copychunk_ioctl_req)` rejects a
buffer that is **exactly** the fixed header size.
- **Symptom:** clients sending FSCTL_COPYCHUNK / FSCTL_COPYCHUNK_WRITE
with ChunkCount=0 and no chunk entries (the standard “query server
copy limits” request) get `-EINVAL` / `STATUS_INVALID_PARAMETER`.
- **Root cause:** the struct ends in a flexible array; the minimum valid
length is the fixed header. `sizeof` and `offsetof(..., Chunks)` are
the same numeric value (32); the real change is `<=` → `<` so equality
is accepted.
- **Version info:** none in the message. The FAM conversion that made
`sizeof` equal the header size is in this tree.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not hidden.** Subject/body explicitly describe a protocol off-
by-one. Not cleanup/refactor.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `fs/smb/server/smb2pdu.c` — 1 line changed (`<= sizeof(...)`
→ `< offsetof(..., Chunks)`).
- **Function:** `smb2_ioctl()` (`FSCTL_SRV_COPYCHUNK` /
`FSCTL_SRV_COPYCHUNK_WRITE` cases).
- **Scope:** single-file surgical fix, ~1 line.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** reject when `in_buf_len <= 32` → a valid 32-byte header-
only request is rejected; `goto out` with `ret = -EINVAL` **before**
`nbytes` is set, so the client gets an error response **without** the
copychunk limits body.
- **After:** reject only when `in_buf_len < 32` → 32-byte request
proceeds into `fsctl_copychunk()`.
- **Path:** ioctl input-length check (not a crash path). Downstream
`fsctl_copychunk()` already does `if (chunk_count == 0) goto out;`
after filling max chunk count/size/total in the response.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** logic / correctness (off-by-one bounds check), protocol
interoperability.
- **Mechanism:** `<=` vs `<` on a FAM struct whose `sizeof` is the
header size. Valid minimum request was treated as too small.
- **Not:** UAF, leak, race, overflow, deadlock.
Verified safety after the change: if a 32-byte buffer lies with
ChunkCount ≠ 0, `fsctl_copychunk()` still rejects via `input_count <
struct_size(ci_req, Chunks, chunk_count)` before touching `Chunks[]`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Obviously correct.** `offsetof` on a FAM is the idiomatic minimum;
verified `sizeof == offsetof == 32` with a packed layout compile.
- **Minimal.** No unrelated changes, no API/struct changes.
- **Regression risk: very low.** Only newly accepted case is `in_buf_len
== 32`, which is the documented header-only request. Inner
ChunkCount=0 path already exists in this tree.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Current check is from **8bb04fb2b7e34** (“ksmbd: Replace one-element
arrays with flexible-array members”, Thorsten Blum, 2024-08-20; in
v6.12).
- That commit changed `< sizeof` to `<= sizeof` when converting `__u8
Chunks[1]` (sizeof **33**) to a FAM (sizeof **32**), preserving “need
33+ bytes” and thus still rejecting the 32-byte query.
- Original ioctl length check: **f7db8fd03a4bc5** (“ksmbd: add
validation in smb2_ioctl”, 2021-10-08), `in_buf_len < sizeof` with the
1-byte dummy array — also rejected 32-byte requests.
- **Bug has been present since ioctl validation was added (5.16-era
ksmbd), still present in this 6.12 tree.**
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Buggy behavior traces to f7db8fd / 8bb04fb as
above. Both are ancestors of HEAD.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- **0801c1374ab15** — `__counted_by_le` on `copychunk_ioctl_req` (in
this tree); inner `struct_size` check is already correct.
- **8a84ffa455462** — moved copychunk structs to
`fs/smb/common/smb2pdu.h` (in this tree).
- No other local commit already applies this `<=` → `< offsetof` change
(`git log --grep` on the path found nothing).
- **Standalone.** Cover letter: “These 7 fixes are independent of each
other.”
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record:
- Author Gael Blivet has **no** prior commits in this tree’s `fs/smb/`.
- Series: macOS/Time Machine work; this patch is explicitly **not**
Apple-specific.
- **Namjae Jeon** (maintainer) applied the series (except patch 7,
replaced by other ADS copychunk commits).
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Needs FAM `Chunks[]` so `offsetof(..., Chunks)` is valid — **present**
(8bb04fb).
- Does **not** need later AAPL full-file-copy (`529d203daa00b`, not in
this tree). In 6.12, ChunkCount=0 already means “return limits and
succeed.”
- **Can apply standalone.** `git apply --check` succeeded at offset −857
lines.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig -c fdf17b206bdc8:** match at
https://patch.msgid.link/20260707100033.47512-2-g.blivet@me.com
- **b4 dig -a:** only **v1**; committed version is that v1 (plus later
Assisted-by in the git message).
- Cover: `[PATCH 0/7] ksmbd: assorted fixes found while adding
macOS/Time Machine support` (2026-07-07).
- Author: independent of Apple-specific behavior; this one “affects any
client probing server copy limits with a minimal FSCTL_SRV_COPYCHUNK
request (ChunkCount=0).” Found and verified in live Time
Machine/Finder testing.
- **Namjae Jeon (2026-07-08):** “Applied them to #ksmbd-for-next-next
except 0007 patch.” **No NAK.** No reviewer asked for Cc: stable.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (**b4 dig -w**): To/Cc were Gaël Blivet-Bailly, **Namjae Jeon**,
**linux-cifs@vger.kernel.org**. Maintainer was the recipient and applied
it. No other Named Reviewed-by.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: no bugzilla/syzbot. Evidence is live macOS Finder/Time Machine
testing described in the cover letter. Linux CIFS client
(`__smb2_copychunk_range`) does **not** send ChunkCount=0; it sends real
chunks and learns limits from `STATUS_INVALID_PARAMETER` + response
body. This bug hits clients that probe with a header-only request (macOS
Finder, and any similar SMB2 client).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 7 independent patches. This is 1/7. Patch 7 (ADS copychunk) was
**not** taken; maintainer used other commits. Later AAPL ChunkCount=0
full-file copy is a **feature**, not required here.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search did not turn up discussion of this
specific fix (WebSearch results were unrelated). No evidence it was
previously rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `smb2_ioctl()` (length check). Downstream: `fsctl_copychunk()`.
**Step 5.2: TRACE CALLERS**
Record: `smb2_ioctl` is `SMB2_IOCTL_HE` in `fs/smb/server/smb2ops.c`.
Reachable from authenticated SMB2/SMB3 clients over the network (not a
local syscall). Interrupt/hot-path: no; file-server request path.
**Step 5.3: TRACE CALLEES**
Record: on success, `fsctl_copychunk()` fills `copychunk_ioctl_rsp` with
`ksmbd_server_side_copy_max_{chunk_count,chunk_size,total_size}()` (256
chunks, ~2GiB), then if ChunkCount==0 returns 0 without copy I/O.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: SMB client → SMB2 IOCTL → `smb2_ioctl` → (currently rejected) /
(after fix) `fsctl_copychunk`. **Reachable from userspace/network** with
a writable share. Unprivileged local users cannot hit it unless they are
SMB clients of ksmbd.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: same FAM conversion also used `<= sizeof` for `smb2_ea_info_req`
(line 4779). That is a **different** request and not this patch. Other
ioctl checks already use `in_buf_len < sizeof` or `offsetof`
(validate_negotiate, sparse, zero-data, etc.).
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Local tree is **6.12.111** (`pending-6.12`, `git
describe` p-6.12-3-gc504cf0baa3d8). Buggy check is at
`fs/smb/server/smb2pdu.c:8475`. Inner ChunkCount=0 limits path is at
7925–7934. Candidate commit **fdf17b206bdc8 is not** an ancestor of
HEAD.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** with line-number offset (`git apply --check`:
hunk succeeded at 8472). Context around the COPYCHUNK cases matches. No
conflicting local refactor of this check.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: **No.** `git log --grep='off-by-one rejecting minimal
COPYCHUNK'` on `fs/smb/server/` is empty. No alternate fix of this
comparison.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **ksmbd** (`fs/smb/server/`), in-kernel SMB3 server.
**IMPORTANT** (not core mm/VFS; not staging). `CONFIG_SMB_SERVER`.
Network-facing; protocol mistakes affect all clients of that server.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: **Active.** Recent 6.12.y ksmbd work is mostly
protocol/security/response-size fixes. Mature enough that this ioctl
check dates to 2021; still getting interoperability fixes.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Config-specific + client-specific:** ksmbd servers whose
clients send a 32-byte COPYCHUNK query-limits request. Linux CIFS does
not. macOS Finder does (author’s live testing). Any other SMB2 client
using that probe is affected.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Authenticated client, writable share,
FSCTL_SRV_COPYCHUNK(_WRITE) with InputCount=32 and ChunkCount=0.
**Common for macOS file copy / Time Machine-style copychunk probing.**
Not a race. Not triggerable by a random unprivileged local process
unless it is an SMB client.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- **Failure:** `STATUS_INVALID_PARAMETER` and **no** limits payload
(`smb2_set_err_rsp` after `-EINVAL` with nbytes still 0).
- Server-side copy probe fails; clients that require this query cannot
offload copy (fail or fall back to read/write).
- **Not** a panic, UAF, deadlock, or corruption.
- **Severity: MEDIUM** (functional/interop), important for
ksmbd+macOS/Finder, not a kernel crash.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit: medium-high for ksmbd users** — restores a path the inner
handler already implements; 1-line; live-tested against real clients.
- **Risk: very low** — equality case only; ChunkCount≠0 still size-
checked; no locking/API change.
- **Ratio:** strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real protocol bug: valid header-only COPYCHUNK is rejected; inner
handler already supports ChunkCount=0 query-limits.
- User-visible: macOS Finder/Time Machine testing; any client using that
probe.
- 1-line, obviously correct; sizeof/offsetof verified equal to 32.
- Standalone; maintainer applied it; applies cleanly here.
- Buggy code is in 6.12; candidate is not.
- Downstream access of `Chunks[]` remains guarded.
**AGAINST:**
- Not a crash/security/corruption/deadlock.
- Linux CIFS does not use this probe (Windows often uses oversized-chunk
+ EINVAL).
- Full Time Machine still needs later AAPL work not in 6.12 — but Finder
copychunk probing does not.
- No Fixes:/Cc: stable (expected; not a negative).
**UNRESOLVED:**
- Exact share of Windows versions that send ChunkCount=0 was not
verified against MS-SMB2 traces (author’s claim is “any client” using
that probe; macOS was live-tested).
- lore.kernel.org HTTP fetch returned 403; discussion recovered via `b4
dig -m`.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — 1-line; maintainer applied;
live Finder/TM testing.
2. Fixes a real bug that affects users? **PASS** — valid SMB2 request
rejected.
3. Important issue? **PASS** — interoperability for server-side copy
(MEDIUM, not panic). For ksmbd this is a real service bug, not
cosmetic.
4. Small and contained? **PASS** — 1 line, one function.
5. No new features or APIs? **PASS** — enables an already-implemented
handler path.
6. Can apply to the local tree? **PASS** — `git apply --check` clean.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None (not a device ID, quirk, DT, build, or docs fix). Qualifies
as a normal small bugfix.
**Step 9.4: MAKE YOUR DECISION**
This is a surgical protocol off-by-one in ksmbd’s COPYCHUNK ioctl check.
The 6.12 tree still has `in_buf_len <= sizeof(...)`, which rejects the
32-byte query-limits request that `fsctl_copychunk()` already handles.
Benefit is real for ksmbd users with clients that probe that way; risk
is negligible. It meets stable rules for this tree.
### What the commit solves and why it matters here
ksmbd currently turns a spec-valid FSCTL_COPYCHUNK with only the 32-byte
header (ChunkCount=0) into `STATUS_INVALID_PARAMETER` and drops the
limits body. After the fix, that request reaches the existing
ChunkCount=0 path and returns max chunk count/size/total. That is
required for server-side copy probing used by macOS Finder (and similar
clients). On **this** 6.12 tree the bug is present and the later AAPL
full-file-copy feature is not required.
### Risk vs benefit
Benefit: restore working COPYCHUNK limit queries. Risk: one comparison
change; non-zero ChunkCount still validated with `struct_size`. Applies
with a line offset only.
Verification:
- [Phase 1] Parsed tags: SOB Gael Blivet + Namjae Jeon; Assisted-by
Claude; no Fixes/Cc stable/Reported-by
- [Phase 2] Diff: 1 line in `smb2_ioctl` COPYCHUNK cases; `<= sizeof` →
`< offsetof(..., Chunks)`
- [Phase 2] Compile check: packed `sizeof=32` and `offsetof(Chunks)=32`
- [Phase 2] Read `fsctl_copychunk`: ChunkCount==0 already fills limits
and returns 0; non-zero uses `struct_size` before `Chunks[]`
- [Phase 2] Read `smb2_ioctl` `out:`: `-EINVAL` →
`STATUS_INVALID_PARAMETER` via `smb2_set_err_rsp` (no limits body)
- [Phase 3] `git blame`: check from 8bb04fb2b7e34 (FAM); originally
f7db8fd03a4bc5
- [Phase 3] `git merge-base --is-ancestor` 8bb04fb, f7db8fd, 0801c137:
all in HEAD; fdf17b206bdc8 not in HEAD
- [Phase 3] `git log --grep='off-by-one rejecting minimal COPYCHUNK' --
fs/smb/server/`: empty
- [Phase 4] `b4 dig -c fdf17b206bdc8`: lore match
20260707100033.47512-2; cover 0/7; Namjae applied except 0007
- [Phase 4] `b4 dig -a`: v1 only; `b4 dig -w`: maintainer + linux-cifs
- [Phase 4] Cover letter: independent of Apple-specific patches; live
TM/Finder testing
- [Phase 4] stable@ lore search: no hit for this subject
- [Phase 5] Caller: `smb2ops.c` SMB2_IOCTL_HE → `smb2_ioctl`; network
SMB path
- [Phase 5] Linux client `__smb2_copychunk_range` does not send
ChunkCount=0
- [Phase 6] `git describe HEAD`: p-6.12-3-gc504cf0baa3d8; `make
kernelversion`: 6.12.111
- [Phase 6] Buggy line at smb2pdu.c:8475; `git apply --check` succeeded
at 8472
- [Phase 8] Failure: protocol reject of valid COPYCHUNK query, severity
MEDIUM; not a crash
- UNVERIFIED: whether every Windows build sends ChunkCount=0 (not used
to drive the verdict)
**YES**
fs/smb/server/smb2pdu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index d64753124dd9a..9bb885fa1ac66 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -8576,7 +8576,7 @@ int smb2_ioctl(struct ksmbd_work *work)
goto out;
}
- if (in_buf_len <= sizeof(struct copychunk_ioctl_req)) {
+ if (in_buf_len < offsetof(struct copychunk_ioctl_req, Chunks)) {
ret = -EINVAL;
goto out;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/amd/pm: Validate legacy hwmgr PP table offsets
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (48 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] ksmbd: fix off-by-one rejecting minimal COPYCHUNK query-limits request Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:28 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] Bluetooth: hci_event: fix out-of-bounds read in LE PA report reassembly Sasha Levin
` (466 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Yang Wang, Hawking Zhang, Alex Deucher, Sasha Levin, kenneth.feng,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Yang Wang <kevinyang.wang@amd.com>
[ Upstream commit 0ceb6bc43e62f0e73b282c9de8f4bc4d5498f281 ]
processpptables.c walks several variable-length PPLIB tables by
using offsets from the VBIOS PowerPlay table. Some paths dereference
extended headers, state arrays, clock arrays, non-clock arrays, or VCE
records before checking that the referenced data is inside the table
buffer.
Add local bounds helpers and validate the relevant offsets and entry
sizes before dereferencing them. This prevents truncated or malformed
legacy PowerPlay tables from driving out-of-bounds reads during hwmgr
initialization and table entry lookup.
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Hawking’s series review is on file, and the v6.18.53 parser still has
the unfixed offset walks. I’ll write up the nine-phase verdict from that
evidence.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[drm/amd/pm] [Validate] [bounds-check legacy hwmgr PowerPlay
table offsets before dereference]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Yang Wang <kevinyang.wang@amd.com>` (author, AMD)
- `Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>` (AMD reviewer)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (amdgpu
maintainer)
- No `Fixes:` tag (expected)
- No `Reported-by:` / syzbot / `Cc: stable`
- No `Link:` in the committed message
- Ignore pipeline `Signed-off-by: Sasha Levin` and `[Upstream commit
0ceb6bc43e62...]`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `processpptables.c` walks variable-length PPLIB tables using
VBIOS offsets and dereferences extended headers, state/clock/non-clock
arrays, and VCE records without confirming they lie inside the table
buffer.
- **Symptom:** out-of-bounds kernel reads during hwmgr init and table
entry lookup on truncated or malformed PowerPlay tables.
- **Root cause:** offset/size taken from untrusted table contents; only
a weak `usTableSize >= sizeof(POWERPLAYTABLE3)` check existed for
extended headers; array walks used `ucNumEntries` / `ucEntrySize` with
no remaining-buffer check.
- **Version info:** none in the message. Author date 2026-06-23;
upstream commit 2026-07-01 (after v6.18).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. Explicit memory-safety fix. Also silently
corrects an off-by-one in `get_state_entry_v2` (`entry_index <=
ucNumEntries` vs `>=`) and adds a missing NULL/size check in
`pp_tables_initialize`.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- One file: `drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c`
- `+316 / -130` (446 lines touched); 21 hunks
- New: `pp_table_has_space()`, `get_extended_header()`
- Modified: VCE/UVD/SAMU/ACP/PowerTune/SCLK offset helpers,
`get_state_entry_v2`, `pp_tables_get_response_times`,
`pp_tables_get_num_of_entries`, `pp_tables_get_entry`,
`get_vce_state_table_entry`, `pp_tables_initialize`
- Classification: single-file surgical hardening (not cross-subsystem)
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Extended-header getters:** previously cast `powerplay_table +
usExtendendedHeaderOffset` after only `usTableSize >=
sizeof(POWERPLAYTABLE3)`. Now `get_extended_header()` also requires
the offset and `min_size` to fit in `hwmgr->soft_pp_table_size`.
- **VCE/UVD array size helpers:** previously read `ucNumEntries` and
computed size with no bounds check. Now require the count byte and the
full computed array to fit; otherwise return 0 so later offset math
stops.
- **`get_state_entry_v2`:** previously walked `entry_index` steps if
`entry_index <= ucNumEntries` (allows OOB when `entry_index ==
ucNumEntries`) and returned the resulting pointer even if it walked
off the buffer. Now rejects `entry_index >= ucNumEntries` and checks
each variable-length entry against the buffer.
- **`pp_tables_get_entry`:** previously used offsets as-is (and
`entry_index > ucNumEntries`, another off-by-one). Now validates
state/clock/non-clock array headers, entry sizes, and per-index
offsets; returns `-1` on failure.
- **`pp_tables_initialize`:** previously used `powerplay_table` with no
NULL/size check after `get_powerplay_table()`. Now asserts table
present and large enough for the header.
- Paths: init (`pptable_init` → `hwmgr_hw_init`) and entry lookup
(power-state construction). Error paths become fail-closed instead of
OOB.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **(d) Memory safety — out-of-bounds reads** plus **(g)
logic/off-by-one**.
Mechanism: firmware/sysfs PP tables supply offsets and counts; the
parser added them to the base pointer without comparing against
`soft_pp_table_size`. The fix is overflow-safe (`offset <= table_size &&
size <= table_size - offset`) and rejects truncated entries.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct for the paths it covers: fail closed, no new APIs,
local static helpers.
- Not complete for the whole file: `init_thermal_controller` still uses
`usFanTableOffset`, and `init_overdrive_limits_V2_1` still uses
`usExtendendedHeaderOffset`, without `pp_table_has_space()`. Partial
hardening is still a real fix.
- Regression risk: well-formed VBIOS inside the ATOM-reported size is
unchanged. Malformed tables that previously “worked” by reading past
the buffer now fail init (`pptable_init` error → DPM init error). That
is the intended fail-closed behavior.
- No public API / struct layout change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Unfixed `get_vce_table_offset` at v6.18.53 blames
`3bace359149391` (“drm/amd/powerplay: add hardware manager sub-
component”, 2015-12-21). Present since the powerplay hwmgr was added.
Confirmed ancestor of v6.18.53.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Bug is original parser design, not a later
regression.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same author series (standalone files, not compile deps for this
patch):
- `Validate pp_table header before reading size` (sysfs/SMU)
- `Use uploaded size for legacy custom PPTable` (`amd_powerplay.c`)
- `Validate Tonga PowerPlay state array bounds`
- `Validate Vega hwmgr PowerPlay table bounds`
This commit is **[PATCH 5/5]** and only touches `processpptables.c`. No
prerequisite refactor in this file. No later follow-up on this file
after upstream `0ceb6bc43e62`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Yang Wang is an AMD pm contributor with multiple PP-table
UAF/bounds fixes (`fix pptable use-after-free`, header-size validation,
custom-table size). Hawking Zhang and Alex Deucher reviewed/merged.
Maintainer-backed.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Applies standalone. Uses existing `hwmgr->soft_pp_table_size`
(in `hwmgr.h` at v6.18.53). Sibling patch “Use uploaded size…” is
**not** required for this to compile; it would make short *custom*
uploads match `soft_pp_table_size` more tightly. This patch still stops
offsets past the allocated buffer.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 0ceb6bc43e62...` → only **v1**, msgid
`20260623034151.263746-5-kevinyang.wang@amd.com`
- Series: `[PATCH 1/5] ... header before reading size` through `[PATCH
5/5] Validate legacy hwmgr PP table offsets`
- lore.kernel.org fetches returned **403**; thread recovered via
`https://ratatoskr.run/amd-gfx/2026/06/17163868`
- `b4 dig -a`: only v1 (committed version is the submitted version)
- Merged via Alex Deucher drm-next-7.3 pull
(`lists.freedesktop.org/archives/amd-gfx/2026-July/148126.html`)
- No NAK found. No reviewer `Cc: stable` found (absence expected).
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: `b4 dig -w` CC: Yang Wang, amd-gfx, alexander.deucher@amd.com,
hawking.zhang@amd.com, kenneth.feng@amd.com. Hawking replied R-B on the
series (`RE: [PATCH 1/5]` on 2026-06-23); commit carries his `Reviewed-
by`. Alex Deucher signed off.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. The 5-patch series is systematic hardening
of PP-table parsing after related issues (`bound pp_dpm_set_pp_table()
memcpy` heap overflow, pptable UAF). Severity from code: kernel OOB
read.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 5-patch v1 series; this is 5/5, different files. Standalone for
this tree.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search not usable (403). `git log
--grep="Validate legacy"` on v6.18.53: not present. No evidence it was
rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: KEY FUNCTIONS**
Record: `pp_table_has_space`, `get_extended_header`,
VCE/UVD/SAMU/ACP/PowerTune/SCLK offset helpers, `get_state_entry_v2`,
`pp_tables_get_response_times`, `pp_tables_get_num_of_entries`,
`pp_tables_get_entry`, `get_vce_state_table_entry`,
`pp_tables_initialize`.
**Step 5.2: TRACE CALLERS**
Record:
- `pptable_funcs.pptable_init` = `pp_tables_initialize` →
`hwmgr_hw_init()` (GPU DPM init / `amd_powerplay_reset` after sysfs
upload)
- `pptable_funcs` assigned for:
- SMU7 + `PP_TABLE_V0`: `AMDGPU_FAMILY_CI` (Bonaire/Hawaii),
`CHIP_TOPAZ` (Iceland)
- SMU8: `AMDGPU_FAMILY_CZ` (Carrizo/Stoney)
- SMU10: `CHIP_RAVEN` (dummy table; initialize returns 0 early)
- `pp_tables_get_entry` called from `smu7_hwmgr.c`, `smu8_hwmgr.c`,
`smu10_hwmgr.c` while building power states.
**Step 5.3: TRACE CALLEES**
Record: `get_powerplay_table()` fills `soft_pp_table` /
`soft_pp_table_size` from ATOM `PowerPlayInfo` or the dummy table.
Helpers then index that buffer.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable on every boot of CI/CZ/Iceland amdgpu with DPM, and on
`pp_table` sysfs write (`S_IWUSR`, typically root) which copies a user
buffer and calls `amd_powerplay_reset()` → `pptable_init` / entry
lookup.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same series adds analogous checks in Tonga
(`process_pptables_v1_0.c`) and Vega parsers. Leftover unguarded
`usFanTableOffset` / overdrive extended-header walks remain in this
file.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Local tree is **6.18.53** (`git describe HEAD` =
`v6.18.53-5049-g0f0bdc2b0dffb`; Makefile `VERSION=6 PATCHLEVEL=18
SUBLEVEL=53`).
- `git merge-base --is-ancestor 0ceb6bc43e62 v6.18.53` → **no** (fix not
in 6.18.53)
- `git grep pp_table_has_space v6.18.53 -- processpptables.c` → **NOT
PRESENT**
- Unfixed `get_vce_table_offset` / `get_state_entry_v2` /
`pp_tables_get_entry` confirmed at v6.18.53.
- Bug introduced 2015; present in this series.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: `patch --dry-run` of this commit onto the v6.18.53 blob: **EXIT
0, clean apply**. File not refactored between 6.18.53 and the patch
context.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No equivalent bounds helper in this file at v6.18.53.
`3334985f8b4c7` (`bound pp_dpm_set_pp_table() memcpy`) is in 6.18.53 and
only caps upload size; it does not validate internal offsets.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/gpu/drm/amd/pm/powerplay` — **IMPORTANT** (legacy AMD
GPU powerplay). Not core mm/vfs, but amdgpu DPM init is a common
production path (CI/CZ laptops and cards still in use).
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained; this is late hardening of a 10-year-old
parser, not a brand-new subsystem.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: WHO IS AFFECTED**
Record: Driver-specific: amdgpu CI (Bonaire/Hawaii), Iceland/Topaz,
Carrizo/Stoney; sysfs `pp_table` writers on those chips. Not Navi/RDNA
swsmu.
**Step 8.2: TRIGGER CONDITIONS**
Record:
- Probe/init: truncated or offset-inconsistent VBIOS PowerPlay table.
- Sysfs: root write of a malformed table ≤ original size (6.18.53 still
copies into the VBIOS-sized buffer). Offsets beyond that buffer OOB
without this patch.
- Off-by-one: `entry_index == ucNumEntries` on format rev ≥ 6.
- Unprivileged users cannot write `pp_table` (`S_IWUSR`). VBIOS path
runs on device init.
**Step 8.3: FAILURE MODE SEVERITY**
Record: Kernel **out-of-bounds read** → KASAN/oops or info leak.
**HIGH**. Missing table in `pp_tables_initialize` was a possible NULL
deref (**CRITICAL** if hit).
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit: HIGH** — stops OOB reads in DPM init on remaining CI/CZ
hardware and custom PP tables.
- **Risk: LOW–MEDIUM** — +316 lines but one file, fail-closed checks,
overflow-safe helper, maintainer-reviewed; leftover unguarded
fan/overdrive walks are pre-existing, not introduced.
- **Ratio:** benefit outweighs risk.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR backporting:
- Real OOB reads in a firmware table parser present since 2015 and still
in v6.18.53
- Off-by-one in `get_state_entry_v2` / `pp_tables_get_entry`
- Probe-time path plus documented `pp_table` sysfs upload
- Applies cleanly to this tree
- Reviewed by Hawking Zhang, signed off by Alex Deucher
- No new APIs; overflow-safe helper
- No follow-up fix indicating the patch itself was buggy
AGAINST:
- Larger than a typical 10-line stable patch (+316/−130)
- Incomplete (fan/overdrive offset walks still unchecked)
- No syzbot/CVE/user crash report
- Sibling “uploaded size” patch not in 6.18.53 (custom short tables
still keep VBIOS `soft_pp_table_size`)
UNRESOLVED:
- Full lore thread text (403); ratatoskr + b4 + drm-next pull used
instead
- Whether any production VBIOS relies on reading past ATOM size
(unverified; fail-closed is still correct)
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — overflow-safe bounds checks;
v1 applied; maintainer R-B/SOB
2. Fixes a real bug that affects users? **PASS** — OOB reads on
malformed VBIOS/custom PP tables; CI/CZ still use this parser
3. Important issue? **PASS** — HIGH (OOB read / possible oops); NULL
deref on missing table
4. Small and contained? **PASS** — one file, no refactor, no API; large
but contained
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — clean apply to v6.18.53;
buggy code present
**Step 9.3: EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. Qualifies as a
memory-safety fix.
**Step 9.4: DECISION**
This should be backported to this 6.18.y tree. The parser is in-tree,
the bug is old, the patch applies cleanly, and the failure mode is
kernel OOB during GPU powerplay init.
Verification:
- [Phase 1] Parsed tags: author Yang Wang; Reviewed-by Hawking Zhang;
SOB Alex Deucher; no Fixes/syzbot/stable Cc
- [Phase 2] Diff: +316/−130 in `processpptables.c`; adds
`pp_table_has_space`/`get_extended_header`; validates offsets before
deref; also fixes `entry_index <= ucNumEntries` off-by-one
- [Phase 3] `git blame` at v6.18.53: `3bace359149391` (2015-12-21); `git
merge-base --is-ancestor 3bace359149391 v6.18.53` = yes
- [Phase 3] No Fixes: tag; series siblings touch other files only
- [Phase 3] No follow-up on this file after `0ceb6bc43e62`
- [Phase 4] `b4 dig -c 0ceb6bc43e62`: v1 only, msgid
`20260623034151.263746-5-kevinyang.wang@amd.com`
- [Phase 4] `b4 dig -w`: amd-gfx + Deucher + Hawking + Kenneth Feng
- [Phase 4] lore WebFetch 403; discussion via ratatoskr 17163868; merged
in drm-next-7.3 pull
- [Phase 5] `pptable_funcs` used by smu7 (PP_TABLE_V0: CI, Topaz), smu8
(CZ), smu10 (Raven dummy); `hwmgr_hw_init` → `pptable_init`
- [Phase 5] `pp_table` sysfs `AMDGPU_DEVICE_ATTR_RW` with `S_IWUSR`;
write → `pp_dpm_set_pp_table` → `amd_powerplay_reset`
- [Phase 6] `git describe HEAD` = v6.18.53-5049-g0f0bdc2b0dffb; `make
kernelversion` 6.18.53
- [Phase 6] `git merge-base --is-ancestor 0ceb6bc43e62 v6.18.53` = no;
`pp_table_has_space` absent at v6.18.53
- [Phase 6] patch dry-run against v6.18.53 blob: EXIT 0
- [Phase 8] Failure mode: OOB read during hwmgr init / entry lookup,
severity HIGH
- UNVERIFIED: full lore review body (403); whether any in-field VBIOS
depends on reading past table_size
**YES**
.../amd/pm/powerplay/hwmgr/processpptables.c | 446 +++++++++++++-----
1 file changed, 316 insertions(+), 130 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
index f06b29e33ba45..f1009b2973574 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
@@ -47,26 +47,53 @@
#define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
+static bool pp_table_has_space(struct pp_hwmgr *hwmgr, size_t offset,
+ size_t size)
+{
+ size_t table_size = hwmgr->soft_pp_table_size;
+
+ return offset <= table_size && size <= table_size - offset;
+}
+
+static const ATOM_PPLIB_EXTENDEDHEADER *
+get_extended_header(struct pp_hwmgr *hwmgr,
+ const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+ size_t min_size)
+{
+ const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
+ const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
+ u16 offset;
+
+ if (le16_to_cpu(powerplay_table->usTableSize) <
+ sizeof(ATOM_PPLIB_POWERPLAYTABLE3) ||
+ !pp_table_has_space(hwmgr, 0, sizeof(ATOM_PPLIB_POWERPLAYTABLE3)))
+ return NULL;
+
+ powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+ offset = le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset);
+ if (!offset || !pp_table_has_space(hwmgr, offset,
+ sizeof(extended_header->usSize)))
+ return NULL;
+
+ extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
+ (((unsigned long)powerplay_table) + offset);
+ if (le16_to_cpu(extended_header->usSize) < min_size ||
+ !pp_table_has_space(hwmgr, offset, min_size))
+ return NULL;
+
+ return extended_header;
+}
+
static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
{
uint16_t vce_table_offset = 0;
+ const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
- if (le16_to_cpu(powerplay_table->usTableSize) >=
- sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
- const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
- (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
-
- if (powerplay_table3->usExtendendedHeaderOffset > 0) {
- const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
- (const ATOM_PPLIB_EXTENDEDHEADER *)
- (((unsigned long)powerplay_table3) +
- le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
- if (le16_to_cpu(extended_header->usSize) >=
- SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)
- vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
- }
- }
+ extended_header = get_extended_header(hwmgr, powerplay_table,
+ SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2);
+ if (extended_header)
+ vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
return vce_table_offset;
}
@@ -93,7 +120,14 @@ static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,
if (table_offset > 0) {
const VCEClockInfoArray *p = (const VCEClockInfoArray *)
(((unsigned long) powerplay_table) + table_offset);
- table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
+ size_t size;
+
+ if (!pp_table_has_space(hwmgr, table_offset, sizeof(p->ucNumEntries)))
+ return 0;
+
+ size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
+ if (pp_table_has_space(hwmgr, table_offset, size))
+ table_size = size;
}
return table_size;
@@ -104,10 +138,13 @@ static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,
{
uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
powerplay_table);
+ u16 table_size;
- if (table_offset > 0)
- return table_offset + get_vce_clock_info_array_size(hwmgr,
- powerplay_table);
+ if (table_offset > 0) {
+ table_size = get_vce_clock_info_array_size(hwmgr, powerplay_table);
+ if (table_size)
+ return table_offset + table_size;
+ }
return 0;
}
@@ -121,8 +158,15 @@ static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
if (table_offset > 0) {
const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =
(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);
+ size_t size;
- table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
+ if (!pp_table_has_space(hwmgr, table_offset, sizeof(ptable->numEntries)))
+ return 0;
+
+ size = sizeof(uint8_t) +
+ ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
+ if (pp_table_has_space(hwmgr, table_offset, size))
+ table_size = size;
}
return table_size;
}
@@ -130,9 +174,13 @@ static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
{
uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
+ u16 table_size;
- if (table_offset > 0)
- return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
+ if (table_offset > 0) {
+ table_size = get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
+ if (table_size)
+ return table_offset + table_size;
+ }
return 0;
}
@@ -143,8 +191,12 @@ static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(
{
uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
- if (table_offset > 0)
- return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);
+ if (table_offset > 0) {
+ if (pp_table_has_space(hwmgr, table_offset,
+ sizeof(((ATOM_PPLIB_VCE_State_Table *)0)->numEntries)))
+ return (const ATOM_PPLIB_VCE_State_Table *)
+ (((unsigned long)powerplay_table) + table_offset);
+ }
return NULL;
}
@@ -153,21 +205,13 @@ static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
{
uint16_t uvd_table_offset = 0;
+ const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
+
+ extended_header = get_extended_header(hwmgr, powerplay_table,
+ SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3);
+ if (extended_header)
+ uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
- if (le16_to_cpu(powerplay_table->usTableSize) >=
- sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
- const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
- (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
- if (powerplay_table3->usExtendendedHeaderOffset > 0) {
- const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
- (const ATOM_PPLIB_EXTENDEDHEADER *)
- (((unsigned long)powerplay_table3) +
- le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
- if (le16_to_cpu(extended_header->usSize) >=
- SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)
- uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
- }
- }
return uvd_table_offset;
}
@@ -193,8 +237,14 @@ static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,
const UVDClockInfoArray *p = (const UVDClockInfoArray *)
(((unsigned long) powerplay_table)
+ table_offset);
- table_size = sizeof(UCHAR) +
- p->ucNumEntries * sizeof(UVDClockInfo);
+ size_t size;
+
+ if (!pp_table_has_space(hwmgr, table_offset, sizeof(p->ucNumEntries)))
+ return 0;
+
+ size = sizeof(UCHAR) + p->ucNumEntries * sizeof(UVDClockInfo);
+ if (pp_table_has_space(hwmgr, table_offset, size))
+ table_size = size;
}
return table_size;
@@ -206,10 +256,13 @@ static uint16_t get_uvd_clock_voltage_limit_table_offset(
{
uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
powerplay_table);
+ u16 table_size;
- if (table_offset > 0)
- return table_offset +
- get_uvd_clock_info_array_size(hwmgr, powerplay_table);
+ if (table_offset > 0) {
+ table_size = get_uvd_clock_info_array_size(hwmgr, powerplay_table);
+ if (table_size)
+ return table_offset + table_size;
+ }
return 0;
}
@@ -218,21 +271,12 @@ static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
{
uint16_t samu_table_offset = 0;
+ const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
- if (le16_to_cpu(powerplay_table->usTableSize) >=
- sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
- const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
- (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
- if (powerplay_table3->usExtendendedHeaderOffset > 0) {
- const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
- (const ATOM_PPLIB_EXTENDEDHEADER *)
- (((unsigned long)powerplay_table3) +
- le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
- if (le16_to_cpu(extended_header->usSize) >=
- SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)
- samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
- }
- }
+ extended_header = get_extended_header(hwmgr, powerplay_table,
+ SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4);
+ if (extended_header)
+ samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
return samu_table_offset;
}
@@ -254,21 +298,12 @@ static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
{
uint16_t acp_table_offset = 0;
+ const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
- if (le16_to_cpu(powerplay_table->usTableSize) >=
- sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
- const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
- (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
- if (powerplay_table3->usExtendendedHeaderOffset > 0) {
- const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
- (const ATOM_PPLIB_EXTENDEDHEADER *)
- (((unsigned long)powerplay_table3) +
- le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
- if (le16_to_cpu(pExtendedHeader->usSize) >=
- SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)
- acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);
- }
- }
+ extended_header = get_extended_header(hwmgr, powerplay_table,
+ SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6);
+ if (extended_header)
+ acp_table_offset = le16_to_cpu(extended_header->usACPTableOffset);
return acp_table_offset;
}
@@ -290,21 +325,12 @@ static uint16_t get_cacp_tdp_table_offset(
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
{
uint16_t cacTdpTableOffset = 0;
+ const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
- if (le16_to_cpu(powerplay_table->usTableSize) >=
- sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
- const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
- (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
- if (powerplay_table3->usExtendendedHeaderOffset > 0) {
- const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
- (const ATOM_PPLIB_EXTENDEDHEADER *)
- (((unsigned long)powerplay_table3) +
- le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
- if (le16_to_cpu(pExtendedHeader->usSize) >=
- SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)
- cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);
- }
- }
+ extended_header = get_extended_header(hwmgr, powerplay_table,
+ SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7);
+ if (extended_header)
+ cacTdpTableOffset = le16_to_cpu(extended_header->usPowerTuneTableOffset);
return cacTdpTableOffset;
}
@@ -341,22 +367,13 @@ static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
{
uint16_t sclk_vdd_gfx_table_offset = 0;
+ const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
- if (le16_to_cpu(powerplay_table->usTableSize) >=
- sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
- const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
- (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
- if (powerplay_table3->usExtendendedHeaderOffset > 0) {
- const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
- (const ATOM_PPLIB_EXTENDEDHEADER *)
- (((unsigned long)powerplay_table3) +
- le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
- if (le16_to_cpu(pExtendedHeader->usSize) >=
- SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)
- sclk_vdd_gfx_table_offset =
- le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);
- }
- }
+ extended_header = get_extended_header(hwmgr, powerplay_table,
+ SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8);
+ if (extended_header)
+ sclk_vdd_gfx_table_offset =
+ le16_to_cpu(extended_header->usSclkVddgfxTableOffset);
return sclk_vdd_gfx_table_offset;
}
@@ -770,20 +787,37 @@ static ULONG size_of_entry_v2(ULONG num_dpm_levels)
}
static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
+ struct pp_hwmgr *hwmgr,
const StateArray * pstate_arrays,
+ u16 state_array_offset,
ULONG entry_index)
{
ULONG i;
const ATOM_PPLIB_STATE_V2 *pstate;
+ size_t entry_offset;
+ size_t entry_size;
+
+ if (entry_index >= pstate_arrays->ucNumEntries)
+ return NULL;
+ entry_offset = state_array_offset + sizeof(pstate_arrays->ucNumEntries);
pstate = pstate_arrays->states;
- if (entry_index <= pstate_arrays->ucNumEntries) {
- for (i = 0; i < entry_index; i++)
- pstate = (ATOM_PPLIB_STATE_V2 *)(
- (unsigned long)pstate +
- size_of_entry_v2(pstate->ucNumDPMLevels));
+ for (i = 0; i <= entry_index; i++) {
+ if (!pp_table_has_space(hwmgr, entry_offset, sizeof(*pstate)))
+ return NULL;
+
+ entry_size = size_of_entry_v2(pstate->ucNumDPMLevels);
+ if (!pp_table_has_space(hwmgr, entry_offset, entry_size))
+ return NULL;
+
+ if (i == entry_index)
+ return pstate;
+
+ entry_offset += entry_size;
+ pstate = (ATOM_PPLIB_STATE_V2 *)((unsigned long)pstate + entry_size);
}
- return pstate;
+
+ return NULL;
}
static const unsigned char soft_dummy_pp_table[] = {
@@ -851,6 +885,8 @@ int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
"Missing PowerPlay Table!", return -EINVAL);
+ PP_ASSERT_WITH_CODE(pp_table_has_space(hwmgr, 0, sizeof(*powerplay_tab)),
+ "Invalid PowerPlay Table!", return -EINVAL);
*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
@@ -863,13 +899,21 @@ int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
{
const StateArray *pstate_arrays;
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
+ u16 state_array_offset;
if (powerplay_table == NULL)
return -1;
+ if (!pp_table_has_space(hwmgr, 0, sizeof(*powerplay_table)))
+ return -1;
if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
+ state_array_offset = le16_to_cpu(powerplay_table->usStateArrayOffset);
+ if (!pp_table_has_space(hwmgr, state_array_offset,
+ sizeof(pstate_arrays->ucNumEntries)))
+ return -1;
+
pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
- le16_to_cpu(powerplay_table->usStateArrayOffset));
+ state_array_offset);
*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
} else
@@ -896,49 +940,128 @@ int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
const NonClockInfoArray *pnon_clock_arrays;
const ATOM_PPLIB_STATE *pstate_entry;
+ u16 state_array_offset;
+ u16 clock_info_array_offset;
+ u16 non_clock_info_array_offset;
+ size_t clock_info_offset;
+ size_t non_clock_info_offset;
+ size_t state_entry_offset;
if (powerplay_table == NULL)
return -1;
+ if (!pp_table_has_space(hwmgr, 0, sizeof(*powerplay_table)))
+ return -1;
ps->classification.bios_index = entry_index;
if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
+ state_array_offset = le16_to_cpu(powerplay_table->usStateArrayOffset);
+ if (!pp_table_has_space(hwmgr, state_array_offset,
+ sizeof(pstate_arrays->ucNumEntries)))
+ return -1;
+
pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
- le16_to_cpu(powerplay_table->usStateArrayOffset));
+ state_array_offset);
+
+ if (entry_index >= pstate_arrays->ucNumEntries)
+ return -1;
- if (entry_index > pstate_arrays->ucNumEntries)
+ pstate_entry_v2 = get_state_entry_v2(hwmgr, pstate_arrays,
+ state_array_offset,
+ entry_index);
+ if (!pstate_entry_v2)
+ return -1;
+
+ clock_info_array_offset =
+ le16_to_cpu(powerplay_table->usClockInfoArrayOffset);
+ if (!pp_table_has_space(hwmgr, clock_info_array_offset,
+ sizeof(*pclock_arrays)))
return -1;
- pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
- le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
+ clock_info_array_offset);
+ if (!pclock_arrays->ucEntrySize)
+ return -1;
+
+ non_clock_info_array_offset =
+ le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset);
+ if (!pp_table_has_space(hwmgr, non_clock_info_array_offset,
+ sizeof(*pnon_clock_arrays)))
+ return -1;
pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
- le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
+ non_clock_info_array_offset);
+ if (!pnon_clock_arrays->ucEntrySize ||
+ pnon_clock_arrays->ucEntrySize < ATOM_PPLIB_NONCLOCKINFO_VER1 ||
+ (pnon_clock_arrays->ucEntrySize > ATOM_PPLIB_NONCLOCKINFO_VER1 &&
+ pnon_clock_arrays->ucEntrySize < ATOM_PPLIB_NONCLOCKINFO_VER2) ||
+ pstate_entry_v2->nonClockInfoIndex >= pnon_clock_arrays->ucNumEntries)
+ return -1;
+ non_clock_info_offset = non_clock_info_array_offset +
+ offsetof(NonClockInfoArray, nonClockInfo) +
+ pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize;
+ if (!pp_table_has_space(hwmgr, non_clock_info_offset,
+ pnon_clock_arrays->ucEntrySize))
+ return -1;
pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
- const void *pclock_info = (const void *)(
- (unsigned long)(pclock_arrays->clockInfo) +
- (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
+ const void *pclock_info;
+
+ if (pstate_entry_v2->clockInfoIndex[i] >=
+ pclock_arrays->ucNumEntries)
+ return -1;
+
+ clock_info_offset = clock_info_array_offset +
+ offsetof(ClockInfoArray, clockInfo) +
+ pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize;
+ if (!pp_table_has_space(hwmgr, clock_info_offset,
+ pclock_arrays->ucEntrySize))
+ return -1;
+
+ pclock_info = (const void *)
+ ((unsigned long)(pclock_arrays->clockInfo) +
+ (pstate_entry_v2->clockInfoIndex[i] *
+ pclock_arrays->ucEntrySize));
res = func(hwmgr, &ps->hardware, i, pclock_info);
if ((0 == result) && (0 != res))
result = res;
}
} else {
- if (entry_index > powerplay_table->ucNumStates)
+ if (entry_index >= powerplay_table->ucNumStates ||
+ !powerplay_table->ucStateEntrySize ||
+ !powerplay_table->ucNonClockSize ||
+ powerplay_table->ucNonClockSize < ATOM_PPLIB_NONCLOCKINFO_VER1 ||
+ (powerplay_table->ucNonClockSize > ATOM_PPLIB_NONCLOCKINFO_VER1 &&
+ powerplay_table->ucNonClockSize < ATOM_PPLIB_NONCLOCKINFO_VER2) ||
+ !powerplay_table->ucClockInfoSize)
+ return -1;
+
+ state_array_offset = le16_to_cpu(powerplay_table->usStateArrayOffset);
+ state_entry_offset = state_array_offset +
+ entry_index * powerplay_table->ucStateEntrySize;
+ if (!pp_table_has_space(hwmgr, state_entry_offset,
+ powerplay_table->ucStateEntrySize))
return -1;
pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
- le16_to_cpu(powerplay_table->usStateArrayOffset) +
+ state_array_offset +
entry_index * powerplay_table->ucStateEntrySize);
+ non_clock_info_array_offset =
+ le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset);
+ non_clock_info_offset = non_clock_info_array_offset +
+ pstate_entry->ucNonClockStateIndex * powerplay_table->ucNonClockSize;
+ if (!pp_table_has_space(hwmgr, non_clock_info_offset,
+ powerplay_table->ucNonClockSize))
+ return -1;
+
pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
- le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
+ non_clock_info_array_offset +
pstate_entry->ucNonClockStateIndex *
powerplay_table->ucNonClockSize);
@@ -947,12 +1070,23 @@ int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
pnon_clock_info);
for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
- const void *pclock_info = (const void *)((unsigned long)powerplay_table +
- le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
+ const void *pclock_info;
+
+ clock_info_array_offset =
+ le16_to_cpu(powerplay_table->usClockInfoArrayOffset);
+ clock_info_offset = clock_info_array_offset +
+ pstate_entry->ucClockStateIndices[i] *
+ powerplay_table->ucClockInfoSize;
+ if (!pp_table_has_space(hwmgr, clock_info_offset,
+ powerplay_table->ucClockInfoSize))
+ return -1;
+
+ pclock_info = (const void *)((unsigned long)powerplay_table +
+ clock_info_array_offset +
pstate_entry->ucClockStateIndices[i] *
powerplay_table->ucClockInfoSize);
- int res = func(hwmgr, &ps->hardware, i, pclock_info);
+ res = func(hwmgr, &ps->hardware, i, pclock_info);
if ((0 == result) && (0 != res))
result = res;
@@ -1667,21 +1801,70 @@ static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
unsigned long *flag)
{
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
+ const ATOM_PPLIB_VCE_State_Table *vce_state_table;
+ const ATOM_PPLIB_VCE_State_Record *record;
+ const VCEClockInfoArray *vce_clock_info_array;
+ const VCEClockInfo *vce_clock_info;
+ const ClockInfoArray *clock_arrays;
+ u16 vce_state_table_offset;
+ u16 vce_clock_info_array_offset;
+ u16 clock_info_array_offset;
+ unsigned long clockInfoIndex;
+ size_t record_offset;
+ size_t vce_clock_info_offset;
+ size_t clock_info_offset;
+
+ if (!powerplay_table || !pp_table_has_space(hwmgr, 0, sizeof(*powerplay_table)))
+ return -1;
- const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
+ vce_state_table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
+ vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
+ if (!vce_state_table || i >= vce_state_table->numEntries)
+ return -1;
+
+ record_offset = vce_state_table_offset +
+ offsetof(ATOM_PPLIB_VCE_State_Table, entries) +
+ i * sizeof(*record);
+ if (!pp_table_has_space(hwmgr, record_offset, sizeof(*record)))
+ return -1;
+
+ record = &vce_state_table->entries[i];
+
+ vce_clock_info_array_offset =
+ get_vce_clock_info_array_offset(hwmgr, powerplay_table);
+ if (!pp_table_has_space(hwmgr, vce_clock_info_array_offset,
+ sizeof(vce_clock_info_array->ucNumEntries)))
+ return -1;
- unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
+ vce_clock_info_array = (const VCEClockInfoArray *)
+ (((unsigned long)powerplay_table) + vce_clock_info_array_offset);
+ if (record->ucVCEClockInfoIndex >= vce_clock_info_array->ucNumEntries)
+ return -1;
- const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
+ vce_clock_info_offset = vce_clock_info_array_offset +
+ offsetof(VCEClockInfoArray, entries) +
+ record->ucVCEClockInfoIndex * sizeof(*vce_clock_info);
+ if (!pp_table_has_space(hwmgr, vce_clock_info_offset, sizeof(*vce_clock_info)))
+ return -1;
- const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
- le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
+ vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
- const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
+ clock_info_array_offset = le16_to_cpu(powerplay_table->usClockInfoArrayOffset);
+ if (!pp_table_has_space(hwmgr, clock_info_array_offset,
+ sizeof(*clock_arrays)))
+ return -1;
- const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
+ clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
+ clock_info_array_offset);
+ clockInfoIndex = record->ucClockInfoIndex & 0x3F;
+ if (!clock_arrays->ucEntrySize || clockInfoIndex >= clock_arrays->ucNumEntries)
+ return -1;
- unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
+ clock_info_offset = clock_info_array_offset +
+ offsetof(ClockInfoArray, clockInfo) +
+ clockInfoIndex * clock_arrays->ucEntrySize;
+ if (!pp_table_has_space(hwmgr, clock_info_offset, clock_arrays->ucEntrySize))
+ return -1;
*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
@@ -1705,6 +1888,10 @@ static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
hwmgr->need_pp_table_upload = true;
powerplay_table = get_powerplay_table(hwmgr);
+ PP_ASSERT_WITH_CODE((powerplay_table),
+ "Missing PowerPlay Table!", return -1);
+ PP_ASSERT_WITH_CODE(pp_table_has_space(hwmgr, 0, sizeof(*powerplay_table)),
+ "Invalid PowerPlay Table!", return -1);
result = init_powerplay_tables(hwmgr, powerplay_table);
@@ -1807,4 +1994,3 @@ const struct pp_table_func pptable_funcs = {
.pptable_get_vce_state_table_entry =
get_vce_state_table_entry,
};
-
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] Bluetooth: hci_event: fix out-of-bounds read in LE PA report reassembly
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (49 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm: Validate legacy hwmgr PP table offsets Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/amd/display: Fix rounding errors in CalculatePrefetchSchedule Sasha Levin
` (465 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Laxman Acharya, Luiz Augusto von Dentz, Sasha Levin, marcel,
luiz.dentz, linux-bluetooth, linux-kernel
From: Laxman Acharya <acharyalaxman8848@gmail.com>
[ Upstream commit e3643fbddb257c928c075cab05bbd929106b56ee ]
hci_le_per_adv_report_evt() is dispatched with a minimum length of
sizeof(struct hci_ev_le_per_adv_report), which only covers the fixed
part of the event and not the trailing data[] array:
struct hci_ev_le_per_adv_report {
__le16 sync_handle;
__u8 tx_power;
__u8 rssi;
__u8 cte_type;
__u8 data_status;
__u8 length;
__u8 data[];
} __packed;
The handler notifies the ISO layer via hci_proto_connect_ind(), which
reaches iso_connect_ind(). That function retrieves the stored event with
hci_recv_event_data() and, while reassembling the periodic advertising
data, does:
memcpy(hcon->le_per_adv_data + hcon->le_per_adv_data_offset,
ev->data, ev->length);
ev->length is taken directly from the event and is never validated
against the amount of data the event actually carries. A controller
that reports a length larger than the received event therefore causes
the memcpy() to read past the end of the event buffer. The leaked bytes
are stored in hcon->le_per_adv_data and can subsequently be read back
from user space via getsockopt(BT_ISO_BASE).
Validate that the event contains ev->length data bytes before it is
consumed, mirroring the check already performed by
hci_le_ext_adv_report_evt() and hci_le_adv_report_evt().
Signed-off-by: Laxman Acharya <acharyalaxman8848@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a 6.12.111 tree (`pending-6.12`). The PA-report handler is
present and still copies `ev->length` without checking the event buffer,
so the OOB read and `BT_ISO_BASE` leak exist here.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[Bluetooth/hci_event] [fix] [out-of-bounds read while
reassembling LE periodic advertising reports]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Laxman Acharya <acharyalaxman8848@gmail.com>` (author)
- `Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>`
(Bluetooth maintainer applied it)
- No `Fixes:` tag (expected for this review)
- No `Cc: stable@vger.kernel.org` (expected)
- No `Reported-by:` / `Tested-by:` / `Reviewed-by:` / `Link:`
- Ignore any pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit
...]` markers
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: `hci_le_per_adv_report_evt()` is dispatched with `min_len ==
sizeof(struct hci_ev_le_per_adv_report)` (fixed header only).
`iso_connect_ind()` later does `memcpy(..., ev->data, ev->length)`
using the controller-supplied length with no check against remaining
event bytes.
- Symptom: slab/skb out-of-bounds read; copied bytes land in
`hcon->le_per_adv_data` and can be read from userspace via
`getsockopt(BT_ISO_BASE)`.
- Failure mode: kernel info leak (and KASAN OOB read / possible oops).
- Root cause: HCI LE Periodic Advertising Report `length` is trusted;
sibling handlers (`hci_le_adv_report_evt`,
`hci_le_ext_adv_report_evt`) already validate trailing data with
`hci_le_ev_skb_pull()`.
- Version info: none in the message. Local history puts the memcpy in
v6.9-rc1 (`168d9bf9c7f01`), present in this 6.12 tree.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. Subject and body describe a real OOB
read plus userspace-visible leak. Explicit `fix`.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `net/bluetooth/hci_event.c` — about +7 / -0 (comment + 2
executable lines)
- Function: `hci_le_per_adv_report_evt()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record: Before: after the debug print, the handler takes `hci_dev_lock`
and calls `hci_proto_connect_ind()` → `iso_connect_ind()`, which copies
`ev->length` bytes from the stored event. After:
`hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_PER_ADV_REPORT, ev->length)`
must succeed first; on failure the event is dropped and logged as a
malformed LE event. Normal well-formed reports are unchanged.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- Category: memory safety — buffer overflow / out-of-bounds **read**,
with kernel heap contents later exposed to userspace.
- Mechanism: `ev->length` (`u8`) is not compared to remaining skb bytes.
Destination is capped at `HCI_MAX_PER_AD_TOT_LEN` (1650) in `iso.c`,
so this is a **source** OOB, not a dest write overflow. The pull is
the same pattern as LE adv / ext-adv report handlers.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct. `skb_pull_data()` returns NULL when `skb->len
< len`. The check runs before the lock and before
`hci_proto_connect_ind()`, so a short event never reaches the memcpy.
Regression risk is very low: only malformed events are dropped. No
API/data-structure change. `hci_le_ev_skb_pull` is used only for
validation here; `iso_connect_ind()` still reads `hdev->recv_event` (a
clone taken before parsing pulls).
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Handler added in `9c0826310bfb7` (“Bluetooth: ISO: Add support for
periodic adv reports processing”, 2023-08-24) — contained in v6.6-rc1,
ancestor of HEAD.
- Unsafe memcpy added in `168d9bf9c7f01` (“Bluetooth: ISO: Reassemble PA
data for bcast sink”, 2024-03-06) — contained in **v6.9-rc1**,
ancestor of this 6.12 tree.
- Call already uses `PA_LINK` (`a8444cca514ed` is in this tree).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The memcpy that needs the check is
`168d9bf9c7f01`, present here (`git merge-base --is-ancestor`
succeeded).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same file already has length pulls for adv/ext-adv, BIG complete
(`22559ad7654f6`), etc. This is a standalone one-hunk fix, not patch
X/Y. No later local commit implements this check (`git grep
hci_le_ev_skb_pull.*PER_ADV` empty).
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Laxman Acharya is a regular Bluetooth bounds-checking
contributor, not the maintainer. Same-tree examples: `a34df5c4a439c`
(CIG params response length) and `930be1f6ae581` (vendor codec count).
Maintainer Luiz applied this patch.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs `hci_le_ev_skb_pull`, `HCI_EV_LE_PER_ADV_REPORT`,
`hci_le_per_adv_report_evt`, `iso_connect_ind` memcpy, and `PA_LINK`.
All exist in this checkout. Standalone.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Message-ID: `20260805173701.6649-1-acharyalaxman8848@gmail.com`
- `b4 dig -c` not usable: candidate SHA is not in this checkout.
- `b4 mbox` on that msgid: 3-message thread, **v1 only**.
- Recipients: Luiz von Dentz, Marcel Holtmann, linux-bluetooth, linux-
kernel.
- Applied to bluetooth-next as `96995a7d94f3` by Luiz (2026-08-07).
Listed in Luiz’s netdev pull `for-net-next-2026-08-07`.
- No NAK, no reviewer risk comments, no extra revisions.
- BlueZ CI: CheckPatch/build/sparse PASS; **iso-tester PASS**; GitLint
FAIL only for tabs in the quoted struct; mgmt/mesh failures are
unrelated timeouts.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Sent To Bluetooth maintainers; Luiz applied it (Ack-by-apply).
No extra Reviewed-by.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla `Reported-by`. Description matches the code
in this tree (`iso.c:2250-2251` memcpy; `iso_sock_getsockopt`
`BT_ISO_BASE`).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone `[PATCH]`, not a series. Same author also sent CIG
validation (already in this tree). No extra companion hunk required.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable returned 403. gnuweeb linux-bluetooth
index shows this patch (2 messages) with no stable-specific NAK. No
evidence it was rejected for stable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
semcode MCP tools were not available; used `git grep` and file reads.
**Step 5.1: KEY FUNCTIONS**
Record: `hci_le_per_adv_report_evt` (modified); uses
`hci_le_ev_skb_pull`; downstream `hci_proto_connect_ind` →
`iso_connect_ind`.
**Step 5.2: TRACE CALLERS**
Record: Only the LE subevent table (`HCI_EV_LE_PER_ADV_REPORT` /
`HCI_LE_EV_VL`). Path: `hci_event_packet` → `hci_event_func` →
`hci_le_meta_evt` (pulls `min_len` = 7-byte header) → handler. HCI
events come from the controller (USB/UART/virtio) or a user-channel HCI
socket (`CAP_NET_ADMIN` / `CAP_NET_RAW` in `hci_sock.c`).
**Step 5.3: TRACE CALLEES**
Record: `hci_le_ev_skb_pull` → `skb_pull_data` (NULL if short). Then
lock, `hci_proto_connect_ind` → `iso_connect_ind` →
`hci_recv_event_data` (clone at `hci_event_packet`) → memcpy of
`ev3->data`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable on CONFIG_BT + CONFIG_BT_LE (iso.o, default y) when a
broadcast-sink ISO socket matches `sync_handle`. `iso_sock_create()` has
no extra cap check. The memcpy runs only if `iso_get_sock` finds that
listener. Userspace can then read `le_per_adv_data` via
`getsockopt(BT_ISO_BASE)` when connected with `dst == BDADDR_ANY`.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Trailing-data pulls already in `hci_le_adv_report_evt`,
`hci_le_ext_adv_report_evt`, `hci_le_create_big_complete_evt`. This
handler was the missing analog for PA reports.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `net/bluetooth/hci_event.c:6460-6497` has the handler
**without** the pull. `iso.c:2246-2251` has dest-size check only, then
memcpy of `ev3->length`. Struct FAM is in `include/net/bluetooth/hci.h`.
Introduced v6.9, present in 6.12.111.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: `git apply --check` of the candidate hunk **succeeded**.
Insertion site matches (after `bt_dev_dbg`, before `hci_dev_lock`).
Expected difficulty: **clean apply**.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No. `git log --grep="out-of-bounds read in LE PA"` empty; no
`hci_le_ev_skb_pull(..., HCI_EV_LE_PER_ADV_REPORT, ev->length)`.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: `net/bluetooth` HCI event parsing + ISO (LE Audio / periodic
advertising / broadcast sink). **IMPORTANT** — not mm/core, but default-
on `CONFIG_BT_LE` on phones, laptops, IoT.
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Active; many recent HCI/ISO memory-safety fixes in this tree.
Pattern of trusting HCI length fields is a known class.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: Bluetooth LE users with ISO broadcast sink / PA sync (LE Audio /
Auracast-style). Config: `CONFIG_BT` + `CONFIG_BT_LE`. Driver- and
config-specific, not universal.
**Step 8.2: TRIGGER CONDITIONS**
Record: Malformed `HCI_EV_LE_PER_ADV_REPORT` (`length` larger than
remaining bytes) while a matching ISO listener exists. Sources:
buggy/malicious controller (including USB dongle), or privileged HCI
injection. Not every boot; realistic for HCI parsers. Unprivileged user
can hold the ISO socket; injecting the event usually needs
controller/firmware or `CAP_NET_ADMIN`/`CAP_NET_RAW`.
**Step 8.3: FAILURE MODE SEVERITY**
Record: Kernel OOB read of skb/slab tail; bytes stored and returned by
`getsockopt(BT_ISO_BASE)` → **info leak**. KASAN/hardened kernels can
oops. Severity: **HIGH** (memory safety + userspace-visible leak). Not a
guaranteed panic on every box, but not cosmetic.
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- Benefit: high for BT LE Audio/ISO users — stops OOB read and leak.
- Risk: very low — 2 code lines, established helper, drops only invalid
events.
- Ratio: strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB read of HCI event buffer; leak via `BT_ISO_BASE`.
- Buggy memcpy present in this 6.12 tree since v6.9.
- Small, obviously correct; same pull used by sibling handlers.
- Applies cleanly; all helpers/types present.
- Maintainer applied v1; iso-tester passed.
- No new feature/API.
AGAINST:
- Needs ISO broadcast-sink + PA report (not every Bluetooth device).
- No syzbot/`Fixes:`/`Cc: stable` (absence is expected).
- CI GitLint/mgmt/mesh noise is unrelated/cosmetic.
UNRESOLVED (do not drive the verdict):
- lore.kernel.org and git.kernel.org fetches blocked (403 / Anubis).
- `b4 dig -c` unused (SHA not in this repo); thread recovered via msgid.
- Mainline SHA after net-next merge not confirmed locally (bluetooth-
next `96995a7d94f3` and the 2026-08-07 pull are enough).
- No stable@ thread found (search blocked).
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — pull-before-consume;
maintainer applied; iso-tester PASS.
2. Real bug affecting users? **PASS** — OOB read + `getsockopt` leak on
ISO PA reassembly.
3. Important (crash/security/corruption/deadlock)? **PASS** — HIGH
memory-safety / info leak.
4. Small and contained? **PASS** — ~7 lines, one function.
5. No new features or APIs? **PASS**.
6. Can apply to this tree? **PASS** — `git apply --check` clean; bug
present.
**Step 9.3: EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary
security/correctness fix.
**Step 9.4: DECISION**
Backport. The bug is in this tree, the fix is surgical, and the user-
visible effect is a kernel info leak from a trusted-length HCI field.
---
### What this solves for 6.12 users
On 6.12.111, `hci_le_per_adv_report_evt()` still accepts a 7-byte header
and `iso_connect_ind()` copies `ev->length` bytes from the stored event.
A short HCI packet with a large `length` reads past the skb into
`hcon->le_per_adv_data`, which `getsockopt(BT_ISO_BASE)` can return. The
patch drops that event unless the skb actually contains `ev->length`
data bytes.
### Stable rules / risk vs benefit
Meets all six criteria. Benefit is preventing an OOB read and leak on
Bluetooth ISO PA reassembly; risk is dropping already-invalid events. No
missing prerequisites in this checkout.
### Concerns
None that block backport. Path is ISO/PA-specific, not every HCI user;
still a real memory-safety bug in default `CONFIG_BT_LE` code. No series
dependency.
---
Verification:
- [Phase 1] Parsed tags: author + Luiz SOB only; no
Fixes/Cc:stable/Reported-by
- [Phase 2] Diff: +7 lines in `hci_le_per_adv_report_evt`;
`hci_le_ev_skb_pull(..., ev->length)` before consume
- [Phase 2] Confirmed dest check in `iso.c:2246-2248` vs missing source
check at `iso.c:2250-2251`
- [Phase 2] `skb_pull_data` returns NULL if `skb->len < len`
(`net/core/skbuff.c:2667-2676`)
- [Phase 3] `git describe HEAD` / Makefile: **6.12.111**, branch
`pending-6.12`
- [Phase 3] blame: handler `9c0826310bfb7` (v6.6-rc1); memcpy
`168d9bf9c7f01` (v6.9-rc1); both ancestors of HEAD
- [Phase 3] `git merge-base --is-ancestor 168d9bf9c7f01 HEAD` → yes
- [Phase 3] `git log --grep="out-of-bounds read in LE PA" --
net/bluetooth/` → empty (fix not in tree)
- [Phase 3] `hci_le_ev_skb_pull` present at `hci_event.c:71-81`
- [Phase 4] `b4 mbox` msgid
`20260805173701.6649-1-acharyalaxman8848@gmail.com`: v1, 3 msgs, no
NAK; applied bluetooth-next `96995a7d94f3`
- [Phase 4] BlueZ CI: iso-tester PASS; GitLint tabs in commit-message
sample; unrelated mgmt/mesh timeouts
- [Phase 4] netdev pull 2026-08-07 lists this commit under Laxman
Acharya
- [Phase 4] UNVERIFIED: lore.kernel.org 403; git.kernel.org Anubis; `b4
dig -c` skipped (SHA not local)
- [Phase 5] Call chain: event table → `hci_le_meta_evt` min_len pull →
handler → `hci_proto_connect_ind` (`PA_LINK`) → `iso_connect_ind`
- [Phase 5] `hci_recv_event_data` uses `skb_clone` taken before pulls
(`hci_event.c:7575-7576`)
- [Phase 5] `BT_ISO_BASE` getsockopt copies `le_per_adv_data`
(`iso.c:1834-1848`)
- [Phase 5] `iso.o` built with `CONFIG_BT_LE`; `iso_sock_create` has no
extra cap
- [Phase 6] Local handler at `hci_event.c:6460` lacks the pull; `git
apply --check` of candidate hunk exit 0
- [Phase 8] Failure mode: OOB read + userspace info leak; severity HIGH
- UNVERIFIED: whether mgmt/mesh CI fails are pre-existing flakes (iso-
tester passed; those tests are unrelated)
**YES**
net/bluetooth/hci_event.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 23fe327a0fcd6..fd823baf64415 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6580,6 +6580,13 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle));
+ /* The reassembly in iso_connect_ind() copies ev->length bytes from the
+ * stored event, so make sure the event actually carries that many data
+ * bytes before it is consumed.
+ */
+ if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_PER_ADV_REPORT, ev->length))
+ return;
+
hci_dev_lock(hdev);
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, PA_LINK, &flags);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amd/display: Fix rounding errors in CalculatePrefetchSchedule
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (50 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] Bluetooth: hci_event: fix out-of-bounds read in LE PA report reassembly Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] ASoC: Intel: bytcr_rt5651: Add quirk for Chuwi Hi8 with generic DMI strings Sasha Levin
` (464 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Matthew Stewart, Dillon Varone, Fangzhi Zuo, Dan Wheeler,
Alex Deucher, Sasha Levin, harry.wentland, sunpeng.li,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Matthew Stewart <Matthew.Stewart2@amd.com>
[ Upstream commit fa0300333db07ca4ad56c9879f155faafd3f7079 ]
[why]
Rounding errors were causing mode validation to fail in some cases when
it should not. (IE. Increasing fclk from a lower value could lead to
validation failure, which should not happen.)
Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Matthew Stewart <Matthew.Stewart2@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Connection lost, reconnecting to https://agentn.us.api5.cursor.sh
(attempt 1)...
Retry attempt 1...
I have enough to decide: this is a small DCN4 DML prefetch-rounding fix
in 7.3-rc4, and the remaining work is to write the phase-by-phase
verdict.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [drm/amd/display] [Fix] [rounding errors in
CalculatePrefetchSchedule causing false mode-validation failures]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Reviewed-by: Dillon Varone <dillon.varone@amd.com>
- Signed-off-by: Matthew Stewart <Matthew.Stewart2@amd.com>
(author)
- Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com> (DC series
collector)
- Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
- Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (amdgpu
maintainer)
- No Fixes: tag (expected)
- No Reported-by, no syzbot, no Link:, no Cc: stable
- Ignore any Sasha Levin SOB / Upstream-commit markers if present in a
candidate wrapper; none are in the real commit
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: rounding in the DCN4 DML21 prefetch scheduler made mode
validation fail for configurations that are actually valid.
- Symptom: increasing fclk (fabric clock) from a working lower value can
cause validation to fail. That is non-monotonic and should not happen.
- Failure mode: Display Core rejects a mode (`PrefetchSupported` /
`NoTimeForPrefetch`), so a modeset or clock bump that should work is
refused.
- No stack trace, no CVE, no named kernel version range in the message.
- Root cause (from message + comments in the diff): VM/row prefetch
times are later ceiled to quarter-line units, which steals time from
the swath (SW) stage. `Tsw_est*` did not account for that, so the
wrong prefetch-bandwidth case was selected.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. Subject and body state a real
validation bug. The three subtracted LineTime fractions are the actual
fix.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_
core_dcn4_calcs.c`
- +6 / -3 (stat of fa0300333db07)
- Function: `CalculatePrefetchSchedule`
- Scope: single-file surgical change to three assignments
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: `Tsw_est1/2/3 = prefetch_sw_bytes / prefetch_bwN` (SW time
estimated with no rounding slack).
- After:
- `Tsw_est1 -= 3/4 LineTime` (VM +1/4, two rows +2/4)
- `Tsw_est2 -= 1/4 LineTime` (VM only)
- `Tsw_est3 -= 2/4 LineTime` (two rows)
- Affected path: DML mode-support / mode-programming prefetch bandwidth
selection, not an error-path or init-only path.
- Those `Tsw_est*` values feed `if (Tsw_estN < min_Lsw_equ * LineTime)`
which already subtracts 0.75 / 0.25 / 0.5 LineTime when recalculating
`prefetch_bw1/2/3`. The initial estimate is now consistent with that
later quarter-line rounding.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [Logic / correctness] [DML prefetch time rounding]
- Later in the same function, VM and row times are ceiled to U2.2
quarter-lines:
`dst_y_per_vm_vblank = ceil(4 * Tvm / LineTime) / 4` and the same for
rows.
- That can consume up to +1/4 line (VM) and +1/4 line × 2 rows. SW then
has less time than `Tsw_est` assumed, so the equalized bandwidth case
is wrong and validation fails even though the mode is feasible
(including after an fclk increase).
- Category is not UAF/leak/race/NULL; it is display-mode calculator
incorrectness.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Quality: high. The 3/4, 1/4, 2/4 constants match the existing 0.75 /
0.25 / 0.5 LineTime terms and the documented quarter-line clamp.
- Minimal: three expressions plus comments.
- Regression risk: changing DML bandwidth can theoretically accept a
mode that underflows, or reject a previously accepted one. Here the
change only makes `Tsw_est` pessimistic so the already-margined
recalculation path runs; the author states the old path rejected valid
modes. Reviewed and Tested-by AMD display.
- No public API / data-structure change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- File added as DCN401 DML21 in 70839da636050 (`drm/amd/display: Add new
DCN401 sources`, 2024-04-26). Present from v6.11 onward.
- Surrounding `Tpre_rounded` / `Tsw_est` logic largely from
be4e3509314af7 (`DML21 Reintegration For Various Fixes`, 2024-12-18).
- The three `Tsw_est*` lines are fa0300333db07 itself (2026-06-19 /
committed 2026-07-28).
- Bug has been in DCN4 DML21 since that IP was added, not a last-month
regression.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Not applicable. Buggy code is the original DCN4
prefetch estimator, not a one-commit regression.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Recent file commits include DCN6 compile, PMO pstate plumbing, this
fix, UCLK pstate, divide-by-zero, HDMI FRL, HostVM units.
- Follow-ups after this fix (9fcd9c7545654, 992694ad28584) do not revert
or rework these three lines.
- Standalone mathematically; landed as patch 46/49 of a bulk DC drop,
but the hunk has no dependency on 45/47/etc.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Matthew Stewart is an AMD display engineer (DCN42B enablement,
soc_bb, register masks). Not the drm/amd maintainer; Alex Deucher signed
it off. Related nearby work is DCN42B, not a prerequisite for this
rounding change.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: No extra helpers or struct fields. Can apply standalone wherever
this `CalculatePrefetchSchedule` exists. This tree uses `dml2_0/`
(rename e6a8a000cfe6a, 2025-10-28); older stables still on `dml2/` would
only need a path tweak. No missing prerequisites in this checkout.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c fa0300333db07` failed: lore.kernel.org returned errors.
- Found on amd-gfx: [PATCH 46/49] in “DC Patches July 20th, 2026”
- Cover: https://lists.freedesktop.org/archives/amd-
gfx/2026-July/149310.html
- Patch: https://lists.freedesktop.org/archives/amd-
gfx/2026-July/149359.html
- Cover letter summary: KUnit expansion, dm refactor, Apple 5K tiled
monitor, FRL/DSC, dcn42 fixes. This rounding fix is not called out as
a highlight.
- Diff on the list matches the committed change. No v2/v3 of this
specific patch.
- No reviewer NAK, no Cc: stable in the mail.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: Reviewed-by Dillon Varone (DML/DCN4). Tested-by Dan Wheeler.
Collected by Fangzhi Zuo, merged by Alex Deucher. Appropriate AMD
display reviewers.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No user bugzilla/syzbot/lore bug report found. Evidence is AMD
internal: “some cases”, fclk monotonicity example. Severity from the
author: false mode-validation failure, not oops.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Independent of the rest of the 49-patch DC drop (KUnit,
refactors, Apple tiled display, etc.). DCN5
`dml2_core_dcn5_calcs_dchub.c` still uses unadjusted `Tsw_est*`; this
fix is DCN4 DML21 only.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search returned 403.
lists.freedesktop.org has no AUTOSEL of this subject. Unverified whether
stable@ ever discussed it.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `CalculatePrefetchSchedule` only (static in
dml2_core_dcn4_calcs.c).
Step 5.2: TRACE CALLERS
Record: Two call sites in the same file:
- Mode support (~line 7645): `mode_lib->ms.NoTimeForPrefetch[k] =
CalculatePrefetchSchedule(...)` then `PrefetchSupported &=
!NoTimeForPrefetch[k]`
- Mode programming (~line 11473): `mode_lib->mp.NoTimeToPrefetch[k] =
CalculatePrefetchSchedule(...)`
`dml2_core_calcs_mode_support_ex` is used from `dml2_core_dcn4.c` during
DC mode validation.
Step 5.3: TRACE CALLEES
Record: Floating-point DML math (`math_max2/3`, `math_ceil2`), no
alloc/lock/I/O. Pure calculator.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace DRM atomic modeset / DC validate → DML21 mode_support
→ CalculatePrefetchSchedule. Reachable on DCN4 family (DCN401/42/42B;
dcn401_resource.c sets `.using_dml21 = true`). Not a syscall crash path;
it is the normal display-mode path for those GPUs.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same unadjusted `Tsw_est` pattern remains in DCN5 DML21 and
older VBA DML (dcn31/32/314). Not a tree-wide systematic fix;
DCN4-specific.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Local tree: `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4.
- File and function exist. Current tree already has the fixed `Tsw_est*`
lines (fa0300333db07 is an ancestor of HEAD; also in v7.3-rc1).
- Bug introduced with DCN401 sources (v6.11). This 7.3 codebase includes
that IP.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Expected apply on this tree: clean (context matches). No
conflicting local changes around those three assignments.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No earlier alternate fix of these `Tsw_est*` lines. No revert.
DCN5 still unfixed (different file).
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [drm/amd/display DML21 DCN4] [IMPORTANT] — not mm/core, but
current AMD dGPU/APU display mode library. DCN401 is GC 12.0
(RDNA4-class). Affects all users of that display IP.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Very active (DC drops, DCN42B, DCN6). This is a calculator
correction in a mature DCN4 path, not a new subsystem.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific / DCN4-family AMD display (DCN401/42/42B with
DML21). Not universal; not staging.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger is DML prefetch scheduling during mode validation,
especially near rounding boundaries and when fclk changes. Common for
anyone setting modes or changing clocks on those GPUs. Unprivileged
userspace can trigger via KMS modeset. Not a rare CONFIG-only path.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: [False mode validation failure / non-monotonic fclk] [MEDIUM,
user-visible HIGH on affected HW]
- Not panic, UAF, deadlock, or filesystem corruption.
- Result: atomic commit / mode rejected; valid timing or a clock
increase can fail. That is a real display functional bug (blank / mode
not available / DPM clock bump fails), not cosmetic logging.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: DCN4 users keep modes that should work; fclk increases remain
monotonic. High for that hardware, moderate globally.
- Risk: 3-line DML tweak, internally consistent with existing margins,
reviewed/tested. Low.
- Ratio: favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real user-visible bug: DML falsely fails prefetch/mode validation.
- Concrete symptom: raising fclk can make validation fail.
- Small, obviously correct vs quarter-line VM/row ceils already in this
function.
- Reviewed-by Dillon Varone, Tested-by Dan Wheeler, SOB Alex Deucher.
- DCN4 DML21 is in this 7.3-rc4 tree; fix applies cleanly.
- Similar DML prefetch correctness patches have historically been stable
material (underflow/clamp fixes).
- Standalone; no new API.
AGAINST:
- Not a crash, security hole, leak, or data-corruption bug.
- No external reporter / syzbot / Fixes: tag.
- Landed inside a 49-patch DC dump, not highlighted as a stable item.
- DML float tweaks can in principle change which modes pass; residual
underflow risk is low but non-zero.
- DCN5 sibling calculator left unchanged (DCN4-only).
UNRESOLVED:
- lore.kernel.org (b4 dig and stable list) returned HTTP errors; amd-gfx
archive was used instead.
- No public reproducer beyond the author’s fclk example.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — quarter-line math matches
existing 0.75/0.25/0.5 paths; Tested-by + Reviewed-by.
2. Fixes a real bug that affects users? PASS — false mode reject on DCN4
validation, including fclk increase.
3. Important issue? PASS — display mode / clock-validation failure on
current AMD DCN4 hardware is a serious functional bug for those users
(not a panic, but modeset/DPM can fail).
4. Small and contained? PASS — 6 insertions / 3 deletions, one function.
5. No new features or APIs? PASS.
6. Can apply to the local tree? PASS — file/function present; hunk
matches this tree.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None of device-ID / quirk / DT / build / docs. Qualifies as a
normal small correctness fix.
Step 9.4: MAKE YOUR DECISION
This tree is 7.3.0-rc4 and contains DCN4 DML21. The patch is a small,
reviewed correction so prefetch time estimates match the quarter-line
rounding the hardware/DML already applies. Without it, valid modes can
be rejected and raising fclk can fail validation. That is a real display
bug, not a feature or cleanup. Risk is low relative to the benefit for
DCN4 users of this codebase.
Verification:
- [Phase 1] Parsed tags: Reviewed-by Dillon Varone; Tested-by Dan
Wheeler; SOB Matthew Stewart, Fangzhi Zuo, Alex Deucher; no
Fixes:/Reported-by/Cc: stable
- [Phase 2] Diff: 3 `Tsw_est*` assignments in
`CalculatePrefetchSchedule`; subtract 3/4, 1/4, 2/4 LineTime
- [Phase 2] Confirmed later code ceils VM/row to quarter-lines and
already uses 0.75/0.25/0.5 LineTime in the BW-update path
- [Phase 3] `git merge-base --is-ancestor fa0300333db07 HEAD` → yes
(exit 0)
- [Phase 3] File added in 70839da636050; in v6.11+, not in v6.10; fix in
v7.3-rc1+
- [Phase 3] blame: original DCN401 DML (Aurabindo Pillai) / DML21
reintegration (Austin Zheng)
- [Phase 4] b4 dig: lore server error (UNVERIFIED via b4)
- [Phase 4] amd-gfx: patch 46/49 of DC July 20 2026 (149310 cover,
149359 patch); no NAK; not Cc: stable
- [Phase 4] lore.kernel.org/stable: 403 (UNVERIFIED)
- [Phase 5] Callers: mode_support and mode_programming in the same file;
`PrefetchSupported &= !NoTimeForPrefetch`
- [Phase 5] dcn401_resource.c `.using_dml21 = true`
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37;
kernelversion 7.3.0-rc4; buggy/fixed code present
- [Phase 6] DCN5 still has unadjusted Tsw_est (different IP)
- [Phase 8] Failure mode: false DML mode validation fail, not oops
- UNVERIFIED: whether older LTS trees need a `dml2/` vs `dml2_0/` path
tweak (out of scope for this checkout)
**YES**
.../dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index da865bd466c9a..c32b704627085 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -5554,7 +5554,8 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch
+ 2 * (p->PixelPTEBytesPerRow * p->HostVMInefficiencyFactor + p->meta_row_bytes + tdlut_row_bytes)
+ *p->prefetch_sw_bytes)
/ (*p->Tpre_rounded - *p->Tno_bw);
- s->Tsw_est1 = *p->prefetch_sw_bytes / s->prefetch_bw1;
+ /* due to rounding, VM can clamp to +1/4, Row can clamp to +2/4, giving SW less time */
+ s->Tsw_est1 = *p->prefetch_sw_bytes / s->prefetch_bw1 - 3.0 * s->LineTime / 4.0;
} else
s->prefetch_bw1 = 0;
@@ -5578,7 +5579,8 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch
if (*p->Tpre_rounded - *p->Tno_bw - 2.0 * s->Tr0_trips_rounded > 0) {
s->prefetch_bw2 = (vm_bytes * p->HostVMInefficiencyFactor + *p->prefetch_sw_bytes) /
(*p->Tpre_rounded - *p->Tno_bw - 2.0 * s->Tr0_trips_rounded);
- s->Tsw_est2 = *p->prefetch_sw_bytes / s->prefetch_bw2;
+ /* due to rounding, VM can clamp to +1/4 */
+ s->Tsw_est2 = *p->prefetch_sw_bytes / s->prefetch_bw2 - 1.0 * s->LineTime / 4.0;
} else
s->prefetch_bw2 = 0;
@@ -5592,7 +5594,8 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch
if (*p->Tpre_rounded - s->Tvm_trips_rounded > 0) {
s->prefetch_bw3 = (2 * (p->PixelPTEBytesPerRow * p->HostVMInefficiencyFactor + p->meta_row_bytes + tdlut_row_bytes) + *p->prefetch_sw_bytes) /
(*p->Tpre_rounded - s->Tvm_trips_rounded);
- s->Tsw_est3 = *p->prefetch_sw_bytes / s->prefetch_bw3;
+ /* due to rounding, Row can clamp to +2/4 */
+ s->Tsw_est3 = *p->prefetch_sw_bytes / s->prefetch_bw3 - 2.0 * s->LineTime / 4.0;
} else
s->prefetch_bw3 = 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] ASoC: Intel: bytcr_rt5651: Add quirk for Chuwi Hi8 with generic DMI strings
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (51 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] drm/amd/display: Fix rounding errors in CalculatePrefetchSchedule Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amdgpu: Validate ATIF buffer length before use Sasha Levin
` (463 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Jasper Firth, Mark Brown, Sasha Levin, cezary.rojewski,
liam.r.girdwood, peter.ujfalusi, yung-chuan.liao, kai.vehmanen,
perex, tiwai, linux-sound, linux-kernel
From: Jasper Firth <jasper.m.f@hotmail.com>
[ Upstream commit c5a8fc2abe05cf6db71f57ff0177fddc59861a1a ]
Some Chuwi Hi8 tablets with model number CWI513 ship with a BIOS
(American Megatrends 5.11, dated 05/21/2016) whose DMI sys_vendor and
product_name are both "Default string". The tested unit is labelled
just "Hi8", but its model number is the same as the existing "Chuwi Hi8
Pro (CWI513)" entry, and it needs the same quirks. That entry matches on
sys_vendor "Hampoo" and product_name "X1D3_C806N", so it never applies
to these units.
Without its quirks the internal speaker, whose amplifier has a
differential input wired across LOUT left and right, cancels to a faint
distorted residual for any centred (L == R) content, and the headphone
channels are swapped.
Add an entry matching board_vendor "Hampoo" and board_name "Cherry Trail
CR", plus the BIOS date since those two are too generic on their own.
drivers/platform/x86/touchscreen_dmi.c already matches the Chuwi HiBook
the same way.
The quirks are those of the existing Hi8 Pro entry, except for the
over-current detection scale factor: 1.0 instead of the 0.75 from
BYT_RT5651_DEFAULT_QUIRKS. With 0.75 and a CTIA headset (inline mic and
one button), loud speech into the mic, and headphone playback coupling
onto the mic line, were reported as spurious KEY_PLAYPAUSE presses, one
of them held for a whole 8 second speech window. With 1.0 the same test
gave no spurious events, and 3 real button presses were reported as
exactly 3 press/release pairs.
Tested on a unit with the generic DMI strings, with a module built from
this patch and no quirk module parameter. The quirks were applied via
the new entry, the card components read "cfg-spk:1 cfg-mic:in2
cfg-hp:lrswap", and the following all work: speaker, headphone left/right
order, jack and headset-mic detection, headset button, and the internal
and headset mics.
The problem was diagnosed with the help of an AI coding assistant, which
also drafted this changelog.
Assisted-by: Claude Opus 5.5
Signed-off-by: Jasper Firth <jasper.m.f@hotmail.com>
Link: https://patch.msgid.link/20260925-hi8-quirk-v1-1-ffd00b0447f9@hotmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: this is a DMI hardware quirk for a tablet whose
audio is already broken without it, and the surrounding driver code is
present in this 6.18 tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [ASoC/Intel/bytcr_rt5651] [Add] [DMI quirk so Chuwi Hi8 units
with generic BIOS strings get the existing audio workarounds]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Assisted-by: Claude Opus 5.5
- Signed-off-by: Jasper Firth \<jasper.m.f@hotmail.com\> (author)
- Link: https://patch.msgid.link/20260925-hi8-quirk-v1-1-
ffd00b0447f9@hotmail.com
- Signed-off-by: Mark Brown \<broonie@kernel.org\> (ASoC maintainer)
- No Fixes: tag (expected)
- No Reported-by / Tested-by / Reviewed-by / Acked-by
- No Cc: stable@vger.kernel.org (expected; not a negative)
- Ignore pipeline-added "[Upstream commit ...]" and Sasha Levin SOB
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: Some Chuwi Hi8 CWI513 tablets ship AMI BIOS 5.11 dated 05/21/2016
with DMI sys_vendor and product_name both "Default string". The
existing "Chuwi Hi8 Pro (CWI513)" entry matches sys_vendor "Hampoo" +
product_name "X1D3_C806N" and never applies.
- Symptom: internal speaker (differential amp across LOUT L/R) cancels
to a faint distorted residual for centred (L==R) content; headphone
L/R swapped. With default OVCD scale 0.75, loud speech into a CTIA
headset mic produced spurious KEY_PLAYPAUSE events (one held for an 8s
window).
- Root cause: missing DMI match, so DEFAULT_QUIRKS (stereo path, SF
0.75) are used on hardware that needs mono-speaker mix, HP swap, and
OVCD SF 1.0.
- Version info: hardware/BIOS from 2016; no kernel-version restriction
stated.
- Author tested on a real unit without the quirk module parameter; card
components became "cfg-spk:1 cfg-mic:in2 cfg-hp:lrswap"; speaker, HP
order, jack/headset-mic, button, and both mics worked.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit hardware-quirk
addition. The "add" verb here is the standard form for DMI/quirk table
entries that fix broken hardware, not a new feature.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- Files: sound/soc/intel/boards/bytcr_rt5651.c only (+17 / -0)
- Functions: none modified; one new `dmi_system_id` entry in
`byt_rt5651_quirk_table[]`
- Scope: single-file surgical table addition
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: `dmi_check_system(byt_rt5651_quirk_table)` in
`snd_byt_rt5651_mc_probe()` never matches these units, so
`byt_rt5651_quirk` stays `BYT_RT5651_DEFAULT_QUIRKS |
BYT_RT5651_IN2_MAP`.
- After: units with board_vendor "Hampoo", board_name "Cherry Trail CR",
and BIOS date "05/21/2016" set:
MCLK_EN | JD1_1 | OVCD_TH_2000UA | OVCD_SF_1P0 | IN2_MAP |
HP_LR_SWAPPED | MONO_SPEAKER
- That is the existing Hi8 Pro quirk set with OVCD scale 1.0 instead of
DEFAULT_QUIRKS' 0.75.
- Path: machine-driver probe / initialization only. Callback
`byt_rt5651_quirk_cb` still just stores `driver_data` and returns 1.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: (h) hardware workaround / DMI quirk table entry
- Mechanism: without MONO_SPEAKER the stereo DAC feeds a differential
mono amp and centred audio cancels (this is the same failure Hans de
Goede documented in `a0d1d867c262f`, "Add mono speaker quirk").
Without HP_LR_SWAPPED, headphone channels are reversed. OVCD_SF_1P0
raises the headset-button over-current scale so coupled mic audio is
not reported as KEY_PLAYPAUSE.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: additive table entry using the same callback and
flag bits already used by the Hi8 Pro / Vi8 Plus entries.
- Match is deliberately narrowed with BIOS date after the author noted
board_vendor+board_name are too generic; same comment/pattern as Chuwi
HiBook in `drivers/platform/x86/touchscreen_dmi.c`.
- `dmi_check_system()` stops on first callback returning non-zero.
Existing Hi8 Pro entry is earlier in the table, so units with proper
"Hampoo"/"X1D3_C806N" strings keep the old flags.
- Residual risk: another Hampoo "Cherry Trail CR" board with BIOS date
05/21/2016 and the RT5651 machine driver could get mono/HP-swap
incorrectly. BIOS date plus first-match-wins makes that small. No
locking/API/data-structure changes.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Quirk table exists since Pierre-Louis Bossart, 2016
(`2bd5bd15a51858`).
- Existing "Chuwi Hi8 Pro (CWI513)" match (Hampoo / X1D3_C806N) from
Hans de Goede, 2018 (`55d69c0309acea` / `8f250e7009d71`).
- MONO_SPEAKER + HP_LR_SWAPPED on that entry from 2018
(`a0d1d867c262f4`).
- The buggy situation is long-standing: these generic-DMI units have
never matched. Introduced with the 2016 BIOS, not by a recent kernel
change.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Not applicable. The "bug" is missing DMI
coverage, not a regression from a tagged commit.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Recent file history is unrelated (DAPM idle_bias, invalid quirk
mapping, DPCM flags, remove() conversion).
- Original Hi8 Pro/Vi8 Plus DMI entries and all flag macros are already
in this tree.
- Standalone; not patch X/Y.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Only this commit by Jasper Firth under
`sound/soc/intel/boards/`. Not a subsystem maintainer. Hans de Goede
(historical author of these Chuwi entries) and Intel ASoC maintainers
were on the original To/Cc. Mark Brown applied it the same day.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: No extra commits needed. `BYT_RT5651_MCLK_EN`, `JD1_1`,
`OVCD_TH_2000UA`, `OVCD_SF_1P0`, `IN2_MAP`, `HP_LR_SWAPPED`,
`MONO_SPEAKER`, `byt_rt5651_quirk_cb`, and
`dmi_check_system(byt_rt5651_quirk_table)` all exist in v6.18.57. Can
apply standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- b4 dig -c c5a8fc2abe05cf6db71f57ff0177fddc59861a1a matched https://pat
ch.msgid.link/20260925-hi8-quirk-v1-1-ffd00b0447f9@hotmail.com
- b4 dig -a: v1 only (2026-09-25)
- Thread has two messages: submission and Mark Brown "Applied to
broonie/sound.git for-7.3"
- No NAKs, no requested revisions, no reviewer Cc: stable
- Author note (not in the final commit body): left the existing Hi8 Pro
entry unchanged because they do not have an X1D3_C806N unit; that
model may still see OVCD_SF_0P75 spurious buttons. This patch does not
change that entry.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (b4 dig -w): linux-sound, linux-kernel, Mark Brown, Takashi Iwai,
Jaroslav Kysela, Hans de Goede, Pierre-Louis Bossart, Liam Girdwood,
Cezary Rojewski, Bard Liao, Kai Vehmanen, Peter Ujfalusi. Subsystem
maintainer applied it. No extra Reviewed-by.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla link. Evidence is the author's hardware test
in the changelog (speaker cancellation, swapped HP, spurious
KEY_PLAYPAUSE, and post-fix verification).
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Single standalone patch, change-id
20260925-hi8-quirk-00ca3a49b32f. No series dependencies.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: Web search of lore.kernel.org/stable for this subject/file found
no discussion of this quirk. Nobody requested or rejected it for stable
in a thread I could verify.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: No function bodies changed. Data consumed by
`byt_rt5651_quirk_cb()` and `snd_byt_rt5651_mc_probe()`.
Step 5.2: TRACE CALLERS
Record:
- `byt_rt5651_quirk_cb` is only used as `.callback` in this DMI table.
- `dmi_check_system(byt_rt5651_quirk_table)` is called once from
`snd_byt_rt5651_mc_probe()` (line 1024).
- That probe is the platform driver `bytcr_rt5651`
(`MODULE_ALIAS("platform:bytcr_rt5651")`).
- Context: device probe, not IRQ/hot path. Userspace cannot call it
directly; it runs when this Bay Trail / Cherry Trail RT5651 machine
driver binds.
Step 5.3: TRACE CALLEES
Record: Callback only assigns `byt_rt5651_quirk`. Probe later uses those
bits for codec device properties, card `components` (`cfg-spk:1`, `cfg-
hp:lrswap`), long_name, and jack OVCD settings. No new allocations or
locks.
Step 5.4: FOLLOW THE CALL CHAIN
Record: ACPI/platform match → `snd_byt_rt5651_mc_probe` →
`dmi_check_system` → quirk flags → ALSA card registration / UCM profile
selection. Reachable on this tablet at every boot if
`CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH` is enabled (recommended in
Kconfig for such devices). Not a syscall-triggered crash path.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same Hampoo + "Cherry Trail CR" + BIOS-date pattern already used
for Chuwi HiBook in `touchscreen_dmi.c` (BIOS date 05/07/2016, different
from 05/21/2016). Sibling Hi8 Pro / Vi8 Plus audio entries already exist
in this same table. VIOS LTH17 already uses `BYT_RT5651_OVCD_SF_1P0`.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Local tree: `git describe HEAD` = v6.18.57-155-gcdf239ca885b2; `make
kernelversion` = 6.18.57.
- File and quirk table exist at v6.18.57. Existing Hi8 Pro entry is
present; generic-DMI units still miss it.
- Bug is missing coverage, present for as long as this driver has been
used on these 2016 tablets.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Against v6.18.57 the hunk applied with a 1-line offset (`Hunk #1
succeeded at 409`). Context around the Hi8 Pro entry is identical.
Expected difficulty: clean apply / trivial offset. All flag macros exist
unchanged.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: `git log v6.18..v6.18.57 --
sound/soc/intel/boards/bytcr_rt5651.c` is empty; 6.18.y has not already
taken a different fix for this. No "generic DMI" match exists without
this entry. Existing Hi8 Pro match does not cover "Default string"
vendor/product.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [sound/soc/intel/boards – Intel Baytrail/Cherry Trail ASoC
machine driver] [PERIPHERAL / driver-specific, but a supported in-tree
board driver, not staging]
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature. Quirk table dates to 2016–2018; recent commits are small
maintenance. This is a late hardware-coverage add, not a rewrite of new
code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific / DMI-specific. Only Chuwi Hi8 CWI513-class
units with board_vendor Hampoo, board_name "Cherry Trail CR", BIOS date
05/21/2016, using this RT5651 machine driver. Other users are unchanged
unless they share that exact triple (unverified but constrained).
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Every probe/boot on matching hardware. No race. Unprivileged
users do not trigger a kernel bug; they just get broken audio / spurious
KEY_PLAYPAUSE until the quirk is applied.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- Failure: internal speaker effectively unusable for typical centred
content; swapped headphones; false headset-button events.
- Severity: MEDIUM for the affected device (real functional break, not a
panic). Not CRITICAL in the crash/corruption sense, but it is the
class of hardware-quirk issue stable trees routinely take.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: high for owners of this tablet (speaker/headphones/jack
actually work); zero for everyone else if the DMI triple is unique.
- Risk: very low — 17-line table add, existing flags, probe-time only,
first-match preserves the older Hi8 Pro entry.
- Ratio: favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real hardware bug: differential mono speaker cancellation, swapped HP,
spurious KEY_PLAYPAUSE
- Author tested on the affected unit; quirks applied without module-
parameter override
- Textbook stable exception: DMI/hardware quirk on an existing driver
- Small (+17), contained, no new API
- All consumed flags and the table hook exist in this 6.18.57 tree
- Applies with a trivial offset
- Same matching strategy already used for Chuwi HiBook
- ASoC maintainer applied v1 the same day; Intel ASoC and Hans de Goede
were CC'd
- Existing more-specific Hi8 Pro entry remains first and still wins for
X1D3_C806N units
AGAINST:
- Niche 2016 tablet, one reporter/tester
- Not a crash, security hole, or data-corruption bug
- Theoretical false match on another Hampoo Cherry Trail CR board with
the same BIOS date
- No Fixes:/Cc: stable; Mark Brown queued it for the 7.3 merge window
rather than as an urgent fix
UNRESOLVED:
- Could not fetch lore.kernel.org HTML (403); thread reconstructed via
b4 dig + Patchew + LKML archive
- Could not prove no other product shares Hampoo + "Cherry Trail CR" +
BIOS 05/21/2016
- No stable-list thread found
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — additive DMI entry, author
hardware test, maintainer applied
2. Fixes a real bug that affects users? PASS — broken speaker/HP/jack on
a shipping tablet
3. Important issue? PASS under the hardware-quirk exception (device
unusable audio, not a panic)
4. Small and contained? PASS — +17 lines, one table entry
5. No new features or APIs? PASS — existing quirk flags only
6. Can apply to the local tree? PASS — driver + flags present; hunk
applies to v6.18.57
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Hardware quirk / DMI workaround on an existing driver. This is
an allowed stable exception.
Step 9.4: MAKE YOUR DECISION
This is a small, tested DMI quirk that makes existing Chuwi Hi8 hardware
work on this 6.18 tree. Benefit is real for those units; regression
surface is limited to an already-narrow DMI triple. It should be
backported.
Verification:
- [Phase 1] Parsed subject/tags/body from `git show 80c7d7ab1fe03` /
upstream `c5a8fc2abe05`; no Fixes:/syzbot/Cc: stable; Link to msgid
- [Phase 2] Diff is +17 lines in `byt_rt5651_quirk_table[]` only;
compared flags to `BYT_RT5651_DEFAULT_QUIRKS` (diff is OVCD_SF_1P0 vs
0.75)
- [Phase 2] Confirmed `dmi_check_system()` stops when callback returns
non-zero (`drivers/firmware/dmi_scan.c`)
- [Phase 3] `git blame -L 399,423 v6.18.57 --
sound/soc/intel/boards/bytcr_rt5651.c`: Hi8 Pro entry from 2018 Hans
de Goede
- [Phase 3] `git show a0d1d867c262f`: MONO_SPEAKER exists because stereo
mix on a mono amp garbles centred audio
- [Phase 3] `git log --oneline --author='Jasper Firth' --
sound/soc/intel/boards/`: only this commit
- [Phase 3] Flag macros present in `git show
v6.18.57:sound/soc/intel/boards/bytcr_rt5651.c`
- [Phase 4] `b4 dig -c c5a8fc2abe05...` → lore msgid; `-a` v1 only; `-w`
ASoC/Intel/Hans de Goede CCs; `-m` two-message thread, Mark Brown
applied, no NAK
- [Phase 4] Patchew and LKML copies of the patch and apply mail
- [Phase 4] Stable-list search did not find this subject
- [Phase 5] `dmi_check_system` call at line 1024 of
`snd_byt_rt5651_mc_probe`; platform driver `bytcr_rt5651`
- [Phase 5] HiBook analog in `touchscreen_dmi.c` lines 1197–1204 (Hampoo
+ Cherry Trail CR + BIOS date)
- [Phase 6] `git describe HEAD` v6.18.57-155-gcdf239ca885b2; `make
kernelversion` 6.18.57
- [Phase 6] `git show v6.18.57:...` has Hi8 Pro then Vi8 Plus; patch
dry-run succeeded at line 409 (offset -1)
- [Phase 6] `git log v6.18..v6.18.57 --
sound/soc/intel/boards/bytcr_rt5651.c` empty — no prior alternate fix
- [Phase 8] Failure mode from commit text + MONO_SPEAKER history: broken
speaker/HP/button, not oops
- UNVERIFIED: uniqueness of the DMI triple across all Hampoo Cherry
Trail products; lore.kernel.org HTML (403)
**YES**
sound/soc/intel/boards/bytcr_rt5651.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index ca540a66f22ce..723acb58e248e 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -409,6 +409,23 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
BYT_RT5651_HP_LR_SWAPPED |
BYT_RT5651_MONO_SPEAKER),
},
+ {
+ /* Chuwi Hi8 (CWI513) with a BIOS using generic DMI strings */
+ .callback = byt_rt5651_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+ DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+ /* Above matches are too generic, add bios-date match */
+ DMI_MATCH(DMI_BIOS_DATE, "05/21/2016"),
+ },
+ .driver_data = (void *)(BYT_RT5651_MCLK_EN |
+ BYT_RT5651_JD1_1 |
+ BYT_RT5651_OVCD_TH_2000UA |
+ BYT_RT5651_OVCD_SF_1P0 |
+ BYT_RT5651_IN2_MAP |
+ BYT_RT5651_HP_LR_SWAPPED |
+ BYT_RT5651_MONO_SPEAKER),
+ },
{
/* Chuwi Vi8 Plus (CWI519) */
.callback = byt_rt5651_quirk_cb,
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/amdgpu: Validate ATIF buffer length before use
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (52 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] ASoC: Intel: bytcr_rt5651: Add quirk for Chuwi Hi8 with generic DMI strings Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:22 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] wifi: iwlwifi: support TTL platform device ID Sasha Levin
` (462 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Lijo Lazar, Alex Deucher, Sasha Levin, christian.koenig, airlied,
simona, amd-gfx, dri-devel, linux-kernel
From: Lijo Lazar <lijo.lazar@amd.com>
[ Upstream commit b978b7d43963bbb3e2d850288f7c21ac11c3b751 ]
Add a min_size parameter to amdgpu_atif_call() to validate that the
returned ACPI buffer is of type ACPI_TYPE_BUFFER, holds at least a u16
size field, does not claim more data than was actually returned, and
meets the minimum size required by the calling function. Each caller
passes its required minimum via sizeof() or offsetof() of the expected
output struct and drops its own size check.
Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Assisted-by: Claude Sonnet (Cursor AI)
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a firmware-buffer bounds check in `amdgpu_atif_call()`. On this
6.18.53 tree the buggy path is still present, the patch is small, and it
closes a real out-of-bounds read.
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[drm/amdgpu] [Validate] Validate ATIF buffer length before use`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>` (author)
- `Assisted-by: Claude Sonnet (Cursor AI)`
- `Acked-by: Alex Deucher <alexander.deucher@amd.com>` (amdgpu
maintainer)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>`
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Cc: stable`, or syzbot
tags (absence expected)
- Upstream SHA from the candidate wrapper:
`b978b7d43963bbb3e2d850288f7c21ac11c3b751` (ignored as a selection
marker; used only to find the original discussion)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: ACPI ATIF responses are used without checking that the returned
buffer actually contains the `u16` size field, that the BIOS-reported
size does not exceed the ACPI object length, or that the payload meets
the caller’s minimum.
- Symptom/failure mode: out-of-bounds read (and possible oops) when
firmware returns a short or lying buffer, then callers `memcpy()`
using the claimed size.
- Version info: none in the message. The pattern dates to `d38ceaf99ed0`
(“drm/amdgpu: add core driver (v4)”, 2015).
- Root cause: callers trusted `*(u16 *)info->buffer.pointer` and copied
that many bytes without comparing it to `obj->buffer.length`.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: This is an explicit memory-safety fix, not cleanup. Centralizing
existing per-caller `size < N` checks is incidental; the new `actual >=
sizeof(u16)` and `actual >= claimed` tests are the real fix.
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c` (+34/−34)
- Functions: `amdgpu_atif_call`, `amdgpu_atif_verify_interface`,
`amdgpu_atif_get_notification_params`,
`amdgpu_atif_query_backlight_caps`, `amdgpu_atif_get_sbios_requests`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record (v6.18.53 before → after):
- `amdgpu_atif_call()`: after confirming `ACPI_TYPE_BUFFER`, return the
object. After: reject length `< sizeof(u16)`, claimed size `> actual`
length, or claimed size `< min_size`.
- Callers: pass `sizeof()` / `offsetof()` as `min_size` and drop their
own `size < 12/10/10/0xd` checks. `memcpy` still uses
`min(sizeof(struct), claimed_size)`, now only after those checks.
Verified struct sizes in `drivers/gpu/drm/amd/include/amd_acpi.h`
(`__packed`):
- `sizeof(atif_verify_interface)` = 12 (replaces `size < 12`)
- `offsetof(atif_system_params, command_code)` = 10 (replaces `size <
10`; the `size < 11` command_code path remains)
- `offsetof(atif_qbtc_output, data_points)` = 10 (replaces `size < 10`)
- `sizeof(atif_sbios_requests)` = 13 = `0xd` (replaces `size < 0xd`)
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: `[Memory safety / OOB] [Firmware-controlled size used as memcpy
length]`
v6.18.53 callers still do:
```
size = *(u16 *)info->buffer.pointer;
size = min(sizeof(output), size);
memcpy(&output, info->buffer.pointer, size);
```
If `obj->buffer.length` is 0 or 1, the `u16` load is already OOB. If
claimed size is 12 and actual length is 4, `memcpy` copies 12 bytes from
a 4-byte ACPI payload (heap OOB read). `c9b7c809b89f2` only checked
object type, not length; that hole is still in this tree.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct. Rejecting `claimed > actual` can disable ATIF
on a BIOS that lies about size but still returned enough bytes; that is
malformed firmware, and the fallback is “ATIF unused” rather than a
crash. Error codes change from `-EINVAL` to `-EIO` on undersized
buffers; callers only test `if (ret)` / disable the feature. Low
regression risk.
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: Size-then-memcpy logic is from `d38ceaf99ed0` (Alex Deucher,
2015, “drm/amdgpu: add core driver (v4)”). Type check added by
`c9b7c809b89f2` (2024). NULL-on-`AE_NOT_FOUND` fixed by `91c9e221fe255`
(2024). Length vs claimed size was never checked.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The bug is in original ATIF parsing, present
since 2015. Both `d38ceaf99ed0` and `c9b7c809b89f2` are ancestors of
`v6.18.53`.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `c9b7c809b89f2` “Guard against bad data for ATIF ACPI method” — real
oops in `amdgpu_atif_query_backlight_caps`; later tagged
CVE-2024-50117; already in this tree.
- `91c9e221fe255` — NULL deref if ATIF missing; already in this tree.
- Sibling `9d367fab451d9` “Validate ATPX buffer length before use” is
patch 2/2 on a different file; not a prerequisite.
- No later commits on this file after the candidate that rework the same
logic.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Lijo Lazar is a regular AMD amdgpu contributor (ATPX/ATRM/XCP
bounds checks in the same wave). Maintainer Acked-by/SOB from Alex
Deucher.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. `amdgpu_atif_call` is static with four local
callers, all updated. No new helpers. ATPX 2/2 is independent.
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c b978b7d43963...` failed (lore.kernel.org returned errors).
- Original submission: `[PATCH 1/2] drm/amdgpu: Validate ATIF buffer
length before use`, 14 Jun 2026, https://www.mail-archive.com/amd-
gfx@lists.freedesktop.org/msg145004.html
- Series: 1/2 ATIF, 2/2 ATPX. No v2 found.
- No NAKs found. Merged via Alex Deucher’s `drm-next-7.3` pull; Dave
Airlie acked the pull.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Posted to amd-gfx. Acked/signed by Alex Deucher. Recipients from
`b4 dig -w` could not be retrieved (lore 403).
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: This commit has no new user report. The related 2024 ATIF bad-
data oops (`c9b7c809b89f2`) was hit on at least one system and became
CVE-2024-50117. That earlier fix did not validate lengths.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 1/2 of ATIF+ATPX ACPI buffer validation. ATRM buffer checks in
the same author batch. ATIF is self-contained.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned 403. No verified stable-
list discussion. Prior ATIF guard *was* taken into stable
(CVE-2024-50117).
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `amdgpu_atif_call` plus the four callers listed above. No
semcode tools available.
**Step 5.2: TRACE CALLERS**
Record:
- `amdgpu_atif_verify_interface` ← `amdgpu_atif_pci_probe_handle` ←
`amdgpu_acpi_detect` ← `amdgpu_drv.c` (driver load)
- `amdgpu_atif_get_notification_params` /
`amdgpu_atif_query_backlight_caps` ← `amdgpu_acpi_detect`
- `amdgpu_atif_get_sbios_requests` ← `amdgpu_atif_handler` ← ACPI
notifier (`amdgpu_acpi_event`) on brightness/hotplug-style events
**Step 5.3: TRACE CALLEES**
Record: `acpi_evaluate_object`, then `memcpy` of firmware bytes into
stack structs.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reached on every amdgpu load when the GPU’s ACPI node has ATIF
(common on AMD laptops/APUs). SBIOS request path runs on ACPI video
notifies. Unprivileged userspace cannot call ATIF directly; a guest/VM
with a crafted ACPI table can. Firmware bugs have already crashed this
path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same claimed-size-then-memcpy pattern remains in
`amdgpu_atcs_call` callers in this file and in `radeon_acpi.c`. This
patch does not touch those; not a reason to reject the ATIF fix.
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Local tree is **6.18.53** (`v6.18.53-5049-g0f0bdc2b0dffb`,
branch `autosel`). `git merge-base --is-ancestor c8373721c3e54 v6.18.53`
is false. `v6.18.53:drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c` still has
the unvalidated `*(u16 *)` / `memcpy` sequence. Bug introduced in 2015
(`d38ceaf99ed0`).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: `git diff v6.18.53 c8373721c3e54 --
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c` is exactly this commit
(+34/−34). Mainline `noinline_for_stack` is not in 6.18; the candidate
as it exists here already matches 6.18. Clean apply.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Type/NULL guards (`c9b7c809b89f2`, `91c9e221fe255`) are in
6.18.53. Length validation is not. No alternate fix.
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `[drm/amdgpu ACPI/ATIF] [IMPORTANT]` — not core mm/net, but a
widely used GPU driver on AMD laptops.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively developed; this ATIF parsing has been stable since 2015
aside from the 2024 type/NULL guards.
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: AMD GPU systems whose ACPI provides ATIF (typical AMD
laptop/APU). Config: `CONFIG_DRM_AMDGPU`.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Driver probe always; ACPI notifies for SBIOS requests. Needs a
short or lying ATIF buffer. Unprivileged userspace cannot trigger it on
bare metal; firmware/VM ACPI can. Prior ATIF bad-data crashes were seen
in the wild.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: `[OOB read → possible oops / info leak] [HIGH]` Same class as
CVE-2024-50117, remaining hole.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: Benefit high (closes firmware OOB on a common driver). Risk low
(~30-line single-file change, fail-closed). Ratio favors backport.
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB: claimed ATIF size used as `memcpy` length without comparing
to ACPI buffer length.
- Same subsystem already produced a stable/CVE oops from unvalidated
ATIF data (`c9b7c809b89f2` / CVE-2024-50117); that patch did not check
lengths.
- Buggy code is in this 6.18.53 tree since 2015.
- Small, contained, no new API; maintainer Acked-by.
- Applies cleanly here.
- Failure is crash/OOB, not a feature change.
AGAINST:
- No dedicated report for *this* length mismatch (hardening of a known-
bad path).
- Undersized-buffer errno changes `-EINVAL` → `-EIO` (callers treat both
as failure).
- Sibling ATPX patch is separate and not required.
UNRESOLVED:
- `b4 dig` / lore.kernel.org returned errors; discussion recovered from
mail-archive.
- No stable@ thread found (lore 403).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — checks match existing
minima; maintainer merged.
2. Fixes a real bug that affects users? **PASS** — OOB on malformed
ATIF; ATIF bad data already crashed systems.
3. Important issue? **PASS** — HIGH: OOB read / oops from firmware data.
4. Small and contained? **PASS** — one file, +34/−34.
5. No new features or APIs? **PASS** — static helper only.
6. Can apply to the local tree? **PASS** — identical to `v6.18.53` file
plus this diff.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/docs exception. Ordinary memory-safety
bug fix.
**Step 9.4: MAKE YOUR DECISION**
Backport. It closes a leftover ATIF buffer-length hole on this 6.18 tree
with a small, fail-closed change.
### What the commit solves for stable users
On 6.18, `amdgpu_atif_call()` only rejects non-buffer ACPI objects.
Callers then trust a BIOS `u16` size and `memcpy` that many bytes. A
short or inflated ATIF payload over-reads kernel heap and can oops — the
same ATIF path that already oopsed in 2024. This patch requires actual
length ≥ 2, actual ≥ claimed, and claimed ≥ caller minimum before any
copy.
### Risk vs benefit
Benefit is preventing oops/OOB on AMD systems with ATIF. Risk is
disabling ATIF on lying firmware instead of crashing. That is the right
stable tradeoff.
### Concerns
ATPX 2/2 is not required. ATCS/radeon still have the old pattern; out of
scope. No extra 6.18 prerequisites.
Verification:
- [Phase 1] Tags: author SOB, Claude Assisted-by, Alex Deucher Acked-
by/SOB; no Fixes/Reported-by/syzbot
- [Phase 2] Diff: +34/−34 in `amdgpu_acpi.c`; length checks in
`amdgpu_atif_call`; callers pass sizeof/offsetof
- [Phase 2] Struct sizes: 12, offsetof 10, offsetof 10, 13 match old
magic constants
- [Phase 3] blame: size/memcpy from `d38ceaf99ed0` (2015); type check
`c9b7c809b89f2` (in 6.18.53)
- [Phase 3] `git merge-base --is-ancestor d38ceaf99ed0 v6.18.53` true;
`c9b7c809b89f2` true; this commit false
- [Phase 3] ATPX sibling `9d367fab451d9` is a different file; not a
dependency
- [Phase 4] `b4 dig` failed (lore error). Thread: mail-archive
msg145004, series 1/2. Pulled in drm-next-7.3
- [Phase 4] lore/stable 403; UNVERIFIED whether stable@ discussed this
SHA
- [Phase 5] Callers: probe via `amdgpu_acpi_detect`, ACPI notify via
`amdgpu_atif_handler`
- [Phase 6] `git describe HEAD` → `v6.18.53-5049-g0f0bdc2b0dffb`;
Makefile 6.18.53
- [Phase 6] `git diff v6.18.53 <commit> -- amdgpu_acpi.c` equals this
patch (clean apply)
- [Phase 8] Failure mode: heap OOB read / oops; severity HIGH
- UNVERIFIED: exact To/Cc list (`b4 dig -w` unavailable)
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 68 ++++++++++++------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 36f429e7f2027..5a04c20a5fd15 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -138,13 +138,15 @@ static struct amdgpu_acpi_priv {
* @atif: atif structure
* @function: the ATIF function to execute
* @params: ATIF function params
+ * @min_size: minimum size of the expected output buffer in bytes
*
* Executes the requested ATIF function (all asics).
* Returns a pointer to the acpi output buffer.
*/
static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
int function,
- struct acpi_buffer *params)
+ struct acpi_buffer *params,
+ size_t min_size)
{
acpi_status status;
union acpi_object *obj;
@@ -187,6 +189,28 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
return NULL;
}
+ if (obj->buffer.length < sizeof(u16)) {
+ DRM_DEBUG_DRIVER("ATIF buffer too small to hold size field: %u\n",
+ obj->buffer.length);
+ kfree(obj);
+ return NULL;
+ }
+
+ if (obj->buffer.length < *(u16 *)obj->buffer.pointer) {
+ DRM_DEBUG_DRIVER("ATIF buffer length mismatch: reported %u, actual %u\n",
+ *(u16 *)obj->buffer.pointer,
+ obj->buffer.length);
+ kfree(obj);
+ return NULL;
+ }
+
+ if (*(u16 *)obj->buffer.pointer < min_size) {
+ DRM_DEBUG_DRIVER("ATIF buffer too small: expected %zu, got %u\n",
+ min_size, *(u16 *)obj->buffer.pointer);
+ kfree(obj);
+ return NULL;
+ }
+
return obj;
}
@@ -248,19 +272,14 @@ static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif)
size_t size;
int err = 0;
- info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
+ info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL,
+ sizeof(output));
if (!info)
return -EIO;
memset(&output, 0, sizeof(output));
- size = *(u16 *) info->buffer.pointer;
- if (size < 12) {
- DRM_INFO("ATIF buffer is too small: %zu\n", size);
- err = -EINVAL;
- goto out;
- }
- size = min(sizeof(output), size);
+ size = min(sizeof(output), (size_t)*(u16 *)info->buffer.pointer);
memcpy(&output, info->buffer.pointer, size);
@@ -270,7 +289,6 @@ static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif)
amdgpu_atif_parse_notification(&atif->notifications, output.notification_mask);
amdgpu_atif_parse_functions(&atif->functions, output.function_bits);
-out:
kfree(info);
return err;
}
@@ -295,20 +313,14 @@ static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif)
int err = 0;
info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS,
- NULL);
+ NULL, offsetof(struct atif_system_params, command_code));
if (!info) {
err = -EIO;
goto out;
}
- size = *(u16 *) info->buffer.pointer;
- if (size < 10) {
- err = -EINVAL;
- goto out;
- }
-
memset(¶ms, 0, sizeof(params));
- size = min(sizeof(params), size);
+ size = min(sizeof(params), (size_t)*(u16 *)info->buffer.pointer);
memcpy(¶ms, info->buffer.pointer, size);
DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n",
@@ -371,20 +383,14 @@ static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
info = amdgpu_atif_call(atif,
ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS,
- ¶ms);
+ ¶ms, offsetof(struct atif_qbtc_output, data_points));
if (!info) {
err = -EIO;
goto out;
}
- size = *(u16 *) info->buffer.pointer;
- if (size < 10) {
- err = -EINVAL;
- goto out;
- }
-
memset(&characteristics, 0, sizeof(characteristics));
- size = min(sizeof(characteristics), size);
+ size = min(sizeof(characteristics), (size_t)*(u16 *)info->buffer.pointer);
memcpy(&characteristics, info->buffer.pointer, size);
atif->backlight_caps.caps_valid = true;
@@ -422,24 +428,18 @@ static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif,
int count = 0;
info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS,
- NULL);
+ NULL, sizeof(*req));
if (!info)
return -EIO;
- size = *(u16 *)info->buffer.pointer;
- if (size < 0xd) {
- count = -EINVAL;
- goto out;
- }
memset(req, 0, sizeof(*req));
- size = min(sizeof(*req), size);
+ size = min(sizeof(*req), (size_t)*(u16 *)info->buffer.pointer);
memcpy(req, info->buffer.pointer, size);
DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending);
count = hweight32(req->pending);
-out:
kfree(info);
return count;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] wifi: iwlwifi: support TTL platform device ID
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (53 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amdgpu: Validate ATIF buffer length before use Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] comedi: ni_at_a2150: Fix sanity check in interrupt handler Sasha Levin
` (461 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Miri Korenblit, Johannes Berg, Sasha Levin, linux-wireless,
linux-kernel
From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
[ Upstream commit 3bff0d12c36247073fca976498b58a940fca72dc ]
Add support for a new device ID that we will have on TTL (sc2).
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260714165826.46183446954f.Icc260831e530c1c92c9be615a7077768b1b9ae30@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The change
is a one-line PCI ID add for existing iwlwifi Sc/sc2 support. That is
the stable device-ID exception, so the rest of this write-up is the
forensic checklist behind a **YES**.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[iwlwifi / wifi] [support] [add PCI device ID for TTL (sc2)
platform]**
- Subsystem: `wifi: iwlwifi`
- Verb: **support** (hardware enablement, not a crash fix)
- Intent: bind iwlwifi to a new Intel platform PCI ID
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Reviewed-by:** Johannes Berg `<johannes.berg@intel.com>` (iwlwifi
maintainer)
- **Link:** `https://patch.msgid.link/20260714165826.46183446954f.Icc260
831e530c1c92c9be615a7077768b1b9ae30@changeid`
- **Signed-off-by:** Miri Korenblit
`<miriam.rachel.korenblit@intel.com>` (author)
- No **Fixes:** tag (expected; this is not a regression fix)
- No **Cc: stable** (expected for this review path)
- No **Reported-by**, **Tested-by**, **Acked-by**, syzbot, or bugzilla
tags
- Ignore pipeline **Signed-off-by: Sasha Levin** / **[Upstream commit
...]** (none present on the real commit `3bff0d12c36247`)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug/problem:** Driver does not claim PCI device `0x9327`, so TTL
(sc2) Wi-Fi does not bind.
- **Symptom:** iwlwifi never probes; no wireless interface on that SKU.
- **Version info:** none in the message. Author date 2026-07-14; landed
as `v7.2-rc1-199-g3bff0d12c3624`.
- **Root cause (author):** missing PCI ID in `iwl_hw_card_ids` for
hardware “we will have on TTL (sc2).” Same wording as the earlier RZL
ID commit (`6a1b633fdcd904`).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a hidden leak/race/UAF.** It is an explicit new-PCI-ID
addition. That is an allowed stable exception, not a disguised memory-
safety fix.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/net/wireless/intel/iwlwifi/pcie/drv.c` (**+1 / -0**)
- Function/data: `iwl_hw_card_ids[]` (PCI ID table)
- Scope: **single-file surgical**, one table entry
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** Sc block lists `0xE440`, `0xE340`, `0xD340`, `0x6E70`,
`0xD240` with `iwl_sc_mac_cfg`. `0x9327` does not match;
`iwl_pci_driver.id_table` does not bind.
- **After:** `{IWL_PCI_DEVICE(0x9327, PCI_ANY_ID, iwl_sc_mac_cfg)}` is
added. Probe is `iwl_pci_probe()` → `iwl_pci_gen1_2_probe()` with
existing Sc MAC config.
- Path affected: **PCI enumeration / driver bind** for that device ID
only.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Hardware workaround / device ID addition]**
- Macro expands to Intel vendor, device `0x9327`, any
subvendor/subdevice, `driver_data = iwl_sc_mac_cfg`.
- Newer iwlwifi devices are identified from HW RF/MAC registers via
`iwl_pci_find_dev_info()`; Sc IDs are not duplicated as `DEVICE(0x…)`
in `iwl_dev_info_table`. FM/WH/PE RF entries already exist. Same
pattern as `0xD240`.
- `MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids)` updates userspace modalias
matching.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Quality:** Obviously correct; identical to neighboring Sc IDs.
- **Regression risk:** Very low. Only PCI `8086:9327` is affected. Wrong
ID would only mis-bind another Intel function using that ID (Intel
assigns these IDs).
- No API, locking, or data-structure change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Line adding `0x9327`: commit **`3bff0d12c36247`** (Miri Korenblit,
2026-07-14).
- Surrounding Sc IDs: `c96a36491003d7` (2025-05-08) and `6a1b633fdcd904`
(RZL `0xD240`, 2025-06-12).
- `iwl_sc_mac_cfg` and Sc support are long-lived in this 7.3 tree, not
last-month code.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Not introduced by a buggy prior commit; the
ID was simply absent.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Related: `6a1b633fdcd904` “support RZL platform device ID” (same one-
line pattern).
- `5f88b045d959f` “pcie: add two LNL PCI IDs”.
- No later `-S 0x9327` follow-up; the ID was not corrected or reverted.
- Nearby series mates (compile-time hcmd check, FCS d3 fix, etc.) do
**not** touch this table entry.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Miri Korenblit is a regular iwlwifi author (often applying Intel
wireless patches). Johannes Berg reviewed this ID add. Same author wrote
the RZL ID add.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Needs `iwl_sc_mac_cfg` and the Sc PCI block — **present** in this tree
(`cfg/sc.c`, `iwl-config.h`, `drv.c`).
- sc2 firmware prefixes `IWL_SC2_A_FM_C_FW_PRE` /
`IWL_SC2_A_WH_A_FW_PRE` and `IWL_CFG_MAC_TYPE_SC2` are already here;
MAC type is read from CSR at runtime, not from this PCI ID.
- **Standalone:** one line; does not need the other 14 patches from the
07-14-2026 series.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 3bff0d12c36247`: **[PATCH v2 iwlwifi-next 04/15] wifi:
iwlwifi: support TTL platform device ID**
- URL: `https://patch.msgid.link/20260714165826.46183446954f.Icc260831e5
30c1c92c9be615a7077768b1b9ae30@changeid`
- `b4 dig -a`: v2 of “wifi: iwlwifi: updates - 07-14-2026”. Cover
letter: v2 was a resend so -next contained an unrelated compile fix
for a sibling patch. **This ID hunk did not change between versions.**
- Thread mbox: **16 messages, all series patches**; no NAKs, no public
review replies, no `Cc: stable` discussion on this patch.
- Cover letter: “Usual fixed, cleanups and **features** from our
internal tree.” This ID add is listed under Miri’s patches, not as a
CVE/crash fix.
- WebFetch to lore.kernel.org returned **403**; discussion recovered via
`b4 dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc **Johannes Berg**, **linux-
wireless@vger.kernel.org**. **Reviewed-by: Johannes Berg** already on
the sent patch (internal review). Right maintainer and list.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by / bugzilla / syzbot. This is vendor hardware
enablement, not a user crash report.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 15-patch **iwlwifi-next** “updates” mix (validations, recovery,
LARI v14, UHR DBE). **04/15 is independent.** Other patches are not
required for this ID to apply or work.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable WebFetch **403**. `b4` thread has **no**
stable-list discussion. **UNVERIFIED** whether anyone later nominated it
on stable@.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: No function body edited. Data: **`iwl_hw_card_ids[]`**.
Consumers: `MODULE_DEVICE_TABLE`, `iwl_pci_driver.id_table`, probe
`iwl_pci_probe()`.
**Step 5.2: TRACE CALLERS**
Record:
- `iwl_pci_register_driver()` registers `iwl_pci_driver` with `.id_table
= iwl_hw_card_ids`.
- PCI core calls `iwl_pci_probe()` on match.
- Context: process/probe, not IRQ. Common path **only if** device
`8086:9327` is present.
**Step 5.3: TRACE CALLEES**
Record: Probe enables PCI, maps BAR0, reads `CSR_HW_REV`, calls
`iwl_pci_gen1_2_probe(..., iwl_sc_mac_cfg, ...)`. Device family
`IWL_DEVICE_FAMILY_SC` is already used by other Sc IDs.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: PCI enumerates → id_table match → `iwl_pci_probe` → gen1/2
trans/op-mode → firmware via existing sc/sc2 names. **Reachable from
userspace** only by having the hardware (or VFIO/passthrough of that
ID). Not a syscall fuzz path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same one-line Sc ID adds (`0xD240` RZL). No extra
`IWL_DEV_INFO(DEVICE(0x9327))` for other Sc IDs either.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `drivers/net/wireless/intel/iwlwifi/pcie/drv.c` Sc
block and `iwl_sc_mac_cfg` exist. Without this ID, `0x9327` is
unmatched. sc2 (`IWL_CFG_MAC_TYPE_SC2` / `iwlwifi-sc2-a0-*`) already
exists. Bug/gap is “missing ID,” not missing subsystem.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply.** Neighboring lines match the candidate diff. No
refactor needed on 7.3-rc4.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No alternate TTL ID fix. `0x9327` appears only from this commit.
Prerequisite Sc/sc2 stack is already in 7.3.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **drivers/net/wireless/intel/iwlwifi** — **IMPORTANT** (very
common laptop/desktop Wi-Fi), not mm/core. Only TTL/sc2 SKUs with this
ID.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: **Active** (regular Intel iwlwifi-next dumps). ID tables are
still the supported way to enable new SKUs; this is not staging.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific / hardware-specific.** Users with Intel Wi-Fi
PCI `0x9327` (TTL/sc2). Everyone else: no behavior change.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Boot or hotplug of that device. Common **on that platform**,
never otherwise. Unprivileged users cannot trigger it without the
hardware. **UNVERIFIED** whether TTL has shipped at evaluation time;
Intel’s “we will have” language matches prior RZL ID adds.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **No oops/UAF/corruption.** Failure is **Wi-Fi never binds** on
that SKU. Severity for those users is **HIGH** (device unusable); global
severity **LOW**. Stable still takes these ID adds.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Enables existing iwlwifi/Sc/sc2 on TTL platforms that
this tree already knows how to drive.
- **Risk:** **Very low** (1 line, existing cfg pointer, isolated PCI
match).
- **Ratio:** Benefit/risk favors taking it.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Canonical **new PCI ID on an existing driver**
- 1 line, same as other Sc IDs and RZL
- `iwl_sc_mac_cfg`, sc2 firmware names, RF matching already in this tree
- Maintainer Reviewed-by (Johannes Berg)
- `MODULE_DEVICE_TABLE` so autoload works
- Standalone; no series dependency
- Zero impact on other devices
AGAINST:
- Not a crash/security/corruption fix; iwlwifi-next “features” series
- Future-tense “we will have”; shipping status unverified
- No stable@ nomination in the thread
- Mixed 15-patch series (this patch itself is still self-contained)
UNRESOLVED:
- lore.kernel.org HTTP 403 (mailbox recovered via b4)
- No stable@ thread found
- Whether TTL silicon is in users’ machines yet
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one table row, maintainer
Reviewed-by.
2. Fixes a real bug that affects users? **PASS** — missing ID means the
driver never attaches (real for that SKU).
3. Important issue (crash, security, corruption, deadlock)? **FAIL** as
crash/security; **PASS** under the documented **device-ID
exception**.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS** — no new API; only an ID on
existing probe/config.
6. Can apply to the local tree? **PASS** — Sc/sc2 and `iwl_sc_mac_cfg`
are here; hunk applies cleanly.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **NEW DEVICE ID (PCI) to an existing driver.** Driver already
exists; only `0x9327` is new. Same class as “drm/i915: Add new device ID
for Raptor Lake.”
**Step 9.4: MAKE YOUR DECISION**
This tree already has iwlwifi Sc/sc2. Adding PCI ID `0x9327` is the
standard, low-risk way to make TTL hardware work. It should be taken for
this tree.
### What it solves and why it matters here
Without the ID, PCI `8086:9327` never matches `iwl_pci_driver`, so Wi-Fi
stays down on TTL (sc2) even though this kernel already has
`iwl_sc_mac_cfg` and sc2 firmware naming. That is exactly the hardware-
enablement stable trees routinely accept.
### Stable rules
Small, correct, no new APIs, applies here. Importance is “device works,”
via the PCI-ID exception, not a KASAN-class bug.
### Risk vs benefit
Risk is a single ID match. Benefit is working wireless on that Intel
SKU. Other machines are unchanged.
### Concerns
None that block a backport here: no missing prerequisites, no extra
`IWL_DEV_INFO` needed (other Sc IDs have none), no follow-up fix to
`0x9327`. Firmware blobs remain a linux-firmware concern, not a reason
to omit the ID.
Verification:
- [Phase 1] Subject/tags: support new ID; Reviewed-by Johannes Berg;
Link msgid; no Fixes/stable/syzbot
- [Phase 1] Body: “new device ID that we will have on TTL (sc2)”
- [Phase 2] Diff: +1 line in `iwl_hw_card_ids[]` under Sc devices:
`0x9327` → `iwl_sc_mac_cfg`
- [Phase 2] `IWL_PCI_DEVICE` → Intel vendor + `MODULE_DEVICE_TABLE` +
`iwl_pci_driver.id_table`
- [Phase 2] Other Sc IDs also lack `DEVICE(0x…)` in
`iwl_dev_info_table`; FM/WH matching already present
- [Phase 3] `git describe HEAD` / Makefile: **7.3.0-rc4**
(`v7.3-rc4-27-gf0100363d8c37`)
- [Phase 3] `git blame`: `0x9327` is `3bff0d12c36247`; neighbors
`c96a36491003d7` / `6a1b633fdcd904`
- [Phase 3] `git merge-base --is-ancestor 3bff0d12c36247 HEAD` → yes;
`git describe 3bff0d12c36247` → `v7.2-rc1-199-g3bff0d12c3624`
- [Phase 3] `git log -S 0x9327 -- drv.c` → only this commit (no later
correction)
- [Phase 3] RZL analog `6a1b633fdcd904` is the same one-line pattern
- [Phase 4] `b4 dig -c/-a/-w/-m`: v2 iwlwifi-next 04/15; Johannes +
linux-wireless; no NAK; v2 resend unrelated to this hunk
- [Phase 4] Cover letter: mixed fixes/cleanups/features; this ID listed
under Miri
- [Phase 4] UNVERIFIED: lore HTTP 403; no stable@ thread retrieved
- [Phase 5] Callers: PCI probe via `iwl_pci_probe` →
`iwl_pci_gen1_2_probe`; sc2 MAC type from CSR (`iwl-drv.c`)
- [Phase 6] `iwl_sc_mac_cfg` in `cfg/sc.c`; sc2 FW prefixes present;
hunk context matches
- [Phase 6] Apply difficulty: clean
- [Phase 7] iwlwifi: important, actively maintained
- [Phase 8] Failure: no driver bind on `0x9327`; risk very low
- UNVERIFIED: whether TTL hardware is already shipping
**YES**
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 0e8481219839b..4314d95dd12af 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -548,6 +548,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0xD340, PCI_ANY_ID, iwl_sc_mac_cfg)},
{IWL_PCI_DEVICE(0x6E70, PCI_ANY_ID, iwl_sc_mac_cfg)},
{IWL_PCI_DEVICE(0xD240, PCI_ANY_ID, iwl_sc_mac_cfg)},
+ {IWL_PCI_DEVICE(0x9327, PCI_ANY_ID, iwl_sc_mac_cfg)},
#endif /* CONFIG_IWLMVM || CONFIG_IWLMLD */
{0}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] comedi: ni_at_a2150: Fix sanity check in interrupt handler
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (54 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] wifi: iwlwifi: support TTL platform device ID Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] Bluetooth: btrsi: Move set_bt_context after successful HCI registration Sasha Levin
` (460 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Ian Abbott, Greg Kroah-Hartman, Sasha Levin, hsweeten,
linux-kernel
From: Ian Abbott <abbotti@mev.co.uk>
[ Upstream commit e7356cdc7077a4f30fc5232a18e9fc6a4d404581 ]
The driver requests an interrupt handler for the device before it is
fully set up.
For safety, the interrupt handler checks the dev->attached flag to
ensure the device is fully set up, but it currently does that after
dereferencing various pointers which may be NULL if dev->attached is
false. Move the check to avoid the possible null pointer dereferences.
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://patch.msgid.link/20260618102949.26607-5-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit message forensics
**Step 1.1:** Record: `[comedi: ni_at_a2150:] [Fix] [Move the
`dev->attached` check in `a2150_interrupt()` so it runs before pointer
dereferences that can be NULL while the device is still attaching.]`
**Step 1.2:** Tags in `e7356cdc7077a`:
- `Signed-off-by: Ian Abbott <abbotti@mev.co.uk>` (author; comedi
maintainer)
- `Link:
https://patch.msgid.link/20260618102949.26607-5-abbotti@mev.co.uk`
- `Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>`
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` on the committed message (absence is expected
here)
Mailbox recipients of the original mail also included H Hartley Sweeten,
Jaeyoung Chung, and a malformed Cc that was meant to be `Reported-by:
Sangyun Kim` plus Kyungwook Boo. Those trailers were not copied onto the
git commit.
**Step 1.3:** Record:
- Bug: the ISR is registered in `a2150_alloc_irq_and_dma()` during
`a2150_attach()`, before postconfig sets `dev->attached`.
- Symptom: NULL pointer dereference in interrupt context if the handler
runs while `dev->attached` is still false.
- Version info: none in the commit body.
- Root cause: the existing `if (!dev->attached)` guard sits *after*
`dma->desc[0]`, `s->async`, `async->cmd`, and `desc->virt_addr`.
Cover letter for the 11-patch series: “Add/fix sanity check in ISA
drivers to avoid null-ptr-deref”.
**Step 1.4:** Record: Not a hidden fix. Subject and body are explicit
NULL-deref prevention.
## Phase 2: Diff analysis
**Step 2.1:** Record:
- File: `drivers/comedi/drivers/ni_at_a2150.c` (+9 / −4; 13 lines
changed)
- Function: `a2150_interrupt()`
- Scope: single-file surgical ISR change
**Step 2.2:** Record: Before, locals were initialized with dereferences,
then `dev->attached` was checked. After, `desc`/`async`/`cmd`/`buf` are
declared uninitialized, the attached check runs, then those pointers are
filled. Normal attached-and-running IRQ path is unchanged.
**Step 2.3:** Record: `[NULL pointer dereference] [ISR used `dma`,
`read_subdev`, and `async` before the attached guard; those can still be
NULL between `request_irq()` and `dev->attached = true`, and `dma` can
already have been freed on detach before `free_irq()`.]`
Verified attach/detach order in this tree:
1. `comedi_alloc_devpriv()` then `a2150_alloc_irq_and_dma()` →
`request_irq(a2150_interrupt, …)` then DMA alloc, then later
`comedi_alloc_subdevices()` / `dev->read_subdev = s`.
2. `comedi_device_attach()` only then calls
`comedi_device_postconfig()`, which sets `dev->attached = true`.
3. Detach sets `dev->attached = false` first, then `a2150_detach()`
frees DMA, then `comedi_legacy_detach()` calls `free_irq()`.
So a premature IRQ during attach hits NULL `dma` or NULL `s`/`s->async`.
An IRQ between DMA free and `free_irq()` hits a freed `dma` (UAF) in the
old code.
Loads that remain before the check (`dev->private`, `devpriv->dma`,
`dev->read_subdev`) are pointer loads, not the crashing derefs.
`private` is allocated before `request_irq()`, and it is still valid
until after `free_irq()`.
**Step 2.4:** Record: Obviously correct and minimal. Regression risk is
very low: early return already existed; only the check moved. No
API/locking/data-structure change. Residual theoretical issue: if
`attached` were true with `dma` or `read_subdev` still NULL, later
derefs would still fault — that is not the attach/detach window this
patch targets, and `dev->irq` is only kept when DMA alloc succeeded.
## Phase 3: Git history
**Step 3.1:** Record: `if (!dev->attached)` is old (Frank Mori Hess,
2009). The dangerous pre-check initializers come from `1a97f144e3d3e9`
(“staging: comedi: ni_at_a2150: remove depends on ISA_DMA_API
limitation”, H Hartley Sweeten, 2015-01-14), first contained in
`v4.0-rc1`. Present in this tree (`git merge-base --is-ancestor
1a97f144e3d3e9 HEAD`).
**Step 3.2:** Record: No `Fixes:` tag. Introduced by `1a97f144e3d3e9`
(v4.0), which is in this checkout.
**Step 3.3:** Record: This is patch 4/11 of Ian Abbott’s June 2026
series. Neighbor commits are the same class of per-driver ISR guards
(`dt2811`, `aio_iiro_16`, `das6402`, `pcl711`, etc.). Independent; no
shared helper or prerequisite refactor. No later follow-up on
`ni_at_a2150.c`.
**Step 3.4:** Record: Ian Abbott is the long-time comedi maintainer.
Greg Kroah-Hartman applied the series. Related work: `17221216ae8ce`
(“comedi: comedi_parport: deal with premature interrupt”) for the same
premature-IRQ class, with syzbot + `Cc: stable`.
**Step 3.5:** Record: No extra commits required. The ISR,
`dev->attached`, `request_irq`, and `comedi_legacy_detach()` already
exist here. Standalone.
## Phase 4: Mailing list / external research
**Step 4.1:** Record:
- `b4 dig -c e7356cdc7077a` →
https://patch.msgid.link/20260618102949.26607-5-abbotti@mev.co.uk
- `b4 dig -a`: v1 only (no v2/v3)
- Cover letter: “comedi: Add/fix sanity check in ISA drivers to avoid
null-ptr-deref”
- No NAKs in the saved thread (12 series mails, no review replies)
**Step 4.2:** Record (`b4 dig -w`): linux-kernel, Greg KH, Hartley
Sweeten, Jaeyoung Chung, Sangyun Kim, Kyungwook Boo. Maintainer-
authored, applied by Greg.
**Step 4.3:** Record: Original report retrieved with `b4 mbox` msgid
`20260610115912.780131-1-jjy600901@snu.ac.kr`:
- Subject: “comedi: KASAN null-ptr-deref in ISA driver IRQ handlers on
early IRQ”
- From Jaeyoung Chung; Reported-by Sangyun Kim and Kyungwook Boo
- Failure: handler runs before `read_subdev` is set → KASAN NULL deref /
panic
- Named drivers: das6402, ni_atmio16d, aio_iiro_16, pcmmio,
comedi_parport, pcl711
- ni_at_a2150 was not in that list; Ian added it after finding the same
`request_irq` / `read_subdev` / attached-check ordering
Related: `comedi_parport` premature IRQ was a syzbot GPF in
`comedi_get_is_subdevice_running()`.
**Step 4.4:** Record: 11 independent per-driver patches. This one does
not need the others.
**Step 4.5:** Record: UNVERIFIED — lore.kernel.org returned HTTP 403 for
`/stable/` search. No stable-list discussion confirmed.
## Phase 5: Code semantic analysis
**Step 5.1:** Record: `a2150_interrupt()` only.
**Step 5.2:** Record: Sole registration is `request_irq()` in
`a2150_alloc_irq_and_dma()`, called from `a2150_attach()`. Hardirq
context. Userspace can trigger attach/detach via comedi config
(`COMEDI_NI_AT_A2150`).
**Step 5.3:** Record: After the guard: `inw(STATUS_REG)`,
`comedi_handle_events()`, `comedi_isadma_disable()`, sample copy into
the async buffer.
**Step 5.4:** Record: Reachable from the comedi attach ioctl / config
path on ISA AT-A2150 (or a crafted I/O base/IRQ). Same class as the
KASAN/syzbot premature-IRQ bugs. Not a hot syscall path for typical
machines.
**Step 5.5:** Record: Same `if (!dev->attached)` pattern across many
`drivers/comedi/drivers/*.c` files; this series fixes the ones that
checked too late or not at all.
## Phase 6: Local tree (this checkout)
**Step 6.1:** Record:
- `make kernelversion` / Makefile: **7.3.0-rc4**
- `git describe HEAD`: `v7.3-rc4-27-gf0100363d8c37`
- File and ISR exist. Pre-fix ISR confirmed at `e7356cdc7077a^`. Bug
dates to v4.0 (`1a97f144e3d3e9`). This is mainline, not a 6.x.y stable
branch; the driver code the patch targets is present.
**Step 6.2:** Record: Clean apply on the pre-image in this history. No
extra backport rework needed for a tree that still has the old ISR.
**Step 6.3:** Record: No earlier ni_at_a2150-specific substitute.
`comedi_parport` got a related premature-IRQ fix; it does not cover this
driver.
## Phase 7: Subsystem / maintainer
**Step 7.1:** Record: `[drivers/comedi — ISA DAQ] [PERIPHERAL]`. Out of
staging (`8ffdff6a8cfbd`). Hardware is old NI AT-A2150 ISA cards
(`CONFIG_COMEDI_NI_AT_A2150`).
**Step 7.2:** Record: Mature, low churn. Ian Abbott still actively
fixing ISR attach races in 2026.
## Phase 8: Impact and risk
**Step 8.1:** Record: Driver-specific, `CONFIG_COMEDI_NI_AT_A2150`.
Small user set (legacy ISA DAQ).
**Step 8.2:** Record: Trigger is attach (IRQ registered before
`attached`/`read_subdev`) or detach (DMA freed before `free_irq()`).
Needs the device (or a spurious/pending IRQ on that line). Not a general
unprivileged remote exploit; privileged/local comedi attach is enough if
the IRQ fires. Likelihood is low, but the window is real and matches a
KASAN report for the same pattern.
**Step 8.3:** Record: `[NULL deref / possible UAF in hardirq →
oops/panic] [HIGH]` (CRITICAL for that machine; not data corruption).
**Step 8.4:** Record: Benefit HIGH for anyone using this driver (avoids
IRQ oops on attach/detach). Risk very low (13-line ISR reorder). Ratio
favors backport.
## Phase 9: Synthesis
**Evidence FOR:**
- Real NULL deref (and detach UAF) in an interrupt handler
- Same class as a KASAN report and a syzbot GPF on sibling comedi
drivers
- Author is the comedi maintainer; Greg applied v1 unchanged
- Small, obviously correct, no new API
- Bug present since v4.0; code exists in this tree
- Independent of the rest of the series
**Evidence AGAINST:**
- Niche obsolete ISA hardware
- Not in the original SNU driver list (Ian’s extra finding)
- Committed message has no `Fixes:` / `Cc: stable` (expected for this
review)
- No Tested-by on hardware in the thread
**UNRESOLVED:**
- Could not read lore.kernel.org in the browser (403); used `b4` mboxes
instead
- No confirmed stable@ discussion
- No hardware Tested-by
**Stable rules:**
1. Obviously correct and tested? **PASS** — logic is local and matches
core `attached` semantics; applied by Greg. No extra hardware Tested-
by, but the defect is visible in code.
2. Real user-visible bug? **PASS** — KASAN NULL deref / panic for this
ISR pattern.
3. Important (crash/security/corruption/deadlock)? **PASS** — hardirq
oops/panic.
4. Small and contained? **PASS** — one function, +9/−4.
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — pre-fix ISR is the historical form
of this file; no missing helpers.
**Exception category:** none (ordinary crash fix).
This is a 13-line IRQ-handler NULL-deref (and detach UAF) fix in
existing comedi code. It meets the stable rules. The local 7.3.0-rc4
tree has the driver and had the bug since v4.0.
### What it fixes for stable users
If the AT-A2150 ISR runs after `request_irq()` but before
`dev->attached` (or after DMA is freed on detach), the old handler
oopses on NULL/dangling `dma`/`read_subdev`/`async`. Moving the existing
guard first prevents that crash.
### Risk vs benefit
Benefit is avoiding a kernel oops; risk is negligible. Other patches in
the 11-patch series are not required.
---
Verification:
- [Phase 1] Parsed `e7356cdc7077a`: Ian Abbott + Greg KH; msgid
`20260618102949.26607-5`; no Fixes/Cc stable
- [Phase 1] Cover letter from mbox: series is explicitly “avoid null-
ptr-deref”
- [Phase 2] Diff: +9/−4 in `a2150_interrupt()`; moved
`desc`/`async`/`cmd`/`buf` after `if (!dev->attached)`
- [Phase 2] `a2150_attach` / `a2150_alloc_irq_and_dma` /
`comedi_device_postconfig`: `request_irq` before `attached = true`
- [Phase 2] `comedi_device_detach_locked`: `attached = false` before
`a2150_free_dma` then `free_irq`
- [Phase 3] `git blame` on pre-image: check from 2009; early derefs from
`1a97f144e3d3e9` (v4.0-rc1)
- [Phase 3] `git merge-base --is-ancestor 1a97f144e3d3e9 HEAD` and
`e7356cdc7077a HEAD`: both true
- [Phase 3] Series is 11 independent driver patches; no ni_at_a2150
follow-up
- [Phase 4] `b4 dig -c/-a/-w`: v1 only; recipients include Greg, Hartley
Sweeten, SNU reporters
- [Phase 4] `b4 mbox` of `20260610115912.780131-1-jjy600901@snu.ac.kr`:
KASAN null-ptr-deref report
- [Phase 4] Related `17221216ae8ce` comedi_parport fix: syzbot GPF + Cc
stable
- [Phase 4] lore HTTP 403; UNVERIFIED stable@ archive search
- [Phase 5] `a2150_interrupt` only used from `request_irq` in this file
- [Phase 6] Local tree 7.3.0-rc4 (`v7.3-rc4-27-gf0100363d8c37`); pre-fix
ISR confirmed at parent
- [Phase 7] `CONFIG_COMEDI_NI_AT_A2150`; peripheral ISA DAQ
- [Phase 8] Failure mode: hardirq NULL deref/UAF oops, severity HIGH;
backport risk very low
- UNVERIFIED: hardware reproduction on a real AT-A2150; stable mailing-
list mentions
**YES**
drivers/comedi/drivers/ni_at_a2150.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/comedi/drivers/ni_at_a2150.c b/drivers/comedi/drivers/ni_at_a2150.c
index e4e5a0ebd195a..93e9591f5dd4c 100644
--- a/drivers/comedi/drivers/ni_at_a2150.c
+++ b/drivers/comedi/drivers/ni_at_a2150.c
@@ -132,11 +132,11 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
struct comedi_device *dev = d;
struct a2150_private *devpriv = dev->private;
struct comedi_isadma *dma = devpriv->dma;
- struct comedi_isadma_desc *desc = &dma->desc[0];
+ struct comedi_isadma_desc *desc;
struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &async->cmd;
- unsigned short *buf = desc->virt_addr;
+ struct comedi_async *async;
+ struct comedi_cmd *cmd;
+ unsigned short *buf;
unsigned int max_points, num_points, residue, leftover;
unsigned short dpnt;
int status;
@@ -145,6 +145,11 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
if (!dev->attached)
return IRQ_HANDLED;
+ desc = &dma->desc[0];
+ async = s->async;
+ cmd = &async->cmd;
+ buf = desc->virt_addr;
+
status = inw(dev->iobase + STATUS_REG);
if ((status & INTR_BIT) == 0)
return IRQ_NONE;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] Bluetooth: btrsi: Move set_bt_context after successful HCI registration
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (55 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] comedi: ni_at_a2150: Fix sanity check in interrupt handler Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.6] fuse: zero the partial EOF page when extending a file Sasha Levin
` (459 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Chen Changcheng, Luiz Augusto von Dentz, Sasha Levin, marcel,
luiz.dentz, linux-bluetooth, linux-kernel
From: Chen Changcheng <chenchangcheng@kylinos.cn>
[ Upstream commit 290a3644609526f7ac12529cd1618042fa5a32db ]
In rsi_hci_attach(), ops->set_bt_context() stores the newly allocated
h_adapter into common->bt_adapter before hci_alloc_dev() and
hci_register_dev() are called. If either of these fails, h_adapter
is freed but common->bt_adapter remains a non-NULL dangling pointer.
This causes a deterministically reachable use-after-free when the
device operates in a BT+WiFi coexistence mode and CONFIG_RSI_COEX
is enabled. The following software-only trigger paths exist:
1. SDIO driver .remove (rsi_disconnect)
2. USB driver .disconnect (rsi_disconnect)
3. SDIO driver .shutdown (rsi_shutdown)
4. Hibernation .freeze (rsi_freeze)
All four paths check:
if (IS_ENABLED(CONFIG_RSI_COEX) && coex_mode > 1 && bt_adapter)
rsi_bt_ops.detach(bt_adapter); // use-after-free
coex_mode is set during rsi_91x_init(), before rsi_hci_attach() is
called, and is not cleared on attach failure. Since set_bt_context()
already wrote bt_adapter before the failure, the deinit paths see a
non-NULL dangling pointer and proceed to detach it.
Fix this by moving set_bt_context() after hci_register_dev() succeeds.
On failure paths bt_adapter stays NULL, and the deinit callers correctly
skip the detach call.
Signed-off-by: Chen Changcheng <chenchangcheng@kylinos.cn>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111** (`pending-6.12`). The buggy
`set_bt_context()` placement is present in `drivers/bluetooth/btrsi.c`,
and the 3-line UAF fix applies here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: [Bluetooth/btrsi] [Move] [Call `set_bt_context()` only after
`hci_register_dev()` succeeds so a failed HCI attach does not leave a
dangling `bt_adapter`.]
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Chen Changcheng \<chenchangcheng@kylinos.cn\> (author)
- Signed-off-by: Luiz Augusto von Dentz \<luiz.von.dentz@intel.com\>
(Bluetooth maintainer; applied to bluetooth-next)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
or Cc: stable (absence is expected for this review pipeline)
- Upstream object (verified in this repo’s object store, not an ancestor
of HEAD): `17abcfc57c8a0071e60a56256fbc4428957d22bb`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: `rsi_hci_attach()` stores `h_adapter` into `common->bt_adapter`
via `ops->set_bt_context()` *before* `hci_alloc_dev()` /
`hci_register_dev()`. On failure it `kfree`s `h_adapter` but leaves
`bt_adapter` non-NULL.
- Symptom: use-after-free in later detach callers that test `bt_adapter`
and call `rsi_bt_ops.detach()`.
- Named triggers: SDIO `.remove` (`rsi_disconnect`), USB `.disconnect`
(`rsi_disconnect`), SDIO `.shutdown` (`rsi_shutdown`), hibernation
`.freeze` (`rsi_freeze`).
- Root cause: `coex_mode` is set in `rsi_91x_init()` and is not cleared
on attach failure, so deinit still takes the BT detach path.
- Version info: none in the message. The buggy placement dates to the
original driver (`38aa4da504837`, v4.17-rc1).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. This is an explicit UAF fix described as such. The
verb “Move” is the mechanism, not a cleanup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/bluetooth/btrsi.c` only (+2 / −1 in the actual commit
`17abcfc57c8a`; the candidate dump showed extra surrounding context
including `kzalloc_obj`, which is **not** part of the functional
change).
- Function: `rsi_hci_attach()`.
- Scope: single-file surgical fix.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: after `kzalloc`, immediately `ops->set_bt_context(priv,
h_adapter)` (writes `common->bt_adapter`). Then `hci_alloc_dev()` /
`hci_register_dev()`. Either failure does `goto err` →
`kfree(h_adapter)` while `bt_adapter` still points at it.
- After: `set_bt_context()` runs only after `hci_register_dev()` returns
success. Failure paths leave `bt_adapter` NULL (it was never written),
so deinit skips detach.
- Path affected: HCI attach error path; success path still publishes the
adapter, just later.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: [USE-AFTER-FREE / dangling pointer] Mechanism: publish-then-free
on error. Fix: publish only after successful registration. Category (d)
memory safety + (g) error-path ordering.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: `rsi_set_bt_context()` is a straight store of
`common->bt_adapter`; delaying that store until the object is fully
live is the right lifetime rule.
- Minimal: one call moved, no API/data-structure change.
- Regression risk: low. During `hci_register_dev()`, `bt_adapter` stays
NULL so `recv_pkt` is skipped (`if (common->bt_adapter)`). HCI
callbacks use `hci_set_drvdata()`, which is set before register.
Attach is synchronous in the RX path, so by the next BT packet
`bt_adapter` is either valid or still NULL.
- Red flags: none.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Buggy `ops->set_bt_context(priv, h_adapter)` at line 120 is from
`38aa4da504837` (“Bluetooth: btrsi: add new rsi bluetooth driver”,
Prameela Rani Garnepudi, 2018-02-27). Contained in v4.17-rc1. Present in
this 6.12 tree (`git merge-base --is-ancestor 38aa4da504837 HEAD`
succeeded).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. The introducing commit is the original driver
add, confirmed by blame.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Recent `btrsi.c` history in this tree is unrelated (unaligned.h
move, HCI_AMP removal, header/comment cleanups, tx timeout). No prior
UAF/`set_bt_context` fix. Standalone; not patch X/Y.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Chen Changcheng has no other commits in this tree under
`drivers/bluetooth/`. Luiz von Dentz (who applied it) is the Bluetooth
subsystem maintainer and is active here. Author is not the RSI driver
maintainer; the patch was still taken by the Bluetooth maintainer.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: No prerequisites. `set_bt_context` / `rsi_hci_attach` /
`rsi_bt_ops.detach` all exist in this tree. `git apply --check` of
`17abcfc57c8a` succeeded (hunks at offset +10). Standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 17abcfc57c8a`: https://patch.msgid.link/20260722083136.1756
50-1-chenchangcheng@kylinos.cn
- `b4 dig -a`: single v1 series (2026-07-22); no v2/v3.
- Thread: original patch, BlueZ CI bot, patchwork-bot “applied by Luiz”.
No NAKs. No reviewer-requested respin. No explicit “Cc: stable” in the
thread.
- Applied to bluetooth-next as `17abcfc57c8a` by Luiz Augusto von Dentz
(2026-07-23).
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To Marcel Holtmann, Luiz von Dentz; Cc linux-
bluetooth, linux-kernel. Appropriate Bluetooth maintainers. Luiz applied
it (maintainer SOB). No additional human Reviewed-by in the mbox.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by, syzbot, or bugzilla. Bug is explained from code
analysis. BlueZ CI: CheckPatch/BuildKernel/CheckSparse/IncrementalBuild
PASS.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone 1-patch series. No sibling patches required.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No useful stable-list discussion of this fix was found
(lore.kernel.org search 403; web search for site:lore.kernel.org/stable
returned unrelated btrfs hits). UNVERIFIED that nobody previously
rejected it for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `rsi_hci_attach()` only. Related callees/callers used to confirm
the UAF: `rsi_set_bt_context()`, `rsi_hci_detach()`, `rsi_attach_bt()`.
**Step 5.2: TRACE CALLERS**
Record:
- `rsi_hci_attach` is `rsi_bt_ops.attach`.
- `rsi_attach_bt()` in `drivers/net/wireless/rsi/rsi_91x_main.c` calls
`rsi_bt_ops.attach()` and **only logs** on failure.
- Callers of `rsi_attach_bt()`: RX handler on `BT_CARD_READY_IND`
(`rsi_91x_main.c`), and deferred attach from mgmt FSM
(`rsi_91x_mgmt.c`).
- Detach UAF sites (all present here):
- `rsi_91x_sdio.c` remove (~1226), freeze (~1407), shutdown (~1460)
- `rsi_91x_usb.c` disconnect (~882)
- `rsi_91x_main.c` `rsi_91x_deinit()` (~411) — same pattern, not
listed in the commit message
- Context: probe/firmware-ready path and later remove/shutdown/PM. Not
IRQ-critical; reachable from device lifecycle.
**Step 5.3: TRACE CALLEES**
Record:
`kzalloc`/`hci_alloc_dev`/`hci_register_dev`/`hci_free_dev`/`kfree`;
`ops->set_bt_context` → `rsi_set_bt_context()` which assigns
`common->bt_adapter = bt_context`. `rsi_hci_detach()` does
`hci_unregister_dev`/`hci_free_dev`/`kfree` on that pointer.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Plug RSI SDIO/USB device with BT+WiFi firmware
(`CONFIG_RSI_COEX`, `coex_mode > 1`) → firmware `BT_CARD_READY_IND` →
`rsi_attach_bt()` → `rsi_hci_attach()`. If `hci_alloc_dev()` or
`hci_register_dev()` fails, `h_adapter` is freed but `bt_adapter`
remains set. Subsequent BT RX packets hit `if (common->bt_adapter)
rsi_bt_ops.recv_pkt(...)` (UAF without waiting for unplug).
Unplug/shutdown/hibernate also UAF in detach. Userspace can trigger the
lifecycle (unplug, reboot, hibernate); the attach failure itself is an
error path (OOM or HCI register failure).
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: All `rsi_bt_ops.detach(bt_adapter)` sites share the same
`bt_adapter` NULL-check. No other `set_bt_context` call sites. Same bug
class is concentrated in this one publish point.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `drivers/bluetooth/btrsi.c` lines 119–153:
```119:153:drivers/bluetooth/btrsi.c
h_adapter->priv = priv;
ops->set_bt_context(priv, h_adapter);
h_adapter->proto_ops = ops;
// ...
err = hci_register_dev(hdev);
if (err < 0) {
BT_ERR("HCI registration failed with errcode %d", err);
hci_free_dev(hdev);
goto err;
}
return 0;
err:
h_adapter->hdev = NULL;
kfree(h_adapter);
```
`rsi_set_bt_context()` assigns `common->bt_adapter`. `coex_mode` is set
in `rsi_91x_init()` (lines 347–366) and is not cleared on attach
failure. Introduced in v4.17; present in 6.12.111.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply. `git show 17abcfc57c8a -- drivers/bluetooth/btrsi.c
| git apply --check` succeeded (offset 10). This tree still uses
`kzalloc(sizeof(*h_adapter), GFP_KERNEL)` rather than mainline
`kzalloc_obj`; that line is outside the committed hunks. No conflicting
local changes.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: `git log --grep="set_bt_context"` on these files is empty.
`17abcfc57c8a` is **not** an ancestor of HEAD. No alternate fix present.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: [Bluetooth HCI driver + RSI 91x WiFi coexistence] [IMPORTANT for
RSI users, PERIPHERAL vs core kernel]. `CONFIG_RSI_COEX` is `default y`
when `RSI_91X && BT`. `BT_HCIRSI` is selected by that. Affects
Redpine/Silicon Labs RS9113-class BT+WiFi modules, not all machines.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: RSI wireless still receives real fixes in this tree (heap OOB,
beacon length, kthread lifetime, memory corruption). Bluetooth stack is
actively maintained. The UAF itself is old (2018), not a new-code issue.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific + config-specific: RSI 91x with
`CONFIG_RSI_COEX` (default y) in BT coexistence `oper_mode` (`coex_mode
> 1`).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Requires HCI attach failure (`hci_alloc_dev` OOM or
`hci_register_dev` error) after `coex_mode` is already > 1, then either
continued BT RX or remove/shutdown/freeze. Not every boot; once attach
fails, UAF is deterministic. Unprivileged users can unplug USB or
trigger shutdown; they cannot typically force `hci_register_dev` failure
except under memory pressure.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: [Use-after-free of `rsi_hci_adapter`, then
`hci_unregister_dev`/`kfree` on freed memory] [HIGH]. Crash/oops; UAF is
also a memory-safety issue. Not a guaranteed panic on every RSI boot.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: Benefit HIGH for affected hardware (prevents UAF/crash on a
reachable error path). Risk VERY LOW (3-line reorder, no locking/API
change, applies cleanly). Ratio strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real UAF: `bt_adapter` published, object freed, later detach/recv uses
it.
- Confirmed in *this* 6.12.111 tree; introducing commit is an ancestor.
- Multiple concrete deinit paths match the message; `rsi_91x_deinit()`
is another.
- Attach failure is ignored (`rsi_attach_bt` only logs), so the device
stays up with a dangling pointer.
- 3-line, obviously correct, Bluetooth maintainer applied it, BlueZ CI
passed.
- Applies cleanly here; no prerequisites.
- UAF is a standard stable-worthy class.
AGAINST:
- Niche driver (Redpine RSI), not core mm/net.
- Primary trigger is an HCI alloc/register *failure*, not the happy
path.
- No syzbot/user crash report; found by code inspection.
- No Fixes:/Cc: stable (expected; not a negative).
- No extra human Reviewed-by beyond maintainer application.
UNRESOLVED:
- No stable-list history found (lore.kernel.org 403; search noise).
- Could not walk descendants of `17abcfc57c8a` without forbidden
`--all`; no evidence of a follow-up is needed for this standalone
reorder.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — lifetime reorder; applied by
Luiz; CI PASS.
2. Fixes a real bug that affects users? **PASS** — UAF on RSI BT+WiFi
coexistence after failed HCI attach, then unplug/shutdown/hibernate
or further BT RX.
3. Important issue? **PASS** — UAF / crash (HIGH). Not a style change.
4. Small and contained? **PASS** — 3 lines, one function, one file.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — `git apply --check`
succeeded.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. It qualifies as a
normal UAF bug fix.
**Step 9.4: MAKE YOUR DECISION**
This is a small, correct UAF fix for code that has been in tree since
v4.17 and is still buggy in 6.12.111. Benefit outweighs risk.
------------------------------------------------
What the commit solves for stable users
------------------------------------------------
On RSI 91x BT+WiFi coexistence, a failed HCI attach currently leaves
`common->bt_adapter` pointing at freed memory. Later disconnect,
shutdown, freeze, deinit, or even the next BT packet will use that
pointer. Moving `set_bt_context()` until after successful
`hci_register_dev()` keeps `bt_adapter` NULL on failure so those paths
skip detach/recv.
It meets stable rules: real UAF, small, no new API, applies cleanly, low
regression risk.
------------------------------------------------
Verification
------------------------------------------------
- [Phase 1] `git describe HEAD` / `make kernelversion`:
`p-6.12-3-g710455e2077bb`, **6.12.111**, branch `pending-6.12`.
- [Phase 1] Parsed tags: author + Luiz SOBs only; no Fixes/Reported-
by/Cc: stable.
- [Phase 2] Actual upstream commit `17abcfc57c8a`: +2/−1 in
`rsi_hci_attach()`; candidate dump’s `kzalloc_obj` is surrounding
mainline context, not the fix.
- [Phase 3] `git blame drivers/bluetooth/btrsi.c` lines 109–154:
`38aa4da504837` (v4.17-rc1).
- [Phase 3] `git merge-base --is-ancestor 38aa4da504837 HEAD`: yes. `git
merge-base --is-ancestor 17abcfc57c8a HEAD`: no (fix not in this
tree).
- [Phase 3] No related `set_bt_context` history in this tree.
- [Phase 4] `b4 dig -c 17abcfc57c8a`: lore msgid
`20260722083136.175650-1-chenchangcheng@kylinos.cn`; v1 only; To
Luiz/Marcel.
- [Phase 4] Saved mbox: CI PASS; patchwork-bot applied by Luiz; no NAK.
- [Phase 4] lore.kernel.org WebFetch 403; spinics 500 — used b4 mbox
instead.
- [Phase 5] Callers verified in `rsi_91x_main.c`, `rsi_91x_mgmt.c`,
`rsi_91x_sdio.c`, `rsi_91x_usb.c`; `rsi_set_bt_context()` writes
`common->bt_adapter`.
- [Phase 6] Buggy `set_bt_context` still at line 120 of this tree’s
`btrsi.c`.
- [Phase 6] `git apply --check` of `17abcfc57c8a`: succeeded (offset
10).
- [Phase 7] `CONFIG_RSI_COEX` default y in
`drivers/net/wireless/rsi/Kconfig`.
- [Phase 8] Failure mode: UAF → oops / memory safety, severity HIGH;
trigger is attach-failure then deinit/RX.
- UNVERIFIED: later mainline follow-ups after `17abcfc57c8a` (no
`--all`); no stable-list discussion.
**YES**
drivers/bluetooth/btrsi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
index 6c1f584c8a337..0e2894e93e82e 100644
--- a/drivers/bluetooth/btrsi.c
+++ b/drivers/bluetooth/btrsi.c
@@ -117,7 +117,6 @@ static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
return -ENOMEM;
h_adapter->priv = priv;
- ops->set_bt_context(priv, h_adapter);
h_adapter->proto_ops = ops;
hdev = hci_alloc_dev();
@@ -146,6 +145,8 @@ static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
goto err;
}
+ ops->set_bt_context(priv, h_adapter);
+
return 0;
err:
h_adapter->hdev = NULL;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] fuse: zero the partial EOF page when extending a file
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (56 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] Bluetooth: btrsi: Move set_bt_context after successful HCI registration Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amdgpu: Add checks to vbios fetch through ATRM Sasha Levin
` (458 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Jimmy Zuber, Miklos Szeredi, Sasha Levin, miklos, fuse-devel,
linux-kernel
From: Jimmy Zuber <jamz@amazon.com>
[ Upstream commit 34b5c4a6e4fb9dbb3f9d87f3b0fb0372105c8302 ]
Extending a fuse file past a non-page-aligned EOF does not zero the tail of
the old last page. When that page is cached and has been mmap-dirtied beyond
the old EOF, the now in-bounds tail is served to later reads as stale data
rather than zeros, which violates POSIX file-extension semantics.
Some file systems get this zeroing automatically at writeback time
(block_write_full_folio() / iomap_writeback_handle_eof() zero the tail of the
folio straddling i_size). A non-writeback caching fuse file system uses neither
path, so it has to zero the tail itself from the size-extending paths, like
XFS (xfs_file_write_zero_eof()) and ext4 (ext4_block_zero_eof()) do.
Call truncate_pagecache_range() over the newly-exposed range up front from the
three paths that extend a file, before the new size is published:
- a buffered write whose position is past the old EOF (fuse_perform_write());
- a size-extending setattr/truncate (fuse_do_setattr());
- a size-extending fallocate (fuse_file_fallocate()).
This unmaps the stale mappings and zeroes the partial tail of the old EOF
folio, so a later read returns zeros. Truncating [old EOF, write start) before
a buffered write keeps the dropped range disjoint from the written data, so a
write that lands inside the old EOF folio is preserved.
writeback_cache connections are unaffected, as their writes go through
iomap_file_buffered_write(), which zeroes post-EOF folios. The bug is
observable on a non-writeback_cache server that returns FOPEN_KEEP_CACHE on
writable files (without FOPEN_DIRECT_IO), and is caught by the new
write_extend_eof fuse selftest.
Signed-off-by: Jimmy Zuber <jamz@amazon.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111** (`pending-6.12`). The buggy FUSE size-
extend paths are present here; the fix is not. This is a small
POSIX/data-integrity fix that belongs in this tree.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[fuse]** **[zero]** zero the partial EOF page when extending a
file. “Zero” here is a correctness fix (fill a hole that should read as
zeros), not a feature.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Jimmy Zuber \<jamz@amazon.com\> (author)
- Signed-off-by: Miklos Szeredi \<mszeredi@redhat.com\> (FUSE
maintainer; applied the patch)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Link:, or Cc:
stable (absence of Fixes/Cc: stable is expected for this pipeline)
- Ignore any “[Upstream commit …]” / Sasha Levin SOB if present —
candidate-prep only
Notable: maintainer SOB. Cover letter (v4 0/2) also names testing under
UML plus libfuse `passthrough_ll`. Recipients included Jan Kara, Joanne
Koong, Brian Foster (author of the analogous ext4/XFS EOF-zeroing work).
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Extending a FUSE file past a non-page-aligned EOF does not
zero the tail of the old last page.
- **Symptom:** If that page is cached and mmap-dirtied past the old EOF,
later reads of the newly in-bounds tail return stale bytes instead of
zeros (POSIX file-extension violation).
- **Root cause:** Writeback-style filesystems get this from
`block_write_full_folio()` / `iomap_writeback_handle_eof()`. A non-
writeback caching FUSE fs uses neither, so it must zero on extend,
like XFS/ext4.
- **Fix:** `truncate_pagecache_range()` over the newly exposed range on
write, setattr/truncate, and fallocate, before publishing the new size
(write/fallocate; setattr still publishes `i_size` first, as it
already did).
- **Scope note:** writeback_cache writes are claimed unaffected on
mainline because they go through `iomap_file_buffered_write()`.
Observable on non-writeback_cache + `FOPEN_KEEP_CACHE` without
`FOPEN_DIRECT_IO`. Caught by `write_extend_eof` selftest.
- **Version info:** none in the message. Cover letter base-commit
`7d87a5a284bb34edb3f4e7e312ef403b3385a7b7` is post-6.12.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. Explicit POSIX/data-integrity bug with a regression
test. v1 originally zeroed from `fuse_write_update_attr()` after the
fact; v3/v4 moved zeroing to the extend paths so a write inside the old
EOF folio is preserved.
---
## PHASE 2: DIFF ANALYSIS - LINE BY LINE
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `fs/fuse/dir.c`: +3 in `fuse_do_setattr()`
- `fs/fuse/file.c`: +4 in `fuse_perform_write()`, +5 in
`fuse_file_fallocate()`
- **~12 insertions, 0 deletions.** Single-subsystem surgical fix (FUSE
only). Companion selftest (series 2/2) is not part of this commit.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **`fuse_perform_write()`:** Snapshot `old_size`. If `pos > old_size`,
`truncate_pagecache_range(inode, old_size, pos-1)` before filling
pages. Hole `[old EOF, write start)` is unmapped/zeroed; the write
range itself is left intact.
- **`fuse_do_setattr()`:** On size change, if extending, range-truncate
`[oldsize, newsize-1]` then the existing `truncate_pagecache()` +
`invalidate_inode_pages2()`.
- **`fuse_file_fallocate()`:** If not `FALLOC_FL_KEEP_SIZE` and
`offset+length > oldsize`, range-truncate `[oldsize, offset+length-1]`
before `fuse_write_update_attr()` publishes the new size. Punch/zero
still has its own existing range truncate.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Logic/correctness + memory-contents (stale page-cache data).**
mmap may dirty the last page past `i_size`. Extending makes that tail
in-bounds. Without zeroing, reads return mmap garbage instead of zeros.
`truncate_pagecache_range()` unmaps full pages in the hole and
`truncate_inode_partial_folio()` / `folio_zero_range()` zeros the
partial old-EOF folio (`mm/truncate.c`).
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Minimal, matches XFS/ext4. Uses a long-standing helper. v4
dropped a custom `fuse_zero_partial_eof_folio()` after Miklos/Jan noted
`folio_mkclean()`/`folio_mark_dirty()` is a buffer-head concern;
`truncate_pagecache_range()` already zeros. Regression risk is low:
extra truncate of a hole that must read as zeros. Failed write after
hole-zeroing only clears post-EOF cache, which is still past `i_size`.
Does not add APIs or features.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- setattr size-change block: `8373200b124d03` (“fuse: Trust kernel
i_size only”, 2014) wrapping `truncate_pagecache` from
`7caef26767c172` (2013). Comment around the invalidate goes back to
Miklos 2008 (`3be5a52b30aa5c`).
- `fuse_perform_write()`: writethrough extend path since at least
`ea9b9907b82a09` (2008); `FUSE_I_SIZE_UNSTABLE` from `06a7c3c2781409`
(2013).
- fallocate extend: `bee6c307800bbb` / `b0aa7606521790` (2013).
Bug is old, long predating 6.12.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Introducing commit is “FUSE never zeroed this on
extend,” not a recent regression.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Recent 6.12 fuse work is lock leaks, DIO cache, virtiofs UAF —
unrelated. This is standalone, not a prep patch. Series 2/2 is a
selftest only.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Jimmy Zuber has no other fuse commits in this tree. Applied by
Miklos Szeredi (maintainer). Analogous ext4 fix `b6ce2dbe984bc` (“ext4:
partial zero eof block on unaligned inode size extension”) **is already
in this tree**.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Added calls are only `i_size_read()` +
`truncate_pagecache_range()`, both present. No new helpers. The mainline
hunk context mentions `fuse_folios_alloc`; this tree still uses
`fuse_pages_alloc` / `ap->pages`, so the **write hunk may need a trivial
context backport**. setattr and fallocate hunks match 6.12. Standalone:
yes.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record: Could not `b4 dig -c <sha>` (commit not in this checkout).
Retrieved thread via msgid `20260824143052.1546163-2-jamz@amazon.com`.
- Lore/LWN cover: `[PATCH v4 0/2] fuse: zero the partial EOF page when
extending a file`
- Openwall: https://lists.openwall.net/linux-kernel/2026/08/24/1447
(1/2), 1443 (2/2)
- Revisions: v1 (2026-07-31) zeroed from `fuse_write_update_attr()`
(would clobber in-page extending writes); v2/v3 moved zeroing to
extend paths; v4 dropped the helper per Miklos/Jan. Applied version is
v4.
- Miklos reply 2026-08-24: **“Applied, thanks.”** No NAK, no stable
objection.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: To: Miklos Szeredi, Shuah Khan. Cc: fuse-devel, linux-kselftest,
Jan Kara, Joanne Koong, Brian Foster. Maintainer applied v4 after
review-driven simplification.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. Author reproduced vs libfuse
`passthrough_ll` and added a selftest that fails without the fix. Same
mmap-beyond-EOF pattern as the ext4 case (`xfs_io`
pwrite/mmap/mwrite/truncate).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 2-patch series. 2/2 is `write_extend_eof_test.c` only. Kernel
fix does not depend on it. 6.12 has no
`tools/testing/selftests/filesystems/fuse/` (no need to backport the
test).
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — lore.kernel.org returned 403 (Anubis). Patch is
from Aug 2026; no evidence it was rejected for stable. Absence of Cc:
stable is not a negative signal here.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `fuse_perform_write()`, `fuse_do_setattr()`,
`fuse_file_fallocate()`. Helper used: `truncate_pagecache_range()`.
**Step 5.2: TRACE CALLERS**
Record:
- `fuse_perform_write()` ← `fuse_cache_write_iter()` (under
`inode_lock`) ← `fuse_file_write_iter()` (`.write_iter`). Userspace
`write`/`pwrite` on cached FUSE files. Direct-IO and DAX do not use
this function.
- `fuse_do_setattr()` ← `fuse_setattr()` / open `O_TRUNC` path.
Userspace `ftruncate`/`truncate`.
- `fuse_file_fallocate()` ← `.fallocate`. Userspace `fallocate()`.
**Step 5.3: TRACE CALLEES**
Record: `truncate_pagecache_range()` → optional `unmap_mapping_range()`
for full pages in the hole → `truncate_inode_pages_range()` →
`truncate_inode_partial_folio()` / `folio_zero_range()` for the partial
EOF folio. Confirmed in `mm/truncate.c` in this tree.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable from ordinary syscalls on a common FUSE mount. Default
no-open flags are `FOPEN_KEEP_CACHE` (`fs/fuse/file.c` ~line 151). Non-
writeback is the usual libfuse default. Unprivileged apps that mmap then
extend trigger it.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same class as ext4 `ext4_zero_partial_blocks()` on unaligned
extend (already in this tree) and XFS `xfs_file_write_zero_eof()`.
Remaining FUSE holes not covered here: `copy_file_range` (truncates only
the copied range), getattr-driven remote size growth in
`fuse_change_attributes()`. Incomplete coverage is not a reason to skip
the three primary paths.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.**
- `fuse_do_setattr()`: `fs/fuse/dir.c` ~2061–2065 — size change →
`truncate_pagecache` + `invalidate_inode_pages2` only (no hole zero on
extend). Dirty mmap pages can survive invalidate.
- `fuse_perform_write()`: `fs/fuse/file.c` ~1294–1305 — no
`truncate_pagecache_range`.
- `fuse_file_fallocate()`: `fs/fuse/file.c` ~3223–3230 — extend updates
`i_size` only; range truncate is punch/zero only.
Introduced years before 6.12 (2008–2014). `git log --grep="zero the
partial EOF"` on `fs/fuse/` is empty here.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Minor context only.** setattr/fallocate match. Write function
exists with the same `pos` / `FUSE_I_SIZE_UNSTABLE` shape; later in the
function 6.12 still uses pages, not folios. No semantic rework required.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This fix is not present. No earlier FUSE EOF-tail zeroing. ext4
analog is present (`b6ce2dbe984bc`).
Note: the commit’s “writeback_cache uses `iomap_file_buffered_write()`”
is mainline. **6.12 writeback still uses `generic_file_write_iter` →
`fuse_write_begin`/`fuse_write_end`.** That does not remove the
writethrough bug this patch fixes (`fuse_cache_write_iter` non-wb path
still calls `fuse_perform_write()`). setattr/fallocate changes still
apply to both modes.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **fs/fuse — IMPORTANT.** Not mm/VFS-core, but FUSE is widely
used (sshfs, fuse-overlayfs, ntfs-3g, virtiofs, container/user mounts).
Data served from the page cache is wrong.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained (Miklos). This is a long-standing hole, not
churn from a brand-new API.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **FUSE users with page cache kept and without writeback_cache**
(common). Config-specific (`CONFIG_FUSE_FS`), not a single obscure
driver.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Mid-page EOF + mmap store past EOF (legal on the last page) +
extend via `pwrite`/`ftruncate`/`fallocate`. Not every write; well-known
and reproducible (selftest + libfuse passthrough). Unprivileged if the
user can mmap/write the file.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Stale data returned as file contents / POSIX hole not zero —
HIGH (data integrity).** Not a panic. Same class stable already took for
ext4.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: **Benefit high** (wrong reads on a common FUSE config). **Risk
low** (~12 lines, existing helper, maintainer-applied, selftest). Ratio
strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
For:
- Real POSIX/data-integrity bug; selftest fails without the fix
- Small, surgical, no new API
- Buggy code present in 6.12 for years
- Same pattern as ext4, already backported here
- Maintainer applied v4 after review
- Default `FOPEN_KEEP_CACHE`; userspace-reachable
- Failed-write side effect is only clearing post-EOF cache
Against:
- Trigger needs mmap-past-EOF then extend (not every I/O)
- Does not cover `copy_file_range` / getattr size updates
- Write hunk may need a one-line context tweak (pages vs folios)
- No explicit Cc: stable (expected)
Unresolved:
- Exact mainline SHA (not in this tree; git.kernel.org blocked)
- stable@ thread (lore 403)
- Follow-ups after Miklos applied (none seen in the 4-message v4 thread)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — helper is standard; UML
selftest; maintainer applied
2. Fixes a real bug that affects users? **PASS** — stale reads vs zeros
3. Important (crash/security/corruption/deadlock)? **PASS** — data
integrity / POSIX hole semantics
4. Small and contained? **PASS** — 12 lines, two files, three call sites
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — logic applies; write hunk may
need trivial context
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-id/quirk/DT/build/docs exception. Qualifies as a
normal important bugfix.
**Step 9.4: MAKE YOUR DECISION**
Backport. The bug exists in this 6.12 tree, the fix is small and already
the form the maintainer wanted, and the user-visible failure is wrong
file data.
---
### What the commit solves for stable users
On cached, non-writeback FUSE, extending a file (write past EOF,
`ftruncate` up, `fallocate` without `KEEP_SIZE`) leaves mmap-dirtied
bytes in the old last page. Those bytes become part of the file and are
returned to `read` instead of zeros. That is a data-integrity / POSIX
violation. 6.12’s three extend paths match the buggy mainline code.
### Risk vs benefit
Benefit is preventing stale data on a common FUSE configuration. Risk is
a few `truncate_pagecache_range()` calls on a hole that must be zeros
anyway. Companion selftest is optional and this tree lacks the fuse
selftest directory.
---
### Verification
- **[Phase 1]** Tags: author Jimmy Zuber; Miklos Szeredi SOB; no
Fixes/Reported-by/Cc: stable
- **[Phase 1]** Cover letter v4: msgid
`20260824143052.1546163-1-jamz@amazon.com`; tested UML + libfuse
passthrough_ll
- **[Phase 2]** Diff: +3 dir.c setattr, +4 perform_write, +5 fallocate;
12 lines
- **[Phase 2]** `truncate_pagecache_range()` /
`truncate_inode_partial_folio()` / `folio_zero_range()` read in
`mm/truncate.c`
- **[Phase 3]** blame: setattr guard `8373200b124d03` (2014); write path
`ea9b9907b82a09` (2008); fallocate `bee6c307800bbb` (2013)
- **[Phase 3]** No Fixes: tag; `git log --grep="zero the partial EOF" --
fs/fuse/` empty in this tree
- **[Phase 3]** ext4 analog `b6ce2dbe984bc` is an ancestor of HEAD
- **[Phase 4]** `b4 mbox` msgid
`20260824143052.1546163-2-jamz@amazon.com`: 4 messages; Miklos
“Applied, thanks.”
- **[Phase 4]** v1→v4: moved zeroing off `fuse_write_update_attr`;
dropped custom helper
- **[Phase 4]** lore.kernel.org search 403 — UNVERIFIED stable@
discussion
- **[Phase 5]** Callers: `fuse_file_write_iter` →
`fuse_cache_write_iter` → `fuse_perform_write` under `inode_lock`;
setattr; `.fallocate`
- **[Phase 5]** Default `FOPEN_KEEP_CACHE` at `fs/fuse/file.c:151`
- **[Phase 6]** `git describe HEAD` → `p-6.12-3-gc504cf0baa3d8`; `make
kernelversion` → 6.12.111
- **[Phase 6]** Buggy snippets present at dir.c:2061–2065,
file.c:1294–1305, file.c:3223–3230
- **[Phase 6]** 6.12 uses `fuse_pages_alloc`, not `fuse_folios_alloc` —
minor apply context
- **[Phase 6]** 6.12 writeback_cache uses `fuse_write_begin`, not
`iomap_file_buffered_write` (commit text is mainline-specific)
- **[Phase 8]** Failure mode: stale page-cache data on read after
extend; severity HIGH
- **UNVERIFIED:** exact mainline SHA; post-apply follow-ups beyond the
v4 thread; copy_file_range/getattr as extra bugs (not used to vote NO)
**YES**
fs/fuse/dir.c | 3 +++
fs/fuse/file.c | 9 +++++++++
2 files changed, 12 insertions(+)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index a013fad843b2c..9e20bc9dbdac4 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -2095,6 +2095,9 @@ int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
*/
if ((is_truncate || !is_wb) &&
S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
+ if (outarg.attr.size > oldsize)
+ truncate_pagecache_range(inode, oldsize,
+ outarg.attr.size - 1);
truncate_pagecache(inode, outarg.attr.size);
invalidate_inode_pages2(mapping);
}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 0812eee881519..a7a3ac5b34f42 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1290,9 +1290,13 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, struct iov_iter *ii)
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
loff_t pos = iocb->ki_pos;
+ loff_t old_size = i_size_read(inode);
int err = 0;
ssize_t res = 0;
+ if (pos > old_size)
+ truncate_pagecache_range(inode, old_size, pos - 1);
+
if (inode->i_size < pos + iov_iter_count(ii))
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
@@ -2952,6 +2956,11 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
/* we could have extended the file */
if (!(mode & FALLOC_FL_KEEP_SIZE)) {
+ loff_t oldsize = i_size_read(inode);
+
+ if (offset + length > oldsize)
+ truncate_pagecache_range(inode, oldsize,
+ offset + length - 1);
if (fuse_write_update_attr(inode, offset + length, length))
file_update_time(file);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/amdgpu: Add checks to vbios fetch through ATRM
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (57 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.6] fuse: zero the partial EOF page when extending a file Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] comedi: das6402: Add sanity check to interrupt handler Sasha Levin
` (457 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Lijo Lazar, Alex Deucher, Sasha Levin, christian.koenig, airlied,
simona, amd-gfx, dri-devel, linux-kernel
From: Lijo Lazar <lijo.lazar@amd.com>
[ Upstream commit 8c3fcfc14fc1320a1155acb2dd7656fce7003bc0 ]
Check if a valid buffer object is returned after ATRM call. Also, match
the buffer length against requested size before copying.
Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This 6.18.53 tree still copies an untrusted ATRM ACPI buffer with no
type or length check, which is a real heap overflow / NULL-deref during
dGPU probe. The patch is a small, self-contained memory-safety fix and
belongs in this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [drm/amdgpu] [Add] [checks on ATRM ACPI return before copying
VBIOS data]
Subsystem prefix `drm/amdgpu`. Verb is “Add checks,” which here means
adding missing validation, not a feature.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Lijo Lazar \<lijo.lazar@amd.com\> (author)
- Reviewed-by: Alex Deucher \<alexander.deucher@amd.com\> (amdgpu
maintainer)
- Signed-off-by: Alex Deucher \<alexander.deucher@amd.com\>
- No Fixes:, Reported-by, Tested-by, Link:, or Cc: stable (absence
expected)
- Ignore pipeline-added “Upstream commit …” and “Signed-off-by: Sasha
Levin”
Notable: maintainer Reviewed-by + SOB. No fuzzer or user crash report.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: ATRM ACPI evaluation result used without checking it is a buffer,
and without capping copy size to the requested length.
- Symptom: NULL deref if `buffer.pointer` is NULL; type-confused access
if the object is not `ACPI_TYPE_BUFFER`; `memcpy` of firmware-
controlled `obj->buffer.length` into a 4 KiB slot of a 256 KiB
kmalloc, i.e. heap overflow especially on the last 4 KiB page.
- Version info: none in the message. Code dates to amdgpu core (v4.2).
- Root cause (author): ATRM can return a non-buffer or oversized buffer;
copy must be validated first.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Yes. “Add checks” is defensive language for a memory-safety bug:
missing type check + unbounded memcpy from ACPI firmware data. Same
pattern as this author’s ATIF/ATPX buffer validation commits.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c` (+8 / -2)
- Function: `amdgpu_atrm_call()`
- Scope: single-function surgical fix
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
Before: after `acpi_evaluate_object` success, `obj = buffer.pointer`
then `memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length)` and
`return obj->buffer.length`.
After: reject NULL or non-buffer objects (`kfree` + `-EINVAL`); `len =
min_t(size_t, obj->buffer.length, len)`; copy that many bytes; return
the capped length.
Path: dGPU VBIOS fetch via ATRM during probe (`amdgpu_atrm_get_bios` →
`amdgpu_get_bios_dgpu` → `amdgpu_get_bios`).
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: memory safety (NULL deref + out-of-bounds write) on an
ACPI/firmware path.
- Mechanism: `union acpi_object` is type-tagged. Using `.buffer.length`
/ `.buffer.pointer` when type is INTEGER/PACKAGE/etc. reads the wrong
union members. Even with a real buffer, firmware can return length \>
requested 4096. Destination is `adev->bios` (`kmalloc(256*1024)`),
`offset = i * 4096`. Last page (`i == 63`) overflow writes past the
allocation.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: type check is the standard ACPI pattern (ATIF
already does `obj->type != ACPI_TYPE_BUFFER`; nouveau `acpi_read_bios`
already does `min(length, obj->buffer.length)`).
- Minimal; no unrelated churn; no API change.
- Regression risk low: well-behaved ATRM still copies ≤ requested size.
Oversize/wrong-type now fails this chunk; caller already treats `ret <
ATRM_BIOS_PAGE` as end-of-data and then `check_atom_bios()`. `-EINVAL`
is `< 4096`, so the loop stops and BIOS validation fails instead of
overflowing.
- Remaining gap (not a reason to reject): no check that
`obj->buffer.pointer` is non-NULL when type is BUFFER; ACPI normally
provides one. ACPI_FAILURE path still does not `kfree` (pre-existing).
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: Unchecked `memcpy` comes from `d38ceaf99ed015` (“drm/amdgpu: add
core driver (v4)”, 2015-04-20), first in v4.2-rc1. Present for the
entire life of amdgpu, including this 6.18 tree.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Introducer is the original amdgpu core commit,
which is in this tree.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Recent `amdgpu_bios.c` work is VBIOS source selection (ROM BAR,
VFCT, shadow ROM), not ATRM copy logic. ATRM skip for removable devices
is `432e664e7c98c`. This patch is standalone, not “X/Y”. Sibling
hardening (not prerequisites): `c8373721c3e54` ATIF buffer validation,
`9d367fab451d9` ATPX buffer validation (same author, May 2026). No
follow-ups on this file after the candidate.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Lijo Lazar is a regular AMD amdgpu contributor. Same-era ACPI
object validation: ATIF and ATPX. Maintainer Alex Deucher reviewed.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None. Uses existing `acpi_evaluate_object`, `ACPI_TYPE_BUFFER`,
`min_t`, `memcpy`. `git diff v6.18.53 <candidate> -- amdgpu_bios.c` is
exactly this hunk. Applies standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 8c3fcfc14fc1320a1155acb2dd7656fce7003bc0` →
https://patch.msgid.link/20260615053911.59876-1-lijo.lazar@amd.com
- `b4 dig -a`: v1 only, 2026-06-15, no later revisions.
- Thread: patch from Lijo Lazar; Alex Deucher Reviewed-by. No NAK, no
stable nomination, no risk flags.
- lore.kernel.org WebFetch returned 403; thread recovered via `b4 dig
-m`.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc Lijo Lazar, amd-gfx@lists.freedesktop.org,
Hawking Zhang, Alexander Deucher, Asad Kamal, Candice Li. Subsystem
maintainer reviewed.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by / Link. No public crash report found. Bug is from
code inspection of untrusted ACPI length.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone v1. Related ATIF/ATPX validation patches are
independent files (`amdgpu_acpi.c`, `amdgpu_atpx_handler.c`). radeon
`radeon_atrm_call()` still has the old memcpy (separate driver; not
required for this backport).
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable WebFetch 403. `b4 dig` showed only amd-
gfx. No evidence this was rejected for stable. Absence of prior stable
discussion is not a negative.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `amdgpu_atrm_call()` only.
Step 5.2: TRACE CALLERS
Record:
- `amdgpu_atrm_call` ← `amdgpu_atrm_get_bios` (CONFIG_ACPI)
- `amdgpu_atrm_get_bios` ← `amdgpu_get_bios_dgpu`
- `amdgpu_get_bios_dgpu` ← `amdgpu_get_bios` (non-APU)
- `amdgpu_get_bios` ← `amdgpu_device.c` during COMMON IP `early_init` /
device init
Context: process context, driver probe, hybrid/PX dGPU laptops. Not IRQ.
Userspace cannot call it directly; it runs when amdgpu binds.
Step 5.3: TRACE CALLEES
Record: `acpi_evaluate_object`, `acpi_format_exception`, `memcpy`,
`kfree`, `min_t`, `DRM_ERROR`. ACPI allocates with
`ACPI_ALLOCATE_BUFFER`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Reachable on boot/module load for discrete AMD GPUs on PX
platforms with an ATRM ACPI method (on-platform only; removable devices
skipped). Failure of ATRM can make `amdgpu_get_bios()` fail and probe
return `-EINVAL` unless VBIOS is optional. Heap overflow is reachable
whenever ATRM returns a too-large buffer.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same unfixed pattern in `drivers/gpu/drm/radeon/radeon_bios.c`.
Nouveau already caps length. ATIF/ATPX in amdgpu already validate
type/length. Systematic ACPI-buffer issue; this commit fixes amdgpu ATRM
only.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Local tree is 6.18.53 (`git describe HEAD` →
`v6.18.53-5049-g0f0bdc2b0dffb`, `VERSION=6 PATCHLEVEL=18 SUBLEVEL=53`).
`v6.18.53:drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c` still has:
```
memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
```
Bug since v4.2 (`d38ceaf99ed015`).
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. Diff vs v6.18.53 is only this hunk. Surrounding
`amdgpu_atrm_call` matches the patch context.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No other ATRM copy-size fix in this tree. ATIF/ATPX validation
does not cover ATRM.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [drm/amdgpu VBIOS/ACPI] [IMPORTANT] — not mm/core, but a widely
used GPU driver; probe-time heap overflow can oops or corrupt kernel
memory.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: amdgpu is actively developed; this ATRM helper has been
unchanged since 2015 aside from log-string tweaks. Long-lived bug, not a
new-code issue.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific: discrete AMD GPUs on hybrid/PX systems with
ATRM (typical laptop mux). CONFIG_ACPI. Not APUs (`amdgpu_get_bios_apu`
does not call ATRM). Still a real, common laptop class.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Device probe when ATRM is present. Unprivileged users do not
invoke it directly; broken/malicious ACPI (buggy laptop firmware, or
attacker-controlled tables in some virt setups) can trigger overflow.
Well-behaved 4 KiB ATRM responses are unaffected.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Kernel heap out-of-bounds write and/or NULL deref oops during
GPU init. Severity HIGH (crash; potential memory corruption). Not a
guaranteed panic on every AMD system.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: HIGH for ATRM systems — prevents overflow/oops; zero behavior
change for correct firmware.
- Risk: VERY LOW — 8 lines, error-path + bounds cap, maintainer-
reviewed.
- Ratio: strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Unbounded `memcpy` from ACPI-controlled length into a fixed kmalloc
(heap OOB).
- Missing type check → type-confused union access / NULL deref.
- Present in this 6.18.y tree since amdgpu introduction (v4.2).
- Small, obviously correct, applies cleanly.
- Maintainer Reviewed-by.
- Same class as ATIF/ATPX ACPI buffer validation.
AGAINST:
- No user/syzbot report; described as “add checks.”
- Only hybrid/PX ATRM path, not all amdgpu users.
- radeon sibling left unfixed (out of scope).
UNRESOLVED:
- Could not fetch lore/stable HTML (403); mbox via b4 was sufficient.
- No public reproducer; overflow depends on ATRM returning a bad object
(verified in code, not in a crash log).
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — type check + min length;
maintainer review; caller already handles short reads.
2. Fixes a real bug that affects users? PASS — firmware-supplied length
used as memcpy size on a real probe path.
3. Important issue? PASS — heap overflow / oops, HIGH.
4. Small and contained? PASS — one function, +8/-2.
5. No new features or APIs? PASS.
6. Can apply to the local tree? PASS — identical context on v6.18.53.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID/quirk/DT/build/doc exception). Qualifies
as a normal memory-safety bug fix.
Step 9.4: MAKE YOUR DECISION
YES. This tree still has the unchecked ATRM copy. The patch is a
contained, high-value memory-safety fix with negligible regression risk.
===============================================================
What the commit solves for this tree
===============================================================
`amdgpu_atrm_call()` fetches VBIOS in 4 KiB ATRM pages into a 256 KiB
buffer. Before this change it memcpy’d `obj->buffer.length` with no
check that ACPI returned a buffer or that length ≤ 4096. Bad firmware
(wrong type or oversized buffer) can NULL-deref or smash the heap during
amdgpu probe on PX laptops. The fix rejects invalid objects and caps the
copy. That matches stable rules: real bug, important, small, no new API,
clean apply to 6.18.53.
Risk vs benefit: benefit is preventing overflow/oops; risk is a tighter
copy that only changes broken ATRM responses. No prerequisites.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed tags: author Lijo Lazar; Reviewed-by/SOB Alex
Deucher; no Fixes/Reported-by/Cc:stable.
- [Phase 2] Diff: `amdgpu_atrm_call()` +8/-2; type check + `min_t`
before memcpy.
- [Phase 2] Pre-fix at `e0d5ff3ff014b^` and at `v6.18.53`: raw memcpy of
`obj->buffer.length`.
- [Phase 2] `union acpi_object` in `include/acpi/actypes.h`: INTEGER vs
BUFFER overlay confirms type confusion.
- [Phase 2] Caller loop: `ATRM_BIOS_PAGE` 4096, `size` 256*1024; last
chunk overflow is past kmalloc.
- [Phase 3] `git blame` on parent: `d38ceaf99ed015` (2015), `git
describe --contains` → v4.2-rc1.
- [Phase 3] No Fixes: tag; introducer is in this tree.
- [Phase 3] ATIF/ATPX validation commits are sibling files, not
prerequisites.
- [Phase 3] `git log e0d5ff3ff014b..HEAD -- amdgpu_bios.c`: no follow-
ups.
- [Phase 4] `b4 dig -c 8c3fcfc14fc1…`: lore msgid
20260615053911.59876-1-lijo.lazar@amd.com.
- [Phase 4] `b4 dig -a`: v1 only.
- [Phase 4] `b4 dig -w`: amd-gfx + Deucher/Zhang/Kamal/Li.
- [Phase 4] mbox: Deucher Reviewed-by; no NAK.
- [Phase 4] WebFetch lore/stable: 403; treated as UNVERIFIED for HTML,
covered by b4 mbox.
- [Phase 5] Callers: `amdgpu_atrm_get_bios` → `amdgpu_get_bios_dgpu` →
`amdgpu_get_bios` → `amdgpu_device.c` probe.
- [Phase 5] radeon still unfixed; nouveau already mins length.
- [Phase 6] `git describe HEAD`: v6.18.53-5049-g0f0bdc2b0dffb; `make
kernelversion` 6.18.53.
- [Phase 6] `git diff v6.18.53 <candidate> -- amdgpu_bios.c`: this hunk
only → clean apply.
- [Phase 8] Failure mode: heap OOB / NULL deref on ATRM probe, HIGH.
- UNVERIFIED: live ATRM firmware that returns oversized buffers (no
crash report); stable-list HTML search (403).
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index dec312b0f3b0a..f28dec3630de5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -280,8 +280,14 @@ static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
}
obj = (union acpi_object *)buffer.pointer;
- memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
- len = obj->buffer.length;
+ if (!obj || obj->type != ACPI_TYPE_BUFFER) {
+ DRM_ERROR("ATRM returned an invalid object\n");
+ kfree(buffer.pointer);
+ return -EINVAL;
+ }
+
+ len = min_t(size_t, obj->buffer.length, len);
+ memcpy(bios+offset, obj->buffer.pointer, len);
kfree(buffer.pointer);
return len;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] comedi: das6402: Add sanity check to interrupt handler
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (58 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] drm/amdgpu: Add checks to vbios fetch through ATRM Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] ipack: ipoctal: add rwsem to guard against TOCTOU in remove path Sasha Levin
` (456 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Ian Abbott, Jaeyoung Chung, Sangyun Kim, Kyungwook Boo,
Greg Kroah-Hartman, Sasha Levin, hsweeten, linux-kernel
From: Ian Abbott <abbotti@mev.co.uk>
[ Upstream commit e90d0550c5b3056c8821f5cd714f80902de0fca6 ]
The driver requests an interrupt handler for the device, after setting
device registers to disable interrupt generation. The interrupt handler
should not be called prematurely unless the user-configured I/O port
base address and/or IRQ number are incorrect or the hardware is bad.
For safety, check the dev->attached flag in the interrupt handler to
ensure the device has been fully set up, avoiding a possible null
pointer dereference of dev->read_subdev.
Reported-by: Jaeyoung Chung <jjy600901@snu.ac.kr>
Link: https://lore.kernel.org/lkml/20260610115912.780131-1-jjy600901@snu.ac.kr/
Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
Reported-by: Kyungwook Boo <bookyungwook@gmail.com>
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://patch.msgid.link/20260618102949.26607-3-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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: **[comedi/das6402] [Add] sanity check in the IRQ handler to
avoid a NULL deref of `dev->read_subdev` before attach completes**
**Step 1.2: Tags**
Record:
- `Reported-by: Jaeyoung Chung <jjy600901@snu.ac.kr>`
- `Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>`
- `Reported-by: Kyungwook Boo <bookyungwook@gmail.com>`
- `Link: https://lore.kernel.org/lkml/20260610115912.780131-1-
jjy600901@snu.ac.kr/` (original bug report)
- `Signed-off-by: Ian Abbott <abbotti@mev.co.uk>` (author; comedi
maintainer)
- `Link:
https://patch.msgid.link/20260618102949.26607-3-abbotti@mev.co.uk`
- `Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>`
- No `Fixes:` tag (expected for this review)
- No `Cc: stable` (expected; not a negative signal)
- No `Reviewed-by` / `Tested-by` / `Acked-by`
- Three independent reporters (SNU) is a strong real-world signal
**Step 1.3: Body**
Record:
- **Bug:** IRQ handler is registered in `das6402_attach()` before
subdevices (and `dev->read_subdev`) are set up. `dev->attached` is
only set later in core postconfig.
- **Symptom:** NULL pointer dereference of `dev->read_subdev` /
`s->async` if an IRQ arrives early.
- **Trigger (author):** user-configured I/O base and/or IRQ wrong, or
bad hardware. The original report also frames it as any IRQ between
`request_irq()` and `read_subdev` assignment.
- **Root cause:** handler immediately does `s = dev->read_subdev; async
= s->async;` with no attached/NULL check.
- **Version info:** none in the message. Blame shows the deref pattern
since 2014.
**Step 1.4: Hidden bug fix?**
Record: **Not hidden.** It is an explicit NULL-deref guard. Cover
letter: “Add/fix sanity check in ISA drivers to avoid null-ptr-deref.”
Original report title: **KASAN null-ptr-deref**.
---
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/comedi/drivers/das6402.c` (+8 / −2)
- Function: `das6402_interrupt()`
- Scope: **single-file surgical fix**
**Step 2.2: Code flow**
Record: **Before:** on every IRQ, immediately dereference
`dev->read_subdev` and `s->async`. **After:** if `!dev->attached`,
return `IRQ_NONE`; only then load `async`/`cmd`. Assigning `s =
dev->read_subdev` before the check is a pointer copy, not a deref.
**Step 2.3: Bug mechanism**
Record: **[NULL pointer dereference / memory safety]** in IRQ context.
`request_irq()` runs in `das6402_attach()` before
`comedi_alloc_subdevices()` and `dev->read_subdev = s`. Core sets
`dev->attached = true` only in `comedi_device_postconfig()` after attach
returns. On a premature IRQ, `read_subdev` is still NULL → `s->async`
oops.
Detach also sets `attached = false` **before** `comedi_legacy_detach()`
→ `free_irq()`, so the same check covers the teardown window.
**Step 2.4: Fix quality**
Record: **Obviously correct** and the established comedi pattern
(`comedi_parport`, `ni_660x`, many ISA drivers). Minimal. Regression
risk is low: returning `IRQ_NONE` before attach is the intended “not
ours yet” behavior. `DAS6402_CTRL_INTE` is only set in
`das6402_ai_cmd()`, which cannot run until the device is attached, so
legitimate acquisition IRQs are unaffected.
This is patch 02/11 of a per-driver series; das6402 did not already have
a misplaced `attached` check (unlike pcl818/dt2811 “Fix sanity check”
patches). No follow-up was needed for this file.
---
## Phase 3: Git history
**Step 3.1: Blame**
Record:
- Handler exists since `48f16b6aeafdfb` (2009).
- NULL deref of `read_subdev` introduced by `d1d24cb65ee360` (“staging:
comedi: das6402: read analog input samples in interrupt handler”,
Hartley Sweeten, 2014-11-13) → **v3.19-rc1**.
- Driver rewrite: `79e5e6addbb18b` (v3.15-rc1).
- Comedi left staging: `8ffdff6a8cfbd` (around v5.13).
- Long-lived bug, not recent new code.
**Step 3.2: Fixes: tag**
Record: **None.** Introducing commit `d1d24cb65ee360` **is** an ancestor
of this tree.
**Step 3.3: File history**
Record (recent on this file):
- `e90d0550c5b30` this fix
- `2ddb4c5699129` I/O base sanity (independent; not a prerequisite)
- `70f2b28b5243d` bit-shift OOB fix
Standalone. Series is 11 independent per-driver IRQ guards.
**Step 3.4: Author**
Record: Ian Abbott is **the comedi maintainer** (118 comedi commits in
this tree). Sibling `comedi_parport` fix `17221216ae8ce` is the same
class and was explicitly `Cc: stable` + syzbot.
**Step 3.5: Dependencies**
Record: **None.** Uses existing `dev->attached` and `IRQ_NONE`. Applies
standalone.
`git merge-base --is-ancestor e90d0550c5b30 HEAD` → already in this
checkout (v7.3-rc4). That is not treated as “already selected for
stable.”
---
## Phase 4: Mailing list / external research
**Step 4.1: Original discussion**
Record:
- `b4 dig -c e90d0550c5b30` →
https://patch.msgid.link/20260618102949.26607-3-abbotti@mev.co.uk
- Series: **v1 only**, `[PATCH 02/11]`, cover `comedi: Add/fix sanity
check in ISA drivers to avoid null-ptr-deref`
- Bug report (lkml.iu.edu / lore): Jaeyoung Chung, 2026-06-10,
**“comedi: KASAN null-ptr-deref in ISA driver IRQ handlers on early
IRQ”**. Names `das6402_attach` / `das6402_interrupt` first. Failure:
kernel panic / KASAN when IRQ fires after `request_irq()` and before
`read_subdev` is set.
- Suggested fix matches this patch (guard handler or move
`request_irq`).
- Mbox: cover + 11 patches, **no NAKs, no reviewer objections**. Greg KH
applied it.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: `linux-kernel@vger.kernel.org`, Greg Kroah-Hartman, H Hartley
Sweeten, the three reporters. Comedi maintainers were on the patch.
**Step 4.3: Bug report**
Record: Static/code-path KASAN NULL deref in several ISA comedi IRQ
handlers. Three reporters. `das6402` is the exemplar. Sibling parport
case was syzbot-reproduced GPF.
**Step 4.4: Series**
Record: 11 independent driver patches. This one does not need the rest.
**Step 4.5: Stable list**
Record: lore.kernel.org/stable fetch returned 403. Unverified whether
someone already nominated it on the stable list. The related parport
patch **was** `Cc: stable`.
---
## Phase 5: Code semantic analysis
**Step 5.1: Functions**
Record: `das6402_interrupt()` only.
**Step 5.2: Callers**
Record: only `request_irq(..., das6402_interrupt, ...)` in
`das6402_attach()` (`drivers/comedi/drivers/das6402.c:579`). **Hard IRQ
context.**
**Step 5.3: Callees**
Record: `inb`, `das6402_ai_read_sample`, `comedi_buf_write_samples`,
`das6402_clear_all_interrupts`, `comedi_handle_events`. After the guard,
those only run once attached.
**Step 5.4: Reachability**
Record: Yes, from userspace: Comedi `COMEDI_DEVCONFIG` attach with I/O
base + IRQ (`it->options[0]` / `[1]`). Typically privileged.
Misconfigured port/IRQ or a spurious IRQ during attach/detach oopses the
kernel. `das6402_reset()` runs before `request_irq` and leaves
`CTRL_SOFT_TRIG` (no `DAS6402_CTRL_INTE`); device IRQs are enabled later
in `das6402_ai_cmd()`. So a **correct** board is unlikely to interrupt
early; wrong I/O/IRQ, leftover IRQ line, or teardown still can.
**Step 5.5: Similar patterns**
Record: Same `if (!dev->attached)` guard across many comedi ISA drivers.
This series adds/fixes it in 11 of them. Established, not experimental.
---
## Phase 6: Local tree
**Step 6.1: Does the buggy code exist here?**
Record:
- Tree: **`v7.3-rc4-27-gf0100363d8c37`**, `VERSION=7 PATCHLEVEL=3
SUBLEVEL=0 EXTRAVERSION=-rc4` (mainline 7.3-rc, not an LTS branch).
- File and handler exist. Pre-fix handler (parent of `e90d0550c5b30`)
dereferenced `s->async` unconditionally. Bug introduced **v3.19**
(`d1d24cb65ee360`), long before 7.3.
- Current tree already contains the fix (`e90d0550c5b30` is an ancestor
of HEAD).
**Step 6.2: Backport difficulty**
Record: **Clean apply** to any tree with this `das6402_interrupt()`
shape (stable since 2014). No structural prerequisites.
**Step 6.3: Related fixes already here**
Record: This exact fix is already in HEAD. No alternate das6402 IRQ
NULL-deref fix. `2ddb4c5699129` only restricts I/O base; it does not
close the IRQ window.
---
## Phase 7: Subsystem context
**Step 7.1**
Record: **comedi / DAS6402 ISA DAQ driver**. Criticality: **PERIPHERAL**
(legacy ISA, `CONFIG_COMEDI_DAS6402`), but the failure is a **kernel
oops in IRQ context**, not a cosmetic driver glitch. Comedi is out of
staging.
**Step 7.2**
Record: Mature driver (1999/2014). Recent activity is this class of
IRQ/I/O sanity fixes, not a rewrite.
---
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
Record: **Driver-specific / config-specific** (`CONFIG_COMEDI_DAS6402`).
Keithley/Computerboards DAS6402-12/16 and compatibles. Small population,
but a crash is still a crash for those users and for anyone attaching
with a bad IRQ/port.
**Step 8.2: Trigger**
Record: Attach with IRQ configured, then an IRQ before `attached` (bad
I/O/IRQ, spurious line, or the `attached=false`…`free_irq` detach
window). Not every boot on healthy hardware. Privileged attach, not
unprivileged syscall spray like a VFS bug; still a real oops and KASAN-
class memory-safety issue.
**Step 8.3: Failure mode**
Record: **NULL deref in hardirq → KASAN / oops / panic**. Severity:
**CRITICAL** (crash), limited blast radius (this driver).
**Step 8.4: Risk-benefit**
Record:
- **Benefit:** prevents IRQ-time oops on a real, reported path; same
pattern already used for stable on `comedi_parport`.
- **Risk:** very low (8 lines, early return, no locking/API change).
- **Ratio:** favorable.
---
## Phase 9: Synthesis
**Step 9.1: Evidence**
FOR:
- KASAN-reported NULL deref in an interrupt handler (oops/panic)
- Three reporters; das6402 is the primary example in the report
- 8-line, obviously correct guard used across comedi
- Maintainer-authored; applied by Greg KH
- Bug present since ~v3.19; no missing prerequisites in this tree
- Sibling parport fix of the same class was `Cc: stable`
AGAINST:
- Niche ISA DAQ hardware
- Healthy boards with correct I/O/IRQ are unlikely to interrupt before
`DAS6402_CTRL_INTE` is set
- No `Fixes:` / `Cc: stable` on this commit (expected; not used as a NO)
- No extra `Reviewed-by` besides maintainer + Greg
UNRESOLVED:
- Could not search lore.kernel.org/stable (403)
- No C reproducer in the SNU mail (code-path / KASAN analysis, not
syzbot)
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** (standard `dev->attached`
guard; applied upstream)
2. Real user-affecting bug? **PASS** (KASAN NULL deref / panic on early
IRQ)
3. Important (crash/security/corruption/deadlock)? **PASS** — crash in
IRQ handler
4. Small and contained? **PASS** — one function, +8/−2
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — file and handler exist; patch is
already the current code
**Step 9.3: Exception category**
Record: None needed (not a device-ID/quirk/DT/build/doc exception). It
is a straightforward crash fix.
**Step 9.4: Decision**
This tree is **Linux 7.3-rc4**. The DAS6402 IRQ handler and the
`read_subdev` deref have been in this lineage since v3.19. The change is
a small, standard NULL-deref guard for a KASAN-confirmed oops. It meets
stable criteria on technical merit. Niche hardware lowers breadth of
impact, not the fact that the failure is a kernel crash.
---
### What it solves for stable users
If `das6402` is loaded and attached with an IRQ, the handler can run
after `request_irq()` but before `dev->read_subdev` is set (and while
`dev->attached` is still false). The old handler immediately did
`s->async` and oopsed. The patch returns `IRQ_NONE` until attach is
complete.
### Risk vs benefit
Benefit is avoiding an IRQ-context oops; risk is an 8-line early return
that does not change the post-attach command path (`CTRL_INTE` only in
`das6402_ai_cmd()`).
### Concerns
No backport rework, no series dependency. Apply is clean on this
`das6402.c`.
---
Verification:
- [Phase 1] Parsed tags: 3× Reported-by (SNU), lore bug Link, Ian Abbott
+ Greg KH SOBs; no Fixes/Cc:stable
- [Phase 2] Diff: +8/−2 in `das6402_interrupt()`; defer `s->async` until
`dev->attached`
- [Phase 2] Confirmed `DAS6402_CTRL_INTE` only in `das6402_ai_cmd()`;
reset uses `CTRL_SOFT_TRIG` before `request_irq`
- [Phase 2] Confirmed detach sets `attached = false` then
`comedi_legacy_detach()` → `free_irq()`
- [Phase 3] `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`; Makefile
7.3.0-rc4
- [Phase 3] `git blame`: deref from `d1d24cb65ee360` (v3.19-rc1);
handler from 2009/2014
- [Phase 3] `git merge-base --is-ancestor d1d24cb65ee360 HEAD` →
introducing commit in this tree
- [Phase 3] `git merge-base --is-ancestor e90d0550c5b30 HEAD` → this
commit already in HEAD (ignored as “already selected”)
- [Phase 3] Pre-fix handler via `git show
e90d0550c5b30^:drivers/comedi/drivers/das6402.c` matches the candidate
diff
- [Phase 3] Ian Abbott: 118 comedi commits; sibling `17221216ae8ce` had
`Cc: stable` + syzbot
- [Phase 4] `b4 dig -c e90d0550c5b30` → msgid `20260618102949.26607-3`;
series v1 02/11
- [Phase 4] `b4 dig -a`: v1 only; `b4 dig -w`: Greg KH + Hartley Sweeten
+ reporters
- [Phase 4] Mbox: cover letter “null-ptr-deref”; no NAK/review
objections
- [Phase 4] Original report fetched from lkml.iu.edu: KASAN null-ptr-
deref, das6402 listed first
- [Phase 4] lore.kernel.org WebFetch 403; stable-list search UNVERIFIED
- [Phase 5] `das6402_interrupt` callers: only `request_irq` in
`das6402_attach`
- [Phase 6] Current `das6402.c` already has `if (!dev->attached)`; buggy
form exists at parent of this commit
- [Phase 7] `CONFIG_COMEDI_DAS6402` in `drivers/comedi/Kconfig`;
peripheral ISA driver, not staging
- [Phase 8] Failure mode: NULL deref in hardirq → oops/panic, severity
CRITICAL, population driver-specific
- UNVERIFIED: whether this SHA was discussed on stable@ (lore 403)
The fix is small, surgical, and meets all stable kernel criteria.
**YES**
drivers/comedi/drivers/das6402.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/comedi/drivers/das6402.c b/drivers/comedi/drivers/das6402.c
index 7660487e563c5..f9a778390ac93 100644
--- a/drivers/comedi/drivers/das6402.c
+++ b/drivers/comedi/drivers/das6402.c
@@ -173,10 +173,16 @@ static irqreturn_t das6402_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &async->cmd;
+ struct comedi_async *async;
+ struct comedi_cmd *cmd;
unsigned int status;
+ if (!dev->attached)
+ return IRQ_NONE;
+
+ async = s->async;
+ cmd = &async->cmd;
+
status = inb(dev->iobase + DAS6402_STATUS_REG);
if ((status & DAS6402_STATUS_INT) == 0)
return IRQ_NONE;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] ipack: ipoctal: add rwsem to guard against TOCTOU in remove path
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (59 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] comedi: das6402: Add sanity check to interrupt handler Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] serial: 8250: force synchronous probe for the ISA and PNP drivers Sasha Levin
` (455 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Pei Xiao, Greg Kroah-Hartman, Sasha Levin, vaibhavgupta40,
jens.taprogge, industrypack-devel, linux-kernel
From: Pei Xiao <xiaopei01@kylinos.cn>
[ Upstream commit 7d3a708af7f4e2af9e114d731bd60d30c1ec884e ]
The "removed" flag check in each tty op has a TOCTOU race with
__ipoctal_remove(): the device could be removed between the flag
check and the subsequent access to hardware resources (channel
registers via iowrite8, or xmit_buf in write_tty).
Close this race by introducing a read-write semaphore (remove_sem).
The tty ops acquire the read lock via guard(rwsem_read) for the
full duration of the operation, while __ipoctal_remove() acquires
the write lock via scoped_guard(rwsem_write) when setting the
removed flag. This ensures that once removed is true, no in-flight
tty op can still be accessing resources that are about to be freed
by the remove path.
Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
Link: https://patch.msgid.link/fbce75010a0f0a3a3709a5e06fd0ffd19ca0a0ed.1782870760.git.xiaopei01@kylinos.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **v7.3-rc4** (Makefile 7.3.0-rc4). The buggy `removed`
flag is present here (parent UAF fix `b6b5d64cb161a`), and this commit
closes a real TOCTOU on that flag.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[ipack/ipoctal] [add] [rwsem to close TOCTOU between `removed`
check and hardware access in the remove path]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Link:** `https://patch.msgid.link/fbce75010a0f0a3a3709a5e06fd0ffd19c
a0a0ed.1782870760.git.xiaopei01@kylinos.cn`
- **Signed-off-by:** Pei Xiao `<xiaopei01@kylinos.cn>` (author)
- **Signed-off-by:** Greg Kroah-Hartman (char-misc maintainer; applied
the patch)
- No **Fixes:**, **Reported-by:**, **Tested-by:**, **Reviewed-by:**,
**Acked-by:**, or **Cc: stable** on *this* commit (absence is
expected)
- Parent commit `b6b5d64cb161a` *does* have Reported-by: Shuangpeng Bai,
Closes: lore KASAN report, Fixes: `05e5027efc9c`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** unlocked `removed` flag check in tty ops races with
`__ipoctal_remove()`.
- **Symptom:** device can be removed between the check and `iowrite8` /
`xmit_buf` use → MMIO after iounmap (page fault) or use of a freed
transmit buffer.
- **Root cause:** check-then-use without a lock that spans both.
- **Fix:** `remove_sem` rwsem; tty ops take read lock for the whole op;
remove takes write lock while setting `removed`.
- **Version info:** none in the message. Parent UAF bug dates to the
2012 staging move; this TOCTOU exists only after the parent’s
`removed` flag.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not hidden.** Explicit race/TOCTOU fix. “Add rwsem” is the
synchronization change that closes the window.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/ipack/devices/ipoctal.c` — **+10 / −6** (16 lines)
- **Functions/data:** `struct ipoctal` (`remove_sem`);
`ipoctal_port_activate`, `ipoctal_write_tty`, `ipoctal_set_termios`,
`ipoctal_hangup`, `ipoctal_shutdown`; `ipoctal_probe` (`init_rwsem`);
`__ipoctal_remove` (`scoped_guard` around `removed = true`)
- **Scope:** single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** each listed tty op reads `ipoctal->removed` with no lock,
then touches MMIO/`xmit_buf`. Remove stores `removed = true` then
`free_irq`, `tty_port_free_xmit_buf`, `tty_port_destroy`.
- **After:** ops hold `down_read` for the whole op via
`guard(rwsem_read)`. Remove’s `down_write` waits for in-flight
readers, then sets `removed`. Later readers see `removed == true` and
skip hardware. Then remove frees resources.
- **Path:** device-remove vs concurrent tty ops (write, termios, hangup,
shutdown, port activate).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Synchronization / race — TOCTOU]** Flag check without a lock
that covers the subsequent access. Writer waits for readers, then
publishes `removed`; new readers bail out. Category (c) not involved (no
get/put change here). Complements parent kref/`removed` UAF fix.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Quality:** classic rwsem lifetime barrier; `guard`/`scoped_guard`
make unlock-on-return automatic. Write lock is only held while storing
the flag, which is enough because later readers observe `removed`.
- **Verified non-nesting:** `ipoctal_hangup` → `tty_port_hangup` →
`tty_port_shutdown` calls **`tty_port_operations.shutdown`**, which
this driver does **not** set. `tty_operations.shutdown`
(`ipoctal_shutdown`) runs from `release_tty()`, a different path. No
recursive `down_read` on the same task.
- **`tty_unregister_device`** only does `device_destroy`/`cdev_del`; it
does not take `tty_lock`. Write lock is dropped before unregister, so
hangup’s `tty_lock` → read lock vs remove’s write lock → unregister is
not a held-lock inversion.
- **Regression risk:** low. `down_read` in `write_tty` is legal (tty
write may sleep). IRQ handler does not take the rwsem; remove still
`free_irq` after publishing `removed`, which waits out in-flight IRQs.
- **Incompleteness (not a reason to reject):** `write_room` /
`chars_in_buffer` / `get_icount` still unlocked; they only touch
`channel` fields kept alive by the parent kref, not MMIO/`xmit_buf`.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- `removed` and kref: **`b6b5d64cb161a`** (Pei Xiao, 2026-07-17, “fix
UAF, null-ptr-deref, and use-after-free in cleanup on remove”).
- `remove_sem`: **this commit `7d3a708af7f4e`**.
- Driver core (`struct ipoctal`): 2012 (`ba4dc61fe8c545` staging).
- **The TOCTOU is in code added by the immediate parent**, not in
ancient unlocked MMIO.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag on this commit.** Parent `b6b5d64cb161a` has
`Fixes: 05e5027efc9c` (“Staging: ipack: move out of staging”,
2012-11-16). `git merge-base --is-ancestor` confirms `05e5027efc9c`,
`b6b5d64cb161a`, and `7d3a708af7f4e` are all ancestors of HEAD.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Direct parent of this commit **is** `b6b5d64cb161a`. Same author,
consecutive timestamps (10:01:09 / 10:01:10).
- Mailing-list subject: **`[PATCH 2/2]`**. Patch 1 is the
UAF/kref/`removed` flag; patch 2 is this rwsem.
- No later commits on this file after `7d3a708af7f4e`.
- **Standalone for this tree: yes**, because patch 1 is already here.
Not standalone on a tree that lacks `b6b5d64cb161a`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Pei Xiao is **not** the ipack maintainer; only these two ipack
commits. Greg KH applied both. Reporter Shuangpeng Bai iterated on the
series.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- **Hard dependency:** `removed`, the flag checks, `kref_init` context
in probe. All from `b6b5d64cb161a`, **present in this tree**.
- `guard(rwsem_read)` / `scoped_guard(rwsem_write)`:
`DEFINE_LOCK_GUARD_1` in `include/linux/rwsem.h` (includes
`cleanup.h`) — **present here**.
- Can apply standalone **on this tree: yes**.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig -c 7d3a708af7f4e:** matched series; lore msgid `fbce75010a0f0
a3a3709a5e06fd0ffd19ca0a0ed.1782441021.git.xiaopei01@kylinos.cn` (and
committed link with `.1782870760`).
- **b4 dig -a:** evolved RFC → PATCH → **PATCH 1/2 + 2/2**. This commit
is 2/2.
- Thread started as **`[BUG] KASAN: slab-use-after-free in
ipoctal_write_tty`** (Shuangpeng Bai, 14 Jun 2026), QEMU TPCI200/IP-
Octal, repro: open tty then `/sys/bus/pci/drivers/tpci200/unbind`.
- Incomplete earlier versions produced: NULL deref in write, page fault
in `ipoctal_set_termios` → `iowrite8`, UAF in `ipoctal_cleanup`.
- **Shuangpeng on the 1/2+2/2 series (30 Jun 2026): “I tried this patch
on my side and no bug is triggered.”**
- **No NAKs.** No reviewer asked for Cc: stable. Greg applied the
series.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: **b4 dig -w:** To/Cc were Pei Xiao, shuangpeng.kernel@gmail.com,
linux-kernel@. Not a dedicated ipack list. Greg KH (subsystem
maintainer) applied it after Pei asked him to look at
`cover.1782870760`.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record:
- KASAN slab-UAF in `ipoctal_write_tty` via `n_tty_write` /
`ksys_write`, freed from `tpci200_pci_remove` → `unbind_store`.
- Repro gist referenced in-thread. **Root-only sysfs unbind**, QEMU not
physical hardware.
- Greg (15–16 Jun 2026): unbind is a testing path; **“As it's not a real
issue for drivers like this, it's a very low priority”**, but he would
review patches. He still merged the series.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: **2-patch series.** Patch 1: kref, `carrier_owner` cache,
`removed` flag, NULL `xmit_buf` check. Patch 2 (this): rwsem around that
flag. Both in this tree. Tester signed off on the combination.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** for lore.kernel.org/stable (HTTP 403). No `Cc:
stable` in the thread mbox. No evidence of a prior stable NAK.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `ipoctal_port_activate`, `ipoctal_write_tty`,
`ipoctal_set_termios`, `ipoctal_hangup`, `ipoctal_shutdown`,
`ipoctal_probe`, `__ipoctal_remove`; field `ipoctal.remove_sem`.
**Step 5.2: TRACE CALLERS**
Record:
- `ipoctal_write_tty` ← `tty_operations.write` ← userspace `write()` on
the tty.
- `ipoctal_set_termios` ← tty ioctl (reporter: `tty_mode_ioctl`).
- `ipoctal_port_activate` ← `tty_port_operations.activate` ←
`ipoctal_open` → `tty_port_open`.
- `ipoctal_hangup` ← `tty_operations.hangup` ← `__tty_hangup`.
- `ipoctal_shutdown` ← `tty_operations.shutdown` ← `release_tty()`.
- `__ipoctal_remove` ← `ipoctal_remove` ← `ipack_driver_ops.remove`
(unbind / PCI remove / module teardown).
- **Reachable from userspace tty ops + admin device removal.**
**Step 5.3: TRACE CALLEES**
Record: `iowrite8` / `ipoctal_reset_channel`,
`ipoctal_copy_write_buffer` (`xmit_buf`), `tty_port_hangup` /
`tty_port_set_initialized`, `free_irq` via bus ops,
`tty_port_free_xmit_buf`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Open `/dev/tty*` on IP-OCTAL, keep fd, remove carrier (`unbind`,
`rmmod`, PCI remove). **Yes, userspace-reachable.** Unprivileged
write/ioctl; removal needs privileges or hotplug. Failure is kernel
oops/UAF, not just ENODEV.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same unlocked `if (ipoctal->removed)` was in all hardware-
touching tty ops from patch 1; this patch wraps all of them. No sibling
ipack device driver with the same pattern.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** HEAD is `v7.3-rc4-27-gf0100363d8c37`, version
**7.3.0-rc4**. `struct ipoctal` has `removed` from `b6b5d64cb161a` (in
7.3-rc1 char-misc merge). Without this commit, those checks are
unlocked. Bug introduced **in this 7.3 cycle** by patch 1, not after
this tree branched.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply on this tree** (same file layout,
`guard`/`scoped_guard`/`kref_init` present). Context uses `kzalloc_obj`
from a treewide change; this hunk only adds `init_rwsem` next to
`kref_init` from patch 1.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Parent UAF fix **is** here. No alternate TOCTOU fix. No later
revert or follow-up on this file.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **`drivers/ipack` (IndustryPack / GE IP-OCTAL UART).**
**PERIPHERAL.** `CONFIG_SERIAL_IPOCTAL` depends on `IPACK_BUS && TTY`,
**default n**. Used in industrial/HEP-style carrier boards (CERN/GE
history), also QEMU TPCI200.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: **Mature / low churn.** Until this 2026 series, last functional
ipoctal work was small tty API conversions and older leak/race fixes.
Not a hot new subsystem.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific / config-specific** (`CONFIG_SERIAL_IPOCTAL`).
Not universal.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Concurrent tty op and `__ipoctal_remove`. Reproduced with **root
sysfs unbind** while fd open. Same remove path as PCI remove / module
unload. Unprivileged user cannot unbind; they can issue write/ioctl on
an already-open fd. Race window is real but narrow.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Oops / KASAN UAF / MMIO page fault.** **HIGH** when it fires
(kernel crash). Not a generic unprivileged LPE path. Greg called the
underlying unbind-vs-open-fd class **low priority** for this driver.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** medium-high *if* patch 1 is present (this tree):
completes an incomplete UAF mitigation; prevents residual oops on
remove-with-open-tty.
- **Risk:** low — ~10 lines, one file, scoped guards, no API change.
- **Ratio:** favorable **on this tree**, because shipping patch 1
without patch 2 leaves a known TOCTOU.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**For backporting to this tree:**
- Real TOCTOU: check `removed` then access MMIO/`xmit_buf` while remove
frees them.
- Failure is oops/UAF (reporter already hit page fault and KASAN on
related paths).
- Small, obviously correct rwsem barrier; tester confirmed 1/2+2/2 no
longer crashes.
- Prerequisite patch 1 **is in this tree**; without this commit the 7.3
`removed` flag is racy.
- Greg KH applied it; no NAKs.
- Matches stable “race with severe outcome” guidance.
**Against:**
- Explicit **PATCH 2/2** (but dependency is already here).
- Niche `default n` IndustryPack UART.
- Trigger in the report is root sysfs unbind; Greg called that class low
priority.
- This commit has no Fixes:/Reported-by of its own (expected).
- Not a core-kernel path.
**Unresolved:**
- Stable-list search 403 (no confirmation anyone asked stable@).
- No independent reproduction of *only* the TOCTOU (series tested as a
whole).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — lock spans check+use;
Shuangpeng retested the series.
2. Fixes a real bug that affects users? **PASS** — race on this tree’s
`removed` flag; same remove-vs-open-tty path as the KASAN report.
3. Important issue? **PASS** — oops/UAF/page fault, not a style change.
Importance is limited by hardware rarity, not by bug class.
4. Small and contained? **PASS** — one file, +10/−6.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — parent, `removed`, and
`guard(rwsem_*)` all exist here.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **None** (not an ID/quirk/DT/build/doc exception). Qualifies as
a normal race/UAF-completion fix.
**Step 9.4: MAKE YOUR DECISION**
This tree is 7.3-rc4 and already contains the parent UAF fix that added
an unlocked `removed` flag. Leaving that flag without `remove_sem` re-
opens MMIO-after-unmap and freed-`xmit_buf` on remove-while-tty-open.
The patch is small, correct, and was tested as the second half of that
series. That is enough technical merit to backport it **into this
tree**.
It would be the wrong patch to take **alone** on a tree that still lacks
`b6b5d64cb161a`; that is not this tree.
---
## Detailed explanation
The parent commit keeps `struct ipoctal` alive with a kref and uses
`removed` to skip MMIO after unmap. That check is TOCTOU:
`__ipoctal_remove()` can set `removed` and free `xmit_buf`/unmap BARs
between the load of the flag and `iowrite8` / buffer use. The rwsem
makes “still using hardware” and “publish removed” exclusive. That is a
real crash class on a path the reporter already exercised.
Stable rules are met: real bug, crash severity, tiny diff, no new API,
applies here. Peripheral hardware and a root-oriented repro lower
*breadth*, not correctness. Risk is low vs the benefit of not shipping
the incomplete flag.
---
## Verification
- **[Phase 1]** Parsed tags: Link msgid, SOB Pei Xiao + Greg KH; no
Fixes/Reported-by on this commit; parent has Reported-by Shuangpeng
Bai + Fixes 05e5027efc9c
- **[Phase 2]** Diff: `drivers/ipack/devices/ipoctal.c` +10/−6; rwsem
around five tty ops + probe init + remove store
- **[Phase 2]** Confirmed `tty_port_hangup` calls port `.shutdown`, not
`tty_operations.shutdown`; ipoctal port ops have no `.shutdown`
- **[Phase 2]** `tty_unregister_device` is `device_destroy`/`cdev_del`
only
- **[Phase 3]** `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`;
`make kernelversion` → 7.3.0-rc4
- **[Phase 3]** `git merge-base --is-ancestor` b6b5d64, 7d3a708, 05e5027
→ all in HEAD
- **[Phase 3]** `git log -1 7d3a708^` → parent is exactly the
UAF/`removed` commit
- **[Phase 3]** blame: `removed` from b6b5d64; `remove_sem` from 7d3a708
- **[Phase 4]** `b4 dig -c 7d3a708af7f4e` / `-a` / `-w` / `-m`: PATCH
2/2, RFC→v2 series, recipients Pei/Shuangpeng/lkml
- **[Phase 4]** mbox: KASAN report, Greg low-priority comment,
Shuangpeng “no bug is triggered” on 1/2+2/2
- **[Phase 4]** lore.kernel.org WebFetch/curl: **403** — discussion
taken from b4 mbox instead
- **[Phase 5]** Callers traced in `ipoctal.c` + `tty_io.c` /
`tty_port.c`
- **[Phase 6]** Local file has `removed` + `remove_sem`; no later
follow-up on this file
- **[Phase 7]** Kconfig: `SERIAL_IPOCTAL` default n, depends IPACK_BUS
&& TTY
- **[Phase 8]** Failure mode: UAF/oops/PF on remove vs open tty; trigger
requires device removal
- **UNVERIFIED:** whether anyone mailed stable@ about this exact commit
(lore/stable 403)
**YES**
drivers/ipack/devices/ipoctal.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
index 474b58858dca6..aab303c4a9837 100644
--- a/drivers/ipack/devices/ipoctal.c
+++ b/drivers/ipack/devices/ipoctal.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kref.h>
+#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/serial.h>
@@ -54,6 +55,7 @@ struct ipoctal {
u8 __iomem *int_space;
struct kref kref;
struct module *carrier_owner;
+ struct rw_semaphore remove_sem;
bool removed;
};
@@ -81,7 +83,7 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
channel = dev_get_drvdata(tty->dev);
ipoctal = chan_to_ipoctal(channel, tty->index);
-
+ guard(rwsem_read)(&ipoctal->remove_sem);
if (ipoctal->removed)
return -ENODEV;
@@ -476,7 +478,7 @@ static ssize_t ipoctal_write_tty(struct tty_struct *tty, const u8 *buf,
struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
size_t char_copied;
-
+ guard(rwsem_read)(&ipoctal->remove_sem);
if (ipoctal->removed || !channel->tty_port.xmit_buf)
return 0;
@@ -522,7 +524,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
speed_t baud;
-
+ guard(rwsem_read)(&ipoctal->remove_sem);
if (ipoctal->removed)
return;
@@ -660,7 +662,7 @@ static void ipoctal_hangup(struct tty_struct *tty)
return;
ipoctal = chan_to_ipoctal(channel, tty->index);
-
+ guard(rwsem_read)(&ipoctal->remove_sem);
if (ipoctal->removed)
return;
@@ -686,7 +688,7 @@ static void ipoctal_shutdown(struct tty_struct *tty)
return;
ipoctal = chan_to_ipoctal(channel, tty->index);
-
+ guard(rwsem_read)(&ipoctal->remove_sem);
if (ipoctal->removed)
return;
@@ -736,6 +738,7 @@ static int ipoctal_probe(struct ipack_device *dev)
return -ENOMEM;
kref_init(&ipoctal->kref);
+ init_rwsem(&ipoctal->remove_sem);
ipoctal->dev = dev;
ipoctal->carrier_owner = dev->bus->owner;
@@ -755,7 +758,8 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
{
int i;
- ipoctal->removed = true;
+ scoped_guard(rwsem_write, &ipoctal->remove_sem)
+ ipoctal->removed = true;
ipoctal->dev->bus->ops->free_irq(ipoctal->dev);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] serial: 8250: force synchronous probe for the ISA and PNP drivers
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (60 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] ipack: ipoctal: add rwsem to guard against TOCTOU in remove path Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 14:10 ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] wifi: rtlwifi: fix disabling of ASPM for RTL8723BE with AER flooding Sasha Levin
` (454 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Rahul Bukte, Greg Kroah-Hartman, Sasha Levin, jirislaby,
linux-kernel, linux-serial
From: Rahul Bukte <rahul.bukte@sony.com>
[ Upstream commit 31e11af34e2c7cc61e25533ab877b1f9cc3eb528 ]
On x86_64 defconfig, booting with driver_async_probe=serial hangs in early
init. The 8250 PNP driver is put onto the async probe pool.
serial8250_register_8250_port() runs in a kworker concurrently with the
ISA registration done from the serial8250_init() initcall resulting in a
deadlock or NULL dereference.
- Deadlock: serial_core_register_port() holds port_mutex across
serial_core_add_one_port()
uart_configure_port()
autoconfig_irq()
probe_irq_on()
async_synchronize_full(),
which waits for the async probe pool to drain.
The async PNP worker reaches the "port already in use" check and
tries to unregister it.
serial8250_register_8250_port()
uart_remove_one_port()
serial_core_unregister_port()
This blocks on port_mutex.
The init thread waits for the worker and the worker waits for the
init thread.
- NULL deref: when the worker instead observes a slot whose port.dev
is set but whose port_dev has not yet been populated, it hits the
null pointer on the call to serial_core_get_ctrl_dev() in
serial_core_unregister_port().
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Link: https://patch.msgid.link/20260610054130.2825182-1-rahul.bukte@sony.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **v7.3-rc4**. The two-line `PROBE_FORCE_SYNCHRONOUS`
change is a real deadlock/NULL-deref fix on the 8250 ISA vs PNP probe
path, and the affected code is present here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[serial/8250] [force] force synchronous probe for the ISA and
PNP drivers`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>` (author)
- `Link: https://patch.msgid.link/20260610054130.2825182-1-
rahul.bukte@sony.com`
- `Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>` (tty
maintainer applied it)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence of Fixes/Cc-stable is expected for this
review)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** On x86_64 defconfig, `driver_async_probe=serial` hangs in
early init. The 8250 PNP driver (`name = "serial"`) is queued for
async probe while `serial8250_init()` still registers ISA ports.
- **Symptom/failure mode:**
1. **Deadlock:** ISA `serial_core_register_port()` holds `port_mutex`
through `autoconfig_irq()` → `probe_irq_on()` →
`async_synchronize_full()`. The async PNP worker hits the in-use
port path and blocks in `serial_core_unregister_port()` on the same
mutex.
2. **NULL deref:** The worker sees `port.dev` set but `port_dev` still
NULL, then `serial_core_get_ctrl_dev(port_dev)` oopses.
- **Version information:** None beyond “x86_64 defconfig”.
- **Root cause:** Concurrent ISA initcall registration vs async PNP
probe of the same 8250 port slots.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. It is an explicit deadlock/oops fix.
The in-thread note “Found while experimenting with
`driver_async_probe=*` to improve boot time” only explains how it was
found, not that it is theoretical.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `drivers/tty/serial/8250/8250_platform.c`: +1
(`serial8250_isa_driver.driver.probe_type`)
- `drivers/tty/serial/8250/8250_pnp.c`: +1
(`serial_pnp_driver.driver.probe_type`)
- Two insertions total. Surgical, two-file, same subsystem.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** Both drivers use default `PROBE_DEFAULT_STRATEGY`.
`driver_allows_async_probing()` then honors `driver_async_probe=` /
module async-probe, so PNP probe can run in a kworker while
`serial8250_init()` is still in the initcall.
- **After:** `PROBE_FORCE_SYNCHRONOUS` makes
`driver_allows_async_probing()` return false, so probe stays on the
registration thread and cannot overlap ISA `uart_add_one_port()`.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** Race → deadlock and NULL dereference.
- **Mechanism verified in this tree:**
- `serial8250_init()` calls `serial8250_pnp_init()` then later
`serial8250_register_ports()` which sets `up->port.dev` and calls
`uart_add_one_port()`.
- `serial_core_register_port()` holds `port_mutex` across
`serial_core_add_one_port()` → `uart_configure_port()` →
`config_port()`. With `UPF_AUTO_IRQ` (x86 `STD_COM*_FLAGS` when
`CONFIG_SERIAL_8250_DETECT_IRQ`), that reaches `autoconfig_irq()` →
`probe_irq_on()` → `async_synchronize_full()`.
- Concurrent PNP: `serial_pnp_probe()` →
`serial8250_register_8250_port()`. If `uart->port.dev` is already
set: `uart_remove_one_port()` → `serial_core_unregister_port()`.
- `serial_core_unregister_port()` reads `port->port_dev` and calls
`serial_core_get_ctrl_dev(port_dev)` **before** taking `port_mutex`.
NULL `port_dev` is an oops. Non-NULL `port_dev` waits on
`port_mutex` while the init thread waits for async probe → deadlock.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: `PROBE_FORCE_SYNCHRONOUS` exists specifically so
drivers that cannot tolerate async probe stay synchronous, including
against `driver_async_probe=`. Same pattern as i8042 PNP.
- Minimal: two field initializers, no API/behavior change for the
default (already synchronous) boot path.
- Regression risk is very low. The only cost is that these two drivers
cannot be async-probed, which is the intended workaround.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- ISA `platform_driver` struct: `ffd8e8bd26e94` (“serial: 8250: Extract
platform driver”, 2024).
- PNP `pnp_driver` struct: original tree (`1da177e4c3f41`, 2005).
- The race is not in newly added probe_type lines; those are the fix.
The overlapping register/unregister design is long-standing. The NULL
deref specifically needs `port_dev` / `serial_core_get_ctrl_dev()`,
introduced by `84a9582fd2030` (“serial: core: Start managing serial
controllers to enable runtime PM”, in v6.5-rc1).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Not applicable. The deadlock ingredients
(`probe_irq_on()` → `async_synchronize_full()` in `22a9d645677fe`;
`driver_async_probe=` in `1ea61b68d0f86`) and the serial-core `port_dev`
path are all in this tree.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Recent 8250_platform/pnp work is refactoring, not a hidden
prerequisite series.
- This is standalone (not `patch X/Y`).
- Follow-up on these files after this commit is only `4f643bef0984b`
(named initializers in the PNP ID table), unrelated.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Rahul Bukte is not a serial maintainer. This is their only
serial commit here; other listed commits are i915 NULL checks. Weight
comes from Greg Kroah-Hartman applying it to tty, not from author
tenure.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. It only needs `struct device_driver.probe_type` and
`PROBE_FORCE_SYNCHRONOUS`, both present in
`include/linux/device/driver.h` and `drivers/base/dd.c` in this tree.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 31e11af34e2c7`:
https://patch.msgid.link/20260610054130.2825182-1-rahul.bukte@sony.com
- `b4 dig -a`: **v1 only**, no later revisions.
- Saved mbox (`b4 dig -m`) is the original patch only; **no review
replies, NAKs, or Cc: stable comments**.
- Extra note in the mail (not in the committed message): “Found while
experimenting with `driver_async_probe=*` … Tested on x86_64 defconfig
under QEMU + KVM with `driver_async_probe=serial`.”
- lore.kernel.org HTTP fetch returned 403; LKML mirror matches the same
v1 text.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc included Greg Kroah-Hartman, Jiri Slaby,
Ilpo Järvinen, linux-serial, linux-kernel. No `Reviewed-by` landed. Greg
applied it (tty maintainer SOB).
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. Author reproduced a boot hang on x86_64
defconfig + QEMU. That is a concrete trigger, not a static guess.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone. Historical analogue: i8042 PNP
`PROBE_FORCE_SYNCHRONOUS` (same driver-core annotation for probes that
cannot run async). A 2018 attempt to mark 8250
`PROBE_PREFER_ASYNCHRONOUS` shows async 8250 probe has been known to be
delicate.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: `https://lore.kernel.org/stable/?q=...` returned 403. Web search
found no stable-thread discussion. **UNVERIFIED:** whether anyone
already asked for or rejected this on stable@.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: No function bodies changed. Annotations on
`serial8250_isa_driver` and `serial_pnp_driver`. Runtime effect is
through `driver_allows_async_probing()` → probe of `serial8250_probe` /
`serial_pnp_probe`.
**Step 5.2: TRACE CALLERS**
Record:
- `serial_pnp_probe`: PNP match during `pnp_register_driver()` from
`serial8250_pnp_init()` inside `serial8250_init()` (module_init /
boot).
- ISA path: `serial8250_register_ports()` from the same initcall;
platform `serial8250_probe` from
`platform_driver_register(&serial8250_isa_driver)`.
- Context: boot initcall, not a syscall hot path. Reachable on any x86
box with 8250 + PNP (ACPI selects `PNP`; `SERIAL_8250_PNP` defaults to
y).
**Step 5.3: TRACE CALLEES**
Record: `serial_pnp_probe` → `serial8250_register_8250_port` → possible
`uart_remove_one_port` → `serial_core_unregister_port`. ISA:
`uart_add_one_port` → `serial_core_register_port` →
`uart_configure_port` → `autoconfig_irq` → `probe_irq_on` →
`async_synchronize_full`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Triggered by the documented kernel parameter
`driver_async_probe=serial` or `=*`, not by an unprivileged syscall.
Still a real boot-time path: x86_64 defconfig sets
`CONFIG_SERIAL_8250=y`, `CONFIG_SERIAL_8250_CONSOLE=y`,
`CONFIG_SERIAL_8250_DETECT_IRQ=y`. Userspace cannot hit it after boot
unless the driver is re-probed.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Many drivers already set `PROBE_FORCE_SYNCHRONOUS` (i8042 PNP,
USB gadget UDC, PHY, Hyper-V, CXL, regulators, etc.). This is the
established way to opt a driver out of async probe.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- `git describe HEAD`: `v7.3-rc4-27-gf0100363d8c37`
- `make kernelversion` / Makefile: **7.3.0-rc4**
- Both files and both driver structs exist.
`serial_core_unregister_port()` still dereferences `port_dev` before
`port_mutex`. `serial8250_register_ports()` still sets `port.dev` then
calls `uart_add_one_port()`. `probe_irq_on()` still calls
`async_synchronize_full()`. `x86_64_defconfig` still enables
`SERIAL_8250_DETECT_IRQ`.
- NULL-deref window exists since serial-core `port_dev` (v6.5). Deadlock
window with `driver_async_probe` exists since that cmdline was added
(2019) on kernels with IRQ autodetect.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply in this tree. `8250_platform.c` exists here (split
in `ffd8e8bd26e94`). `probe_type` field exists. No conflicting local
changes.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier alternate fix for this race. `git log
--grep='synchronous probe' -- drivers/tty/serial/` only shows this
commit.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/tty/serial/8250` — **IMPORTANT**. 8250 is the standard
PC UART/console driver, not staging/peripheral.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained (regular tty/serial 8250 cleanups). The bug
is in long-lived register/unregister interaction plus async probe, not
in brand-new 8250 code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Config/cmdline specific: `CONFIG_SERIAL_8250` + PNP 8250, and
`driver_async_probe=serial` or `=*`. Default boot (no that parameter)
stays synchronous and does not hit it. Population is everyone using that
documented parameter on x86 8250, including distro/OEM boot-time
experiments.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Trigger: boot with `driver_async_probe=serial` (PNP name) or `=*`.
- Not default, but documented in `kernel-parameters.txt` for boot-time
optimization.
- Timing-dependent: deadlock vs NULL deref depends on whether `port_dev`
is populated yet.
- Unprivileged users cannot set the cmdline after boot.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Deadlock during early init → **CRITICAL** (boot hang).
- NULL deref in `serial_core_get_ctrl_dev()` → **CRITICAL** (oops).
- Author reproduced the hang on x86_64 defconfig + QEMU.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** High for anyone using `driver_async_probe` on 8250;
prevents boot hang/oops. Default path is unchanged.
- **Risk:** Very low (2 lines, existing driver-core flag, no locking/API
change).
- **Ratio:** Strongly in favor of taking it.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR backporting:
- Real, reproduced boot hang and a NULL deref on a common x86_64
defconfig.
- Failure modes are deadlock and oops (stable-class bugs).
- Two-line, obviously correct use of `PROBE_FORCE_SYNCHRONOUS`.
- Call paths verified in this 7.3-rc4 tree.
- Applied by the tty maintainer.
- Same annotation pattern as i8042 PNP.
- Default probe behavior is already synchronous; this only blocks a
dangerous async override.
AGAINST:
- Trigger is a non-default cmdline, not everyday production boots.
- No `Reviewed-by`; mailing list had no discussion.
- Author is not a serial regular.
- No syzbot or multi-user reports.
UNRESOLVED:
- Stable@ discussion could not be fetched (HTTP 403).
- Whether a more invasive serial-core locking fix would be “more
correct” long-term (not required for this self-contained workaround).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — two field sets; tested on
QEMU x86_64 defconfig; Greg applied it.
2. Fixes a real bug that affects users? **PASS** — hang/oops with a
documented kernel parameter.
3. Important issue? **PASS** — deadlock and NULL deref, severity
CRITICAL when triggered.
4. Small and contained? **PASS** — +2 lines, two 8250 driver structs.
5. No new features or APIs? **PASS** — uses existing `probe_type`.
6. Can apply to the local tree? **PASS** — files, APIs, and buggy paths
all exist on v7.3-rc4.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/DT/docs/build fix. Closest analogue is a
hardware/driver quirk: annotate a driver that cannot safely probe
asynchronously.
**Step 9.4: DECISION**
This belongs in this tree. The 8250 ISA/PNP overlap plus
`probe_irq_on()`’s `async_synchronize_full()` is a genuine boot deadlock
and oops once async probe is forced. The workaround is the smallest
correct change and does not alter the default synchronous boot path.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed tags: author SOB, Greg KH SOB, lore msgid link; no
Fixes/Reported-by/Reviewed-by/Cc-stable.
- [Phase 2] Diff: +1 line each in `8250_platform.c` and `8250_pnp.c`;
`probe_type = PROBE_FORCE_SYNCHRONOUS`.
- [Phase 2] `driver_allows_async_probing()`: `PROBE_FORCE_SYNCHRONOUS`
returns false even when cmdline requests async.
- [Phase 2] `serial8250_init()` order: `serial8250_pnp_init()` then
`serial8250_register_ports()` then `platform_driver_register()`.
- [Phase 2] `serial8250_register_8250_port()`: `if (uart->port.dev)
uart_remove_one_port()`.
- [Phase 2] `serial_core_unregister_port()` calls
`serial_core_get_ctrl_dev(port_dev)` before `port_mutex`.
- [Phase 2] `probe_irq_on()` calls `async_synchronize_full()`
(`kernel/irq/autoprobe.c:39`).
- [Phase 2] x86 `STD_COM*_FLAGS` include `UPF_AUTO_IRQ` when
`CONFIG_SERIAL_8250_DETECT_IRQ`; x86_64_defconfig sets that.
- [Phase 3] `git blame`: probe_type lines are this commit; surrounding
structs are older.
- [Phase 3] `84a9582fd2030` introduced `serial_core_unregister_port`
(contained in v6.5-rc1).
- [Phase 3] Author has no other 8250 commits; no prerequisite series.
- [Phase 4] `b4 dig -c 31e11af34e2c7`: original submission found; `-a`
shows v1 only; `-w` lists Greg/Jiri/Ilpo/linux-serial; `-m` mbox has
no replies.
- [Phase 4] lore.kernel.org WebFetch/curl: 403. LKML mirror confirms
same v1 text.
- [Phase 4] UNVERIFIED: stable@ archive contents.
- [Phase 5] PNP driver `.name = "serial"` matches
`driver_async_probe=serial`. ISA name is `serial8250`.
- [Phase 5] ACPI Kconfig `select PNP`; `SERIAL_8250_PNP` default y.
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; Makefile
7.3.0-rc4.
- [Phase 6] `git merge-base --is-ancestor 31e11af34e2c7 HEAD`: ancestor
(used only to confirm the code under review is this change).
- [Phase 8] Failure mode: early-init deadlock or NULL deref; severity
CRITICAL when `driver_async_probe` is used.
The patch is small, correct, and prevents a boot hang/oops on a path
that exists in this 7.3-rc4 tree.
**YES**
drivers/tty/serial/8250/8250_platform.c | 1 +
drivers/tty/serial/8250/8250_pnp.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
index fe7ec440ffa58..69d8720fb65bf 100644
--- a/drivers/tty/serial/8250/8250_platform.c
+++ b/drivers/tty/serial/8250/8250_platform.c
@@ -287,6 +287,7 @@ static struct platform_driver serial8250_isa_driver = {
.driver = {
.name = "serial8250",
.acpi_match_table = acpi_platform_serial_table,
+ .probe_type = PROBE_FORCE_SYNCHRONOUS,
},
};
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index 7a837fdf9df13..3f41a9d6cb273 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -521,6 +521,7 @@ static struct pnp_driver serial_pnp_driver = {
.remove = serial_pnp_remove,
.driver = {
.pm = pm_sleep_ptr(&serial_pnp_pm_ops),
+ .probe_type = PROBE_FORCE_SYNCHRONOUS,
},
.id_table = pnp_dev_table,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] wifi: rtlwifi: fix disabling of ASPM for RTL8723BE with AER flooding
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (61 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] serial: 8250: force synchronous probe for the ISA and PNP drivers Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] arm64/runtime-const: Use aarch64_insn_patch_text_nosync() for patching Sasha Levin
` (453 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: William Hansen-Baird, Ping-Ke Shih, Sasha Levin, linux-wireless,
linux-kernel
From: William Hansen-Baird <william.hansen.baird@gmail.com>
[ Upstream commit 04a46c2dbf3b516c96a1d19b72917b56055ad6c1 ]
commit 77a6407c6ab2 ("wifi: rtlwifi: disable ASPM for RTL8723BE with subsystem ID 11ad:1723")
adds code which sets ppsc->support_aspm to false in
_rtl_pci_update_default_setting() in order to disable ASPM.
This does not, however, disable ASPM. Rather, it disables driver
control of ASPM, and blocks calls to rtl_pci_enable_aspm()
and rtl_pci_disable_aspm().
In some cases, the pci device supplied to the probe function has
ASPM enabled. The code would therefore not disable ASPM, as it means to,
but rather just leave it enabled.
This was discovered through testing on a Razer Blade 14 2017.
Implement a new __rtl_pci_disable_aspm(hw) function which does not check
ppsc->support_aspm before disabling and call it from
rtl_pci_disable_aspm().
Then move the code added in the previous commit to rtl_pci_init_aspm() to
allow adding a call to __rtl_pci_disable_aspm(hw).
This makes sure ASPM is disabled while still disabling
driver control of ASPM to block it from being enabled later.
Signed-off-by: William Hansen-Baird <william.hansen.baird@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260630141553.785769-2-william.hansen.baird@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Local tree is **7.3.0-rc4**. The original incomplete RTL8723BE ASPM
quirk is in this lineage; this commit is a small, tested hardware-quirk
fix that actually clears ASPM instead of only blocking driver control.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: `[wifi: rtlwifi:] [fix] [ASPM disable for RTL8723BE with AER
flooding actually takes effect]`
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- No `Fixes:` tag (v3 cover letter: “Removed misleading Fixes tag from
patch 1”)
- No `Reported-by:` / `Tested-by:` on this commit (testing is described
in the body: Razer Blade 14 2017)
- `Acked-by: Ping-Ke Shih <pkshih@realtek.com>` (rtlwifi maintainer)
- `Signed-off-by: William Hansen-Baird` (author)
- `Signed-off-by: Ping-Ke Shih` (maintainer applied to rtw-next)
- `Link: https://patch.msgid.link/20260630141553.785769-2-
william.hansen.baird@gmail.com`
- No `Cc: stable@vger.kernel.org` (expected for this pipeline; not a
negative)
- Pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit ...]`
ignored per instructions
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** `77a6407c6ab2` set `ppsc->support_aspm = false` intending to
disable ASPM. That only disables *driver control* of ASPM
(`rtl_pci_enable_aspm` / `rtl_pci_disable_aspm` return early). If
firmware/BIOS left ASPM on at probe, it stays on.
- **Symptom:** PCIe AER flooding, heavy lag, poor throughput, occasional
lock-ups on RTL8723BE (subsystem 11ad:1723; same class of issue on
other 8723BE cards).
- **Root cause:** Early return `if (!ppsc->support_aspm) return;` in
`rtl_pci_disable_aspm()` prevents the register write that would clear
L0s/L1.
- **Fix:** `__rtl_pci_disable_aspm()` skips that check; quirk in
`rtl_pci_init_aspm()` calls it, then sets `support_aspm = false` so
ASPM is not re-enabled.
- **Version info:** Fixes incomplete quirk from April 2025; that quirk
is in this tree (first in v6.16).
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not hidden. Explicit fix of a broken hardware quirk. Not
cleanup-only.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/net/wireless/realtek/rtlwifi/pci.c` only (`26`
insertions, `13` deletions)
- Functions: `_rtl_pci_update_default_setting` (quirk removed),
`rtl_pci_disable_aspm` renamed to `__rtl_pci_disable_aspm` (early
`support_aspm` check dropped), new thin `rtl_pci_disable_aspm`
wrapper, `rtl_pci_init_aspm` (quirk moved here +
`__rtl_pci_disable_aspm()` call)
- Scope: single-file surgical hardware-quirk fix
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- **Before:** `_rtl_pci_update_default_setting()` for 11ad:1723 only
sets `support_aspm = false`. Later `rtl_pci_disable_aspm()` /
`rtl_pci_enable_aspm()` no-op. `rtl_pci_init_aspm()` never clears
LNKCTL ASPM bits. RTL8723BE default `const_pci_aspm = 3` would have
taken `RT_RF_PS_LEVEL_ALWAYS_ASPM` and tried to *enable* ASPM; the
quirk blocked that enable but did not clear already-set bits.
- **After:** After defaults, matching 11ad:1723 calls
`__rtl_pci_disable_aspm()` (writes LNKCTL, clears L0s/L1), then
`support_aspm = false`. ALWAYS_ASPM then calls
`rtl_pci_enable_aspm()`, which no-ops. Normal disable path still
respects `support_aspm`.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: **hardware workaround / logic correctness** (quirk did not
do what it claimed)
- Mechanism: `support_aspm = false` was treated as “ASPM off” but it
only gated driver helpers. Probe-time ASPM from firmware stayed
enabled → AER RxErr flood.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: disable first, then lock out re-enable.
- Minimal: no API change; other chips still go through the guarded
wrapper.
- Regression risk low: extra disable only for 11ad:1723; wrapper
preserves old behavior elsewhere.
- Residual limit (pre-existing): `__rtl_pci_disable_aspm()` still
returns if bridge vendor is UNKNOWN. Not introduced here.
- `_rtl8723be_enable_aspm_back_door()` still runs in `hw_init` and can
poke L0s/L1 via DBI; `enable_aspm()` afterward no-ops. Same as the
original quirk. Author testing reported AER flood stopped. Not a
reason to reject this patch.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Incomplete quirk introduced by `77a6407c6ab24` (“wifi: rtlwifi:
disable ASPM for RTL8723BE with subsystem ID 11ad:1723”), 2025-04-28,
**in v6.16** (not v6.15).
- That commit had `Cc: stable`, `Fixes: a619d1abe20c` (rtl8723be driver
add), bugzilla 218127, Tested-by.
- ASPM helpers themselves date to the original rtlwifi PCI code (much
older).
Step 3.2: FOLLOW THE FIXES: TAG
Record: No `Fixes:` on the candidate (intentionally dropped as
“misleading” in v3). Functionally it completes `77a6407c6ab24`. That
commit **is** an ancestor of this HEAD.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: 3-patch series (v4):
1. **This commit** — actual bugfix (standalone)
2. `676e59a3825c6` — if-statement → `rtl_aspm_quirks` table (refactor)
3. `2b7858891b100` — add 17aa:b736 (Razer Blade 14 2017)
This patch does not need 2 or 3. Later `b3943b3c29714` (2023) removed
*bogus bridge* ASPM writes; this patch only uses the remaining device
LNKCTL path, so it does not restore that danger.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: William Hansen-Baird authored this series plus one unrelated
rtl8723be irq cleanup. Applied and Acked by Ping-Ke Shih (Realtek
rtlwifi maintainer).
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Needs `77a6407c6ab24` (or equivalent 11ad:1723 quirk) and
existing `rtl_pci_disable_aspm` / `pcie_capability_*` helpers. All
present here. Standalone vs the rest of the series.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 04a46c2dbf3b5` → https://patch.msgid.link/20260630141553.78
5769-2-william.hansen.baird@gmail.com
- v1 2026-06-14, v2 2026-06-16, v3 2026-06-26, v4 2026-06-30 (applied)
- v2: split `__rtl_pci_disable_aspm()` so the check is bypassed only for
the quirk
- v3: style nits; **removed misleading Fixes tag**; trailing whitespace
- v4: whitespace/`{}` nits; Acked-by carried forward
- No NAKs. Ping-Ke: “looks good to me” + Acked-by; applied all 3 to rtw-
next
- No reviewer `Cc: stable` in the saved thread
- lore.kernel.org HTTP fetch returned 403; thread recovered via `b4 dig
-m`
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: `b4 dig -w`: author, `pkshih@realtek.com`, `linux-
wireless@vger.kernel.org`, `linux-kernel@vger.kernel.org`. Maintainer
reviewed and applied.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: This commit cites in-person testing on a Razer Blade 14 2017.
Underlying AER issue: kernel bugzilla 218127 and lore discussion from
`77a6407c6ab24` (ASUS F441U/X555UQ, 11ad:1723). Real user impact (lags,
lock-ups), not theoretical.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Patch 1 is the mechanism fix and is self-contained. Patches 2–3
are refactor + extra ID; not required for *this* commit.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: **UNVERIFIED** — lore.kernel.org/stable blocked (Anubis). No in-
tree evidence this was rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `_rtl_pci_update_default_setting`, `__rtl_pci_disable_aspm` (new
name of old body), `rtl_pci_disable_aspm` (new wrapper),
`rtl_pci_init_aspm`.
Step 5.2: TRACE CALLERS
Record:
- `rtl_pci_init_aspm()` from `rtl_pci_probe()` (device enumeration)
- `rtl_pci_disable_aspm()` from disconnect and `intf_ops->disable_aspm`
- `disable_aspm`/`enable_aspm` from rtl8723be `hw_init`, other rtlwifi
chips, and `ps.c` power save
- Probe/init path; not a syscall hot path. Userspace-visible via loading
the driver on affected laptops.
Step 5.3: TRACE CALLEES
Record: `pcie_capability_read_word` /
`_rtl_pci_platform_switch_device_pci_aspm` →
`pcie_capability_clear_and_set_word` on `PCI_EXP_LNKCTL`; optional
clkreq via `_rtl_pci_switch_clk_req`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: PCI probe → `rtl_pci_init_aspm` → quirk disable. Reachable on
affected hardware when `rtl8723be`/`rtlwifi` loads. Not a
sanitizer/syzbot path; real laptop hardware.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Toshiba 8192SE still only sets `support_aspm = false` without
forcing disable. Same class of incompleteness; this commit does not
touch it. Follow-up series extends the same disable+flag pattern to
17aa:b736 via an ID table.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes.** Checkout is **7.3.0-rc4**
(`v7.3-rc4-27-gf0100363d8c37`). `77a6407c6ab24` is an ancestor (present
since v6.16). Parent of the candidate still has the 11ad:1723 block that
only clears `support_aspm`. Driver, PCI ASPM helpers, and
`HARDWARE_TYPE_RTL8723BE` are all here. Bug was **not** introduced after
this tree branched.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Against the parent of `04a46c2dbf3b5`, the patch is a clean
apply on this file. Later 7.3 commits already refactored that quirk into
`rtl_aspm_quirks[]`; that is post-fix evolution, not a missing
prerequisite. No rework needed for this tree’s lineage.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No alternate fix of the same “flag vs actually clear LNKCTL” bug
besides this series. Original `77a6407c6ab24` is the incomplete version
this completes.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: `drivers/net/wireless/realtek/rtlwifi` —
**PERIPHERAL/IMPORTANT** for owners of RTL8723BE laptops (ASUS
F441U/X555UQ and similar). Not core mm/fs, but a shipping WiFi adapter
in production machines.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature driver; still receiving bugfixes. rtlwifi 8723BE is old
but still the in-tree driver for that chip.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific: RTL8723BE with subsystem **11ad:1723** (ASUSTek
F441U, X555UQ, etc.). Only that ID in *this* commit.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger is boot/probe with ASPM already enabled (common). Not a
race. Unprivileged users do not need a special exploit; plugging/using
the laptop is enough. Confirmed on real hardware.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: AER correctable-error flood → system-wide slowdown, bad WiFi
throughput, **occasional lock-ups**. Severity **HIGH** (hang/lock-up and
severe lag), not a KASAN crash.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** High for affected laptops; makes an already-stable quirk
actually work.
- **Risk:** Low (~26/+13 lines, one file, ID-gated, maintainer Acked,
tested).
- **Ratio:** Strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
**FOR:**
- Real hardware bug: AER flood, lag, lock-ups on known laptops
- Existing stable-bound quirk (`77a6407c6ab24`) did not disable ASPM
when it was already on
- Small, obviously correct, ID-scoped
- Hardware quirk exception
- Maintainer Acked-by and applied; author tested
- Prerequisite incomplete quirk is in this 7.3 tree
- Self-contained as patch 1/3
**AGAINST:**
- Affects a specific PCI subsystem ID, not all users
- No `Fixes:`/`Cc: stable` (expected here; Fixes was dropped as
misleading)
- DBI backdoor in `hw_init` still exists (pre-existing; testing said AER
stopped)
**UNRESOLVED:**
- Stable mailing-list history (lore/stable fetch blocked)
- Direct lore.kernel.org HTTP (403); discussion recovered via b4
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — maintainer ack; tested on
affected hardware; v2–v4 review
2. Fixes a real bug that affects users? **PASS** — broken quirk left
ASPM on; AER/lag/lock-ups
3. Important issue? **PASS** — lock-ups and severe performance, not
cosmetic
4. Small and contained? **PASS** — one file, +26/-13
5. No new features or APIs? **PASS** — completes an existing quirk
6. Can apply to the local tree? **PASS** — `pci.c` and `77a6407c6ab24`
are here; context matches
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **Hardware quirk/workaround** for a broken RTL8723BE/ASPM
combination.
Step 9.4: MAKE YOUR DECISION
This tree has the incomplete 11ad:1723 quirk and the rtlwifi ASPM path.
The change is a small, reviewed fix that actually clears ASPM so those
laptops do not keep flooding AER and locking up. It belongs in this
tree.
Verification:
- [Phase 1] Tags: Acked-by Ping-Ke Shih; Link msgid
20260630141553.785769-2; no Fixes/Cc:stable; v3 changelog said Fixes
was removed as misleading
- [Phase 1] Body: `support_aspm=false` blocks disable/enable helpers
instead of clearing ASPM
- [Phase 2] Diff: pci.c +26/-13; quirk moved to `rtl_pci_init_aspm`;
`__rtl_pci_disable_aspm` skips the flag check
- [Phase 2] RTL8723BE default `const_pci_aspm = 3` / `aspm_support = 1`
verified in `rtl8723be/sw.c`
- [Phase 3] `git merge-base --is-ancestor 77a6407c6ab24 HEAD` → yes;
original first in v6.16, not v6.15
- [Phase 3] `git merge-base --is-ancestor 04a46c2dbf3b5 HEAD` → yes; not
an ancestor of v7.2; is in v7.3-rc1
- [Phase 3] Series: this commit, then ID-table refactor, then 17aa:b736;
this patch standalone
- [Phase 4] `b4 dig -c 04a46c2dbf3b5` / `-a` / `-w` / `-m`: v1–v4,
maintainer Ack, applied to rtw-next; no NAK
- [Phase 4] WebFetch lore 403; stable lore Anubis — UNVERIFIED via HTTP
- [Phase 5] Callers: `rtl_pci_probe` → `rtl_pci_init_aspm`;
`intf_ops->disable_aspm` from rtl8723be `hw_init` and `ps.c`
- [Phase 6] `make kernelversion` / `git describe HEAD`: 7.3.0-rc4 /
`v7.3-rc4-27-gf0100363d8c37`; origin torvalds/linux.git
- [Phase 6] Parent of candidate still has 11ad:1723 `support_aspm =
false` only
- [Phase 8] Failure mode: AER flood, lag, lock-ups — HIGH; change ID-
gated — low risk
- UNVERIFIED: Whether this was discussed on stable@; whether DBI
backdoor re-enables L0s/L1 after probe on all machines (testing said
AER stopped)
The patch is a contained hardware-quirk correctness fix for a bug this
tree actually has.
**YES**
drivers/net/wireless/realtek/rtlwifi/pci.c | 39 ++++++++++++++--------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 8fb9604c3c533..f9f05252b890e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -156,15 +156,6 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
PCI_EXP_LNKCTL_ASPM_L1 | PCI_EXP_LNKCTL_CCC))
ppsc->support_aspm = false;
- /* RTL8723BE found on some ASUSTek laptops, such as F441U and
- * X555UQ with subsystem ID 11ad:1723 are known to output large
- * amounts of PCIe AER errors during and after boot up, causing
- * heavy lags, poor network throughput, and occasional lock-ups.
- */
- if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8723BE &&
- (rtlpci->pdev->subsystem_vendor == 0x11ad &&
- rtlpci->pdev->subsystem_device == 0x1723))
- ppsc->support_aspm = false;
}
static bool _rtl_pci_platform_switch_device_pci_aspm(
@@ -203,7 +194,7 @@ static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u16 value)
}
/*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/
-static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
+static void __rtl_pci_disable_aspm(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
@@ -215,9 +206,6 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
u16 aspmlevel = 0;
u16 tmp_u1b = 0;
- if (!ppsc->support_aspm)
- return;
-
if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) {
rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
"PCI(Bridge) UNKNOWN\n");
@@ -240,6 +228,16 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
_rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg);
}
+static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
+{
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ if (!ppsc->support_aspm)
+ return;
+
+ __rtl_pci_disable_aspm(hw);
+}
+
/*Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for
*power saving We should follow the sequence to enable
*RTL8192SE first then enable Pci Bridge ASPM
@@ -330,10 +328,25 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
static void rtl_pci_init_aspm(struct ieee80211_hw *hw)
{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
_rtl_pci_update_default_setting(hw);
+ /*
+ * RTL8723BE found on some ASUSTek laptops, such as F441U and
+ * X555UQ with subsystem ID 11ad:1723 are known to output large
+ * amounts of PCIe AER errors during and after boot up, causing
+ * heavy lags, poor network throughput, and occasional lock-ups.
+ */
+ if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8723BE &&
+ (rtlpci->pdev->subsystem_vendor == 0x11ad &&
+ rtlpci->pdev->subsystem_device == 0x1723)) {
+ __rtl_pci_disable_aspm(hw);
+ ppsc->support_aspm = false;
+ }
+
if (ppsc->reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM) {
/*Always enable ASPM & Clock Req. */
rtl_pci_enable_aspm(hw);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] arm64/runtime-const: Use aarch64_insn_patch_text_nosync() for patching
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (62 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] wifi: rtlwifi: fix disabling of ASPM for RTL8723BE with AER flooding Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] HID: rmi: check report length before trimming sentinel bytes Sasha Levin
` (452 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: K Prateek Nayak, Peter Zijlstra (Intel), Catalin Marinas,
Charlie Jenkins, Sasha Levin, will, linux-arm-kernel,
linux-kernel
From: K Prateek Nayak <kprateek.nayak@amd.com>
[ Upstream commit a6690350a4ae7558b39d15fcc776c4d1ab5bbf39 ]
The current scheme to directly patch the kernel text for runtime
constants runs into the following issue with futex adapted to using
runtime constants on arm64:
Unable to handle kernel write to read-only memory at virtual address ...
The pc points to the *p assignment in the following call chain:
futex_init()
runtime_const_init(shift, __futex_shift)
__runtime_fixup_shift()
*p = cpu_to_le32(insn);
which suggests that core_initcall() is too late to patch the kernel text
directly unlike the "d_hash_shift" which is initialized during
vfs_caches_init_early() before the protections are in place.
Use aarch64_insn_patch_text_nosync() to patch the runtime constants
instead of doing it directly to allow runtime_const_init() slightly
later into the boot.
Since aarch64_insn_patch_text_nosync() calls caches_clean_inval_pou()
internally, __runtime_fixup_caches() ends up being redundant.
runtime_const_init() are rare and the overheads of multiple calls to
caches_clean_inval_pou() instead of batching them together should be
negligible in practice.
The cpu_to_le32() conversion of instruction isn't necessary since it is
handled later in the aarch64_insn_patch_text_nosync() call-chain:
aarch64_insn_patch_text_nosync(addr, insn)
aarch64_insn_write(addr, insn)
__aarch64_insn_write(addr, cpu_to_le32(insn))
Sashiko noted that aarch64_insn_patch_text_nosync() does not expect a
lm_alias() address and Catalin suggested it is safe to drop the
lm_alias() for runtime patching since the kernel text is readable. The
address passed to fixup function is interpreted as a __le32 and
dereferenced as is to read the opcode at the patch site.
No functional changes are intended.
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
Tested-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
Link: https://patch.msgid.link/20260728052540.4728-3-kprateek.nayak@amd.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Connection lost, reconnecting to https://agentn.us.api5.cursor.sh
(attempt 1)...
Retry attempt 1...
## Phase 1: Commit message forensics
**Step 1.1 — Subject line**
- Record: **[arm64/runtime-const] [Use] switch text patching from a
direct store to `aarch64_insn_patch_text_nosync()`**
**Step 1.2 — Tags**
- Record:
- Signed-off-by: K Prateek Nayak (author)
- Signed-off-by: Peter Zijlstra (locking/futex maintainer)
- Reviewed-by: Catalin Marinas (arm64 maintainer)
- Reviewed-by: Charlie Jenkins
- Tested-by: Charlie Jenkins
- Link: https://patch.msgid.link/20260728052540.4728-3-
kprateek.nayak@amd.com
- No Fixes:, no Reported-by, no Cc: stable (absence expected)
- Ignore pipeline SOBs if present; none in the real commit
**Step 1.3 — Body**
- Record:
- **Bug:** arm64 runtime-const writes the patched opcode with `*p =
cpu_to_le32(insn)` through `lm_alias()`. That faults once kernel
text (including the linear alias) is read-only.
- **Symptom:** `Unable to handle kernel write to read-only memory`
during `futex_init()` → `runtime_const_init()` →
`__runtime_fixup_shift()`.
- **Root cause:** `d_hash_shift` is patched in
`vfs_caches_init_early()` while the linear alias is still writable.
`futex_init()` is a `core_initcall`, after
`mark_linear_text_alias_ro()`.
- **Fix:** use the existing text-poking helper (fixmap writable alias
+ cache maintenance). Drop redundant `__runtime_fixup_caches()` and
`cpu_to_le32()` (done inside the helper). Drop `lm_alias()` because
the helper wants a kernel-text address.
- **Version info:** none beyond the futex/runtime-const interaction.
**Step 1.4 — Hidden bug fix?**
- Record: Not hidden. The message describes a concrete oops. “No
functional changes are intended” means the patched immediates are the
same; the write path is what changes so late `runtime_const_init()`
can succeed.
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
- Record: one file, `arch/arm64/include/asm/runtime-const.h` (~5
insertions, 12 deletions). Functions: `__runtime_fixup_16()`,
`__runtime_fixup_caches()` (removed), `__runtime_fixup_ptr()`,
`__runtime_fixup_shift()`. Surgical, single-header.
**Step 2.2 — Flow change**
- Record:
- **Before:** read opcode at `lm_alias(where)`, store new insn with
`*p = cpu_to_le32(insn)`, then `caches_clean_inval_pou()` on the
original VA.
- **After:** pass the kernel-text pointer and host-endian insn to
`aarch64_insn_patch_text_nosync()`, which maps a writable fixmap
page, writes, and flushes I/D caches.
- Affected path: boot-time `runtime_const_init()` only (not a hot
path).
**Step 2.3 — Bug mechanism**
- Record: **logic/correctness of text patching after RO protection**.
Direct store to RO kernel text. The helper uses `patch_map()` →
`FIX_TEXT_POKE0`, the same path as kprobes/jump labels/ftrace.
**Step 2.4 — Fix quality**
- Record: Obviously correct. Matches how arm64 already patches text.
Regression risk is low: leftover `#include <asm/cacheflush.h>` is
unused after the helper absorbs the flush; return value of the helper
is ignored (old path had no error check either; kernel text is 4-byte
aligned). Catalin confirmed dropping `lm_alias()` is safe because
kernel text remains readable for the opcode load.
## Phase 3: Git history
**Step 3.1 — Blame**
- Record: Buggy direct-write scheme introduced in `94a2bc0f611cd`
(“arm64: add 'runtime constant' support”, Linus, 2024-07-09). Present
since ~v6.11. The crash only appears when `runtime_const_init()` runs
after `mark_linear_text_alias_ro()`.
**Step 3.2 — Fixes: tag**
- Record: none. Introducing commit is `94a2bc0f611cd` (in this tree).
The late caller that actually faults is `b78b0b6582527` (“futex: Use
runtime constants for `__futex_hash()` hot path”), also in this tree
(v7.3-rc1).
**Step 3.3 — File history**
- Record: `94a2bc0f611cd` add support → `0100e495cdf04` modules ban →
**`a6690350a4ae7` this fix** → `7eccf137dc044`
`runtime_const_mask_32()`. Same series as the futex conversion; this
patch is 2/8 and does not depend on later patches. Later mask support
*uses* this helper.
**Step 3.4 — Author**
- Record: K Prateek Nayak (AMD), not the arm64 maintainer. Arm64 review
is from Catalin. Peter Zijlstra signed off (locking tree). Related:
`7eccf137dc044` immediately after.
**Step 3.5 — Dependencies**
- Record: Needs `aarch64_insn_patch_text_nosync()` / `<asm/text-
patching.h>` — present at the parent and on HEAD. Standalone vs the
rest of the series. On *this* tree the futex caller is already
present, so the fix is load-bearing.
## Phase 4: Mailing list
**Step 4.1 — Original discussion**
- Record: `b4 dig -c a6690350a4ae` → `[PATCH v6 2/8] arm64/runtime-
const: Use aarch64_insn_patch_text_nosync() for patching` at
https://patch.msgid.link/20260728052540.4728-3-kprateek.nayak@amd.com.
Cover: `[PATCH v6 0/8] futex: Use runtime constants for futex_hash
computation`. v5→v6: no diff change on this patch; tags collected. No
NAKs. Sashiko noted the helper must not get an `lm_alias()` address;
Catalin said dropping it is fine. No reviewer asked for Cc: stable.
**Step 4.2 — Recipients**
- Record: Catalin Marinas, Will Deacon, Peter Zijlstra, Thomas Gleixner,
linux-arm-kernel, linux-arch. Right maintainers were on the To/Cc
list. Catalin Reviewed-by is on the committed patch.
**Step 4.3 — Bug report**
- Record: No syzbot/bugzilla. The oops is from the author’s own
futex+runtime-const bring-up on arm64. Charlie Jenkins Tested-by.
Cover letter: build+boot on x86 bare metal and QEMU for other arches.
**Step 4.4 — Series**
- Record: v6 8-patch feature series. This commit is the arm64 text-
poking prerequisite. Patch 8 adds `runtime_const_init()` in
`futex_init()`. Both are in this 7.3-rc4 tree.
**Step 4.5 — Stable list**
- Record: UNVERIFIED for a dedicated stable@ thread (lore HTTP 403). No
stable mention in the saved v6 mbox.
## Phase 5: Code semantics
**Step 5.1 — Functions**
- Record: `__runtime_fixup_16`, `__runtime_fixup_ptr`,
`__runtime_fixup_shift`; `__runtime_fixup_caches` removed. Current
tree also has `__runtime_fixup_mask` (later commit) using the same
helper.
**Step 5.2 — Callers**
- Record: `runtime_const_init()` → `runtime_const_fixup()` → those
fixups. Call sites in this tree:
- `kernel/futex/core.c` `futex_init()` — `core_initcall` — **after**
`smp_cpus_done()` → `mark_linear_text_alias_ro()`
- `fs/dcache.c`, `fs/file_table.c`, `fs/namei.c` —
`vfs_caches_init[_early]()` in `start_kernel()` — **before** that RO
switch
**Step 5.3 — Callees**
- Record: `aarch64_insn_patch_text_nosync()` → `aarch64_insn_write()` →
`__aarch64_insn_write()` (`patch_map` + `copy_to_kernel_nofault`) +
`caches_clean_inval_pou()`.
**Step 5.4 — Reachability**
- Record: Unconditional on arm64. `futex_init` is a `core_initcall`.
Every arm64 boot on this tree hits the late patch. Without this fix:
boot oops.
**Step 5.5 — Similar patterns**
- Record: x86 runtime-const still does a direct store and documents
“only at init before text is RO”. arm64’s linear-map alias is marked
RO earlier (`smp_cpus_done`), so arm64 cannot follow that model for
`core_initcall`.
## Phase 6: This tree
**Step 6.1 — Buggy code here?**
- Record: Yes. Tree is **v7.3-rc4** (`7.3.0-rc4`, HEAD `f0100363d8c37`).
File exists. Pre-fix body is at `a6690350a4ae^`. `futex_init()` still
calls `runtime_const_init()` (`kernel/futex/core.c`). The fix commit
**is already an ancestor of HEAD** (in v7.3-rc1). Current `runtime-
const.h` already calls `aarch64_insn_patch_text_nosync()`.
**Step 6.2 — Backport difficulty**
- Record: Clean on the parent snapshot. Current HEAD already has this
plus `runtime_const_mask_32()`; re-applying the exact hunk would be a
no-op / already-applied.
**Step 6.3 — Related fixes already here**
- Record: This *is* the fix. No later Fixes: for `a6690350`. Follow-up
`7eccf137dc044` only adds mask patching on the new helper.
## Phase 7: Subsystem
**Step 7.1**
- Record: **arch/arm64** text-patching used by **futex** (core locking).
Criticality: **IMPORTANT** — every arm64 boot.
**Step 7.2**
- Record: Active in the 7.3 window (futex runtime-const series). The
underlying helper is old, stable infrastructure.
## Phase 8: Impact and risk
**Step 8.1**
- Record: All arm64 users of this kernel (futex init is not optional).
**Step 8.2**
- Record: Every boot, `core_initcall(futex_init)`. Not userspace-
triggered; it is a boot breaker.
**Step 8.3**
- Record: Kernel fault writing RO text → boot failure. **CRITICAL**.
**Step 8.4**
- Record: Benefit high (arm64 actually boots with the futex runtime-
const code this tree already has). Risk low (~one-header, established
poking API, arm64 maintainer Reviewed-by).
## Phase 9: Synthesis
**Evidence for YES**
- Documented oops: write to RO memory in `__runtime_fixup_shift()`.
- This tree has the late caller (`futex_init` / `core_initcall`) and
`mark_linear_text_alias_ro()` in `smp_cpus_done()` before
`do_basic_setup()` / initcalls.
- Small, local, uses the standard arm64 patching API.
- Reviewed by Catalin Marinas; tested by Charlie Jenkins; signed off by
Peter Zijlstra.
- No new userspace API.
**Evidence against**
- Lives in a feature series (futex hash optimization). On trees
*without* a late `runtime_const_init()`, the old path never faulted.
- No Fixes:/Cc: stable (not a negative under these rules).
- Already in this 7.3-rc4 history, so a second apply is unnecessary —
that is not used as a NO (pipeline “already selected” is ignored).
**Unresolved**
- No stable@ thread readable (lore 403). Does not change the local
technical picture.
**Stable-rules checklist**
1. Obviously correct and tested — **PASS** (Catalin + Tested-by + QEMU
boot)
2. Real user-visible bug — **PASS** (arm64 boot oops with this tree’s
futex init)
3. Important (crash) — **PASS** (CRITICAL)
4. Small/contained — **PASS** (one header, ~17 lines)
5. No new features/APIs — **PASS**
6. Applies to this tree — **PASS** (code and helper are here; commit
already merged in 7.3-rc1)
**Exception category:** none (not an ID/quirk/DT/docs/build-only
change).
This tree ships both the late `runtime_const_init()` and arm64
`STRICT_KERNEL_RWX` linear-alias RO. The old `lm_alias()` store is a
boot crash. Replacing it with `aarch64_insn_patch_text_nosync()` is the
correct, minimal fix and belongs in this series.
### Verification
- [Phase 1] Parsed tags: Reviewed-by Catalin Marinas, Tested-by Charlie
Jenkins, Link to v6 2/8; no Fixes:/syzbot
- [Phase 2] Diff: one file; direct `*p` store + `lm_alias` +
`__runtime_fixup_caches` replaced by `aarch64_insn_patch_text_nosync`
- [Phase 2] Confirmed helper: `arch/arm64/kernel/patching.c`
`aarch64_insn_patch_text_nosync()` → write via `patch_map` +
`caches_clean_inval_pou`
- [Phase 3] `git describe HEAD` / Makefile: **v7.3-rc4**, `7.3.0-rc4`
- [Phase 3] `git merge-base --is-ancestor a6690350 HEAD`: yes; also in
v7.3-rc1; not in v7.2
- [Phase 3] Blame: buggy writes from `94a2bc0f611cd` (2024); late caller
`b78b0b6582527` in this tree
- [Phase 3] Parent file shown: `*p = cpu_to_le32(insn)` + `lm_alias`
- [Phase 4] `b4 dig -c a6690350`: lore match v6 2/8; mbox saved; no NAK;
Catalin R-b on the patch
- [Phase 4] Cover letter: feature series for futex runtime const; this
patch is the arm64 poking prerequisite
- [Phase 4] UNVERIFIED: stable@ mailing-list search (lore 403)
- [Phase 5] Callers: futex `core_initcall` (late); VFS caches in
`start_kernel` (early)
- [Phase 5] `mark_linear_text_alias_ro()` called from `smp_cpus_done()`;
`do_basic_setup()`/`do_initcalls()` after `smp_init()`
- [Phase 6] Current `runtime-const.h` already uses the helper; `text-
patching.h` exists at parent
- [Phase 8] Failure mode: RO-text write → boot oops on all arm64,
CRITICAL
- UNVERIFIED: Catalin’s original review mail text (only R-b + commit-
message paraphrase in v6 mbox)
The patch is small, uses the existing arm64 text-poking path, and
prevents a boot crash on this tree’s futex `runtime_const_init()`.
**YES**
arch/arm64/include/asm/runtime-const.h | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/include/asm/runtime-const.h b/arch/arm64/include/asm/runtime-const.h
index be5915669d239..31a6f94e57955 100644
--- a/arch/arm64/include/asm/runtime-const.h
+++ b/arch/arm64/include/asm/runtime-const.h
@@ -3,6 +3,7 @@
#define _ASM_RUNTIME_CONST_H
#include <asm/cacheflush.h>
+#include <asm/text-patching.h>
/* Sigh. You can still run arm64 in BE mode */
#include <asm/byteorder.h>
@@ -46,34 +47,26 @@ static inline void __runtime_fixup_16(__le32 *p, unsigned int val)
u32 insn = le32_to_cpu(*p);
insn &= 0xffe0001f;
insn |= (val & 0xffff) << 5;
- *p = cpu_to_le32(insn);
-}
-
-static inline void __runtime_fixup_caches(void *where, unsigned int insns)
-{
- unsigned long va = (unsigned long)where;
- caches_clean_inval_pou(va, va + 4*insns);
+ aarch64_insn_patch_text_nosync(p, insn);
}
static inline void __runtime_fixup_ptr(void *where, unsigned long val)
{
- __le32 *p = lm_alias(where);
+ __le32 *p = where;
__runtime_fixup_16(p, val);
__runtime_fixup_16(p+1, val >> 16);
__runtime_fixup_16(p+2, val >> 32);
__runtime_fixup_16(p+3, val >> 48);
- __runtime_fixup_caches(where, 4);
}
/* Immediate value is 6 bits starting at bit #16 */
static inline void __runtime_fixup_shift(void *where, unsigned long val)
{
- __le32 *p = lm_alias(where);
+ __le32 *p = where;
u32 insn = le32_to_cpu(*p);
insn &= 0xffc0ffff;
insn |= (val & 63) << 16;
- *p = cpu_to_le32(insn);
- __runtime_fixup_caches(where, 1);
+ aarch64_insn_patch_text_nosync(p, insn);
}
static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] HID: rmi: check report length before trimming sentinel bytes
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (63 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] arm64/runtime-const: Use aarch64_insn_patch_text_nosync() for patching Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] ata: ata_generic: Don't store pci_device_id Sasha Levin
` (451 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Jiri Kosina, Sasha Levin, jikos, bentiss,
linux-input, linux-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 28a3e326fad2451bdb66b747dd1f7ccbb900eed6 ]
rmi_check_sanity() trims trailing 0xff sentinel bytes, but its loop
reads data[valid_size - 1] before checking that valid_size is non-zero.
Reverse the condition so the length is proved before the last byte is
inspected.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **pending-6.12** (`6.12.111`). The buggy
`rmi_check_sanity()` loop is still present, the one-line short-circuit
reorder is not an ancestor of HEAD, and the patch applies here with only
a line-number offset.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[HID: rmi]** **[check]** check report length before trimming
sentinel bytes. Same class of wording as other HID length-check fixes:
the length must be proved before `data[valid_size - 1]` is read.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Pengpeng Hou \<pengpeng@iscas.ac.cn\> (author)
- Signed-off-by: Jiri Kosina \<jkosina@suse.com\> (HID maintainer)
- No Fixes:, Reported-by, Tested-by, Reviewed-by, Acked-by, Link:, or
Cc: stable (absence is expected for this review pipeline)
- Ignore any pipeline “Upstream commit” / Sasha Levin SOB markers
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: `rmi_check_sanity()` trims trailing `0xff` sentinels but
evaluates `data[valid_size - 1]` before `valid_size > 0`.
- Symptom: one-byte out-of-bounds read when the loop has already trimmed
the buffer to length 0.
- Root cause: C `&&` is left-to-right; the original order does the index
first.
- No stack traces, syzbot IDs, or version list in the message.
- Introducer (from git, not the message): `5b65c2a029664` (“HID: rmi:
check sanity of the incoming report”, 2014-09-10), first tagged
`v3.18-rc1`.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. It is an explicit short-circuit-order
OOB fix. The `valid_size > 0` test was already there; it was just on the
wrong side of `&&`.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/hid/hid-rmi.c` (1 insertion, 1 deletion)
- Function: `rmi_check_sanity()`
- Scope: single-file, one-line surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: `while ((data[valid_size - 1] == 0xff) && valid_size > 0)` —
when `valid_size` is 0, `data[-1]` is still read.
- After: `while (valid_size > 0 && data[valid_size - 1] == 0xff)` — the
subscript is not evaluated on an empty buffer.
- Path: runtime HID `raw_event` input, not probe/error-only.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Memory safety / OOB read.** HID core rejects a zero-length
report (`hid_input_report()` returns if `!size`), so the realistic
trigger is trimming an all-`0xff` (or fully trailing-`0xff`) report down
to 0, then doing one more iteration. That is the exact Dell XPS 13 9333
bus-sentinel case this helper was written for. One OOB byte is compared
to `0xff` and discarded; it is not copied to userspace, so this is not
an info leak, but it is still undefined-behavior / KASAN-class.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct C short-circuit reorder. No API, locking, or
control-flow change beyond skipping the illegal index. Regression risk
is negligible. `rmi_raw_event()` already drops `size < 2` after this
call.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Line 389 blamed to `5b65c2a029664` (Benjamin Tissoires,
2014-09-10). Present since **v3.18-rc1**. Long-lived in this 6.12 tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Introducer confirmed via blame: `5b65c2a029664`
is an ancestor of HEAD.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Candidate SHA on master: `28a3e326fad2451bdb66b747dd1f7ccbb900eed6`
(author date 2026-06-30, committer 2026-08-03). `git merge-base --is-
ancestor` vs HEAD: **not in this tree**.
- Related later commit already here: `ab2958e0c94ed` / upstream
`183da103022ec` “HID: rmi: fix OOB access with undersized RMI reports”
— probe-time report-size clamps and copy bounds. **Does not change
this loop.**
- Standalone one-line patch, not “X/Y”.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Pengpeng Hou is not the HID maintainer. Jiri Kosina applied it.
No other hid-rmi commits from this author in this checkout.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None. Same `while` line exists here. `git apply --check` of
`28a3e326fad24` succeeded (hunk offset 21 from the later OOB patch).
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 28a3e326fad24`:
https://patch.msgid.link/2026063007016439.1-ccfa108-0006-HID-rmi-
check-report-length-pengpeng@iscas.ac.cn
- `b4 dig -a`: **v1 only** (2026-06-30).
- Thread (3 messages): submission; Sashiko bot flagging **unrelated pre-
existing** read/write OOB in `rmi_hid_{read,write}_block` (later the
undersized-report patch already in this tree); Jiri Kosina “Applied,
thanks.” (2026-08-03).
- No NAK. No reviewer asked for Cc: stable.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To Jiri Kosina and Benjamin Tissoires; Cc linux-
input and linux-kernel. HID maintainers were on the original To: line.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla link on this patch. The sentinel behavior
itself is documented in-tree and in `5b65c2a029664` (Red Hat bugzilla
1123584 for Dell XPS 13 9333). That is the hardware path that can fill a
report with `0xff` and drive this loop to length 0.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone. Sibling OOB work (`HID: rmi: fix OOB access with
undersized RMI reports`) is already on pending-6.12 and does not subsume
this change.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — `lore.kernel.org/stable/?q=...` returned HTTP
403. No evidence in the linux-input thread that stable was discussed or
rejected.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `rmi_check_sanity()` only.
**Step 5.2: TRACE CALLERS**
Record: Sole caller is `rmi_raw_event()` (`drivers/hid/hid-rmi.c`),
registered as `.raw_event`. HID core `hid_input_report()`
(`drivers/hid/hid-core.c`) calls it after rejecting empty reports and
resolving a valid `hid_report`. hid-rmi has no `report_table`, so
`hid_match_report()` matches all reports. `rmi_raw_event()` then
requires `RMI_DEVICE` (set after probe validates RMI report IDs).
**Step 5.3: TRACE CALLEES**
Record: The function only indexes `data[]` and decrements `valid_size`.
No alloc/lock/I/O.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: USB/i2c HID interrupt → `hid_input_report()` → `rmi_raw_event()`
→ `rmi_check_sanity()`. Reachable from Synaptics RMI touchpads
(`HID_GROUP_RMI` in `hid_scan_report()`, plus specific USB IDs: Razer
Blade, Lenovo X1 cover, Primax, Acer Switch). Unprivileged USB can also
feed HID reports. Userspace-reachable: **yes** (device I/O, not a
syscall that crafts the buffer directly).
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Only this loop in hid-rmi. Same-tree HID length checks already
backported include `HID: lg4ff: validate report length before fixed
offsets` and `HID: wacom: validate report length in
wacom_intuos_pro2_bt_irq`.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `drivers/hid/hid-rmi.c` lines 389–390:
`while ((data[valid_size - 1] == 0xff) && valid_size > 0)`. Introduced
v3.18, still here on 6.12.111. Candidate `28a3e326fad24` is **not** an
ancestor of HEAD.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply with +21 line offset. No refactor of this helper.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: `ab2958e0c94ed` is a different OOB (report descriptor / copy
length). It does not reorder this condition. No earlier equivalent of
this one-liner.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **HID / hid-rmi** (Synaptics RMI4 over i2c-hid/usbhid).
**IMPORTANT** for laptops with Synaptics HID touchpads; not mm/VFS core,
but not staging/obscure either.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: hid-rmi is mature (2014+). Recent churn is security-style OOB
hardening, not a rewrite of this path.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific: CONFIG_HID_RMI / Synaptics RMI HID devices
(common on some Dell/Lenovo/Acer laptops). Also any malicious HID gadget
bound as hid-rmi.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: A report whose remaining bytes are all `0xff` (documented XPS 13
9333 bus glitch, or a device sending that pattern). After the last
decrement, `valid_size == 0` and the next condition still reads
`data[-1]`. Not every report; it is the sentinel path this function
exists to handle. Physical HID access required; not a random
unprivileged syscall.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: One-byte heap underflow read. Typical result: KASAN report;
crash only if that byte is unmapped (uncommon for kmalloc). Not data
corruption. **Severity: HIGH** for memory safety / HID attack surface,
not a guaranteed panic.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: stops a real OOB on a long-lived, hardware-motivated path; 1
line.
- Risk: very low (boolean operand swap).
- Ratio: strongly in favor of backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB; the `> 0` check was present but evaluated too late.
- Trigger matches the in-tree Dell XPS sentinel comment, not a
hypothetical size=0 from HID core.
- Code has been in this tree since v3.18.
- 1-line, obviously correct; HID maintainer applied v1 as-is.
- Applies cleanly; no prerequisites.
- Same class as other HID length-check stable backports already on this
branch.
AGAINST:
- No Fixes:/Cc: stable/syzbot (not a negative under these rules).
- Single-byte read, not a demonstrated oops or leak.
- Affects hid-rmi users, not every machine.
UNRESOLVED:
- Could not search lore.kernel.org/stable (HTTP 403).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — C short-circuit; applied by
Jiri Kosina.
2. Fixes a real bug that affects users? **PASS** — OOB on the sentinel-
trim path this driver documents.
3. Important issue? **PASS** — memory-safety OOB on HID input (HIGH, not
a guaranteed panic).
4. Small and contained? **PASS** — 1 line, one function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — buggy line present; `git
apply --check` succeeded.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None. Ordinary small bugfix.
**Step 9.4: MAKE YOUR DECISION**
This belongs on **this** 6.12 tree: the bug exists here, the later
undersized-report patch does not fix it, and the change is a one-line
operand swap with no API or locking impact.
===============================================================
What the commit solves for stable users
===============================================================
`rmi_check_sanity()` is supposed to strip trailing `0xff` filler from
Synaptics HID reports. Because `&&` evaluates left-to-right, an all-
sentinel report is trimmed to length 0 and then still reads `data[-1]`.
Laptop touchpads that hit that bus glitch, and USB HID devices that send
the same pattern, can fire a KASAN OOB on every such report. Reordering
the condition makes the existing length check actually protect the
index.
Risk vs benefit: benefit is a real memory-safety hole on a driver
already receiving other OOB backports; risk is a one-line boolean
reorder. No dependencies beyond code that has been here since v3.18.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed subject/body/tags: no Fixes/Reported-by/Cc: stable;
SOBs Hou + Kosina.
- [Phase 2] Diff: 1 line in `rmi_check_sanity()`; operand order only.
- [Phase 3] `git describe HEAD` / Makefile: **pending-6.12, 6.12.111**.
- [Phase 3] `git blame -L 379,410 -- drivers/hid/hid-rmi.c`: introducer
`5b65c2a029664` (v3.18-rc1).
- [Phase 3] `git merge-base --is-ancestor 5b65c2a029664 HEAD`: yes;
`28a3e326fad24`: **no**.
- [Phase 3] Current file still has `while ((data[valid_size - 1] ==
0xff) && valid_size > 0)`.
- [Phase 3] Related `ab2958e0c94ed` already in tree; does not touch this
loop.
- [Phase 3] `git show 28a3e326fad24 | git apply --check`: hunk succeeded
at offset 21.
- [Phase 4] `b4 dig -c 28a3e326fad24`: lore msgid
`2026063007016439.1-ccfa108-...`; To: Kosina + Tissoires.
- [Phase 4] `b4 dig -a`: v1 only; Kosina “Applied, thanks.”
- [Phase 4] Mbox: Sashiko comments are about other pre-existing OOBs,
not this line.
- [Phase 5] Callers: `rmi_raw_event` ← `hid_input_report`; empty `size`
rejected at hid-core.c:2111–2115.
- [Phase 6] Bug present; apply clean; no duplicate fix.
- [Phase 8] Failure mode: 1-byte OOB read on all-`0xff` reports; HID
input path.
- UNVERIFIED: stable@ lore search (HTTP 403).
**YES**
drivers/hid/hid-rmi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index d55a0388895fb..ecc19387f6b05 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -386,7 +386,7 @@ static int rmi_check_sanity(struct hid_device *hdev, u8 *data, int size)
* such reports here.
*/
- while ((data[valid_size - 1] == 0xff) && valid_size > 0)
+ while (valid_size > 0 && data[valid_size - 1] == 0xff)
valid_size--;
return valid_size;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] ata: ata_generic: Don't store pci_device_id
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (64 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] HID: rmi: check report length before trimming sentinel bytes Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] soundwire: intel_auxdevice: Add cs42l44 to wake_capable_list Sasha Levin
` (450 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Gary Guo, Bjorn Helgaas, Danilo Krummrich, Damien Le Moal,
Sasha Levin, cassel, linux-ide, linux-kernel
From: Gary Guo <gary@garyguo.net>
[ Upstream commit 4f3075f629077a8cb3d3455c794a1f4a8fc8b43e ]
pci_device_id is not guaranteed to live longer than probe due to presence
of dynamic ID. All information apart from driver_data can be easily
retrieved from pci_dev, so just store driver_data.
Signed-off-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
Acked-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://patch.msgid.link/20260723-pci_id_fix-v4-1-3580726844e1@garyguo.net
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have the history, the series context, and the UAF path. Next I’ll
write the full nine-phase verdict for this 7.3-rc4 tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[ata / ata_generic] [Don't store] [Stop keeping a pointer to
struct pci_device_id in host private_data; keep only driver_data]`
Subsystem prefix is `ata: ata_generic:`. Action is “Don’t store” —
defensive lifetime fix, not a feature.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected for this review pipeline)
- **Reported-by:** none on this commit
- **Tested-by:** none
- **Reviewed-by:** Danilo Krummrich `<dakr@kernel.org>` (PCI/driver-
core)
- **Acked-by:** Damien Le Moal `<dlemoal@kernel.org>` (libata
maintainer)
- **Link:** `https://patch.msgid.link/20260723-pci_id_fix-v4-1-
3580726844e1@garyguo.net` (v4 patch 1/9)
- **Cc: stable:** none (not a negative signal)
- **Signed-off-by:** Gary Guo (author); Bjorn Helgaas (PCI maintainer,
committer)
- Ignore any Sasha Levin SOB if present — none on the actual git commit
`4f3075f629077`
Notable: ATA maintainer Ack plus PCI maintainer commit. Series name
`pci_id_fix-v4` — this is patch 1 of 9.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `pci_device_id` is not guaranteed to outlive `probe` because
PCI dynamic IDs (`new_id` / `remove_id`) can free that object.
- **Symptom/failure mode:** later dereference of
`ap->host->private_data` as `const struct pci_device_id *` is a use-
after-free.
- **Version info:** none in the message.
- **Root cause:** `ata_generic_init_one()` stored the `id` pointer via
`ata_pci_bmdma_init_one(..., (void *)id, ...)`. `generic_set_mode()`
later reads `id->driver_data`. Only `driver_data` is needed;
vendor/device can come from `pci_dev`.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. The subject is lifetime hygiene, but
the mechanism is a real UAF if a dynamic ID is freed while the ATA host
still holds the pointer. Cover letter for the series calls storing
`pci_device_id` from probe a “bad pattern” and names a genuine dynamic-
ID UAF (Sashiko report, used for the PCI-core patch). This driver change
is both a standalone dangling-pointer fix and a prerequisite so PCI core
can shrink dyn-ID lifetime.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/ata/ata_generic.c` — 3 insertions, 3 deletions (net 0,
6 lines touched)
- Functions: `generic_set_mode()`, `ata_generic_init_one()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Hunk 1 (`generic_set_mode`):
- Before: `const struct pci_device_id *id = ap->host->private_data;`
then `id->driver_data & ATA_GEN_FORCE_DMA`
- After: `unsigned long driver_data = (unsigned
long)ap->host->private_data;` then `driver_data & ATA_GEN_FORCE_DMA`
- Path: ATA mode programming, including libata error handling
(`ata_eh_set_mode()` → `ap->ops->set_mode`), not probe-only
Hunk 2 (`ata_generic_init_one`):
- Before: `ata_pci_bmdma_init_one(..., (void *)id, 0)` stores the full
`pci_device_id *`
- After: `ata_pci_bmdma_init_one(..., (void *)id->driver_data, 0)`
stores the integer flags only
- Path: PCI probe / host registration
`ATA_GEN_CLASS_MATCH` and `ATA_GEN_INTEL_IDER` remain consumed from the
live `id` argument during probe only — they are not read from
`private_data`.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** memory safety / use-after-free (stale pointer)
- **Mechanism:** PCI `remove_id_store()` does `list_del` +
`kfree(dynid)` under `dynids.lock` without unbinding devices. If the
host was bound via that dyn ID, `host->private_data` still pointed at
`dynid->id`. `generic_set_mode()` later loads `id->driver_data`.
- After the later PCI-core change in this same series (`3ffc4c9690c33`),
dyn-ID matches return a **stack copy** valid only during probe
(`include/linux/pci.h`: “The pci_device_id parameter is only valid
during probe.”). Storing that pointer past probe would then be a stack
UAF even without `remove_id`. This driver patch must land first (and
it did: v4-1 before v4-9).
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: the only post-probe use was `id->driver_data`; copy
that integer instead of the object.
- Minimal; no unrelated edits; no API change.
- Regression risk: very low. `driver_data` values are small flags
(`1<<0`..`1<<2`). Same `void *` ↔ `unsigned long` trick already used
elsewhere (e.g. `pata_amd.c`).
- This tree already contains the after-state (`4f3075f629077` is an
ancestor of HEAD).
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Storing the `pci_device_id *` in `host->private_data` was introduced
in `1529c69adce1e` (“ata_generic: implement ATA_GEN_* flags and force
enable DMA on MBP 7,1”), 2010-07-01, contained in `v2.6.35-rc4`.
- That commit is an ancestor of this tree. The pattern is ~16 years old,
not new 7.3 code.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag on this commit. The buggy pattern is
`1529c69adce1e`, verified present. Related PCI-core UAF has `Fixes:
0994375e9614` (“PCI: add remove_id sysfs entry”) on `3ffc4c9690c33` —
different patch, same series.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record (last commits on `drivers/ata/ata_generic.c`):
- `4f3075f629077` this fix
- `9986ce65bebb9` constify `pci_device_id` (unrelated)
- No other recent functional churn at these lines
Standalone vs series: **patch 1/9** of `pci_id_fix`. Sibling driver
patches (`nsp32`, `tpci200`, `mlxsw`, agp). PCI core is patches 7–9.
**This patch applies standalone**; it does not call new PCI helpers.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Gary Guo is not the ATA maintainer; he is the series author
(Rust/PCI ID work). Nearby same-author commits: `3c28376273e8f` nsp32,
`9a1b9aa5cedf3` tpci200, `1ae2920768f79` mlxsw, plus PCI TOCTOU/UAF.
Damien Le Moal Acked this ATA patch. Bjorn Helgaas committed it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: No prerequisites. `ata_pci_bmdma_init_one(..., void *host_priv,
...)` has taken an opaque `host_priv` for a long time (`libata-sff.c`).
This is a caller-side change only. Later PCI patches depend on *this*
class of driver fix, not the reverse.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 4f3075f629077` matched patch-id; lore URL: `https://patch.m
sgid.link/20260723-pci_id_fix-v4-1-3580726844e1@garyguo.net`
- `b4 dig -a` revisions:
- v1 2026-06-26: PCI match refactor only (this driver fix not yet
present)
- v2 2026-06-30: `[PATCH v2 1/7] ata: don't keep pci_device_id` —
driver stores added
- v3 2026-07-06: `[PATCH v3 1/9] ata: don't store pci_device_id`
- v4 2026-07-23: applied version; cover: “PCI: Fix UAF and TOCTOU
related to dynamic ID”
- v2 changelog: “Fix users which store pci_device_id.” v4: style fixes
from Bjorn. Applied version is latest.
- No NAK on this patch. Sashiko bot: “found no issues.”
- Cover letter: Sashiko reported a genuine dynamic-ID UAF; storing
`pci_device_id` from probe is called out as a bad pattern.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): linux-ide, linux-pci, driver-core, linux-scsi,
netdev, dri-devel; Damien Le Moal, Niklas Cassel, Bjorn Helgaas, Danilo
Krummrich, Greg KH. Right maintainers were on CC. Reviewed-by Krummrich,
Acked-by Le Moal, committed by Helgaas.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: This specific ATA patch has no `Reported-by`. The series UAF
report is on patch 9: `Reported-by: Sashiko <sashiko-bot@kernel.org>` /
lore `20260619170503.518F61F00A3A@smtp.kernel.org`. Direct WebFetch of
lore returned HTTP 403; thread was recovered via `b4 dig -m`. No user
crash log for `ata_generic` itself.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 9-patch series. Patches 1–6 fix drivers that stash or pointer-
arithmetic the ID. Patches 7–9 change PCI matching, dyn-ID TOCTOU, and
concurrent probe vs `remove_id` UAF. This commit is self-contained; it
does not require 7–9 to be correct. If 9 were backported without 1, dyn-
ID probe would hand a stack copy to `ata_generic`, which would then
store it — a worse UAF. Evaluating **this** commit alone: it is
independently correct.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: `curl`/`WebFetch` to `lore.kernel.org/stable/` returned 403. The
saved v4 thread contains **no** `Cc: stable` discussion. **UNVERIFIED:**
whether anyone asked for this on the stable list.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `generic_set_mode()`, `ata_generic_init_one()`. (semcode MCP not
available; used hunks + grep.)
**Step 5.2: TRACE CALLERS**
Record:
- `ata_generic_init_one` — PCI `.probe` of `ata_generic_pci_driver`
(device bind).
- `generic_set_mode` — `generic_port_ops.set_mode`. Called from
`ata_eh_set_mode()` in `drivers/ata/libata-eh.c` when
`ap->ops->set_mode` is set. That runs from `ata_eh_recover()` when
`ATA_EHI_SETMODE` is set (initial config, reset, revalidate). **After
probe**, disk errors / resume / EH can invoke it.
**Step 5.3: TRACE CALLEES**
Record: `ata_pci_bmdma_init_one()` stores `host_priv` on the `ata_host`.
`generic_set_mode` reads BMDMA status and libata xfer-mask helpers. No
new allocations or locks.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record:
- Common path: PCI probe of a device in the static `ata_generic[]` table
→ `id` points at module `.rodata` for the module’s lifetime → **no
UAF** on static IDs.
- Buggy path: `echo ... > /sys/bus/pci/drivers/ata_generic/new_id`
(typically CAP_SYS_ADMIN) → bind via heap `pci_dynid` → store pointer
→ `remove_id` kfree’s dynid while host still bound → later EH
`generic_set_mode` → UAF.
- Reachable from userspace: yes, via PCI sysfs + later ATA EH. Not a
normal unprivileged syscall path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same-series fixes in `nsp32`, `tpci200`, `mlxsw`, agp. Other ATA
drivers store their own `hpriv`, not `pci_device_id *`. Pattern was
systematic across PCI drivers, not unique to ATA.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion` = `7.3.0-rc4` (Linus mainline, detached HEAD).
- Commit `4f3075f629077` **is already an ancestor of HEAD** (`git merge-
base --is-ancestor` succeeded; first appeared in `v7.3-rc1`).
- Current `drivers/ata/ata_generic.c` already stores `id->driver_data`
and reads it as `unsigned long`.
- The **pre-fix** code existed on this lineage from `1529c69adce1e`
(v2.6.35) until that commit. This is not a “bug introduced after this
tree branched” case.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Against the pre-fix file (`4f3075f629077^`), the diff is a clean
6-line replace. No refactor of `ata_generic.c` in between. Expected
apply on a tree that still has the old pointer store: **clean**. On
*this* checkout the after-state is already present, so re-applying the
patch would be a no-op/conflict with itself — that is git ancestry, not
a missing-code problem.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This exact fix is in HEAD. PCI-core companion `3ffc4c9690c33` is
also an ancestor. No alternate/earlier ata_generic dyn-ID fix found
(`git log --grep=pci_device_id -- drivers/ata/ata_generic.c` only this
commit and an unrelated constify).
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/ata/` — libata generic PCI IDE driver
(`CONFIG_ATA_GENERIC`). **IMPORTANT** for machines that still use BIOS-
configured PATA/IDE (Cenatek FORCE_DMA, Intel IDE-R, various legacy
chips). Not mm/net core, but storage.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: libata is actively maintained (recent EH/LPM/AHCI fixes).
`ata_generic.c` itself is mature; little churn besides this lifetime
fix.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific (`CONFIG_ATA_GENERIC`), and the UAF only if the
host was bound via a **dynamic** PCI ID. Static-table devices (the usual
case) keep `id` in module memory. Affected population: admins using
`new_id` on `ata_generic`, then `remove_id` or (after PCI stack-copy)
any post-probe `set_mode`.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Trigger: privileged sysfs `new_id`/`remove_id`, then ATA EH
`set_mode`.
- Likelihood on production LTS: **low** (dyn IDs are uncommon for this
driver).
- Unprivileged trigger: **no** (driver `new_id`/`remove_id` are root-
owned sysfs). Still a real kernel UAF, not theoretical pointer math.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Use-after-free of `pci_dynid` / dangling ID pointer → KASAN/oops
or worse. **Severity: HIGH** when triggered; **likelihood: LOW**.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Prevents a real UAF in a long-lived storage driver;
3-line change; maintainer-acked. Also keeps the driver correct if the
PCI dyn-ID lifetime fix is applied.
- **Risk:** Very low (tiny, local, no locking/API).
- **Ratio:** favorable. Conservative “rare trigger” concern does not
outweigh UAF + trivial patch.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR backporting:
- Real UAF: `host->private_data` held `pci_device_id *` beyond probe;
`remove_id` can free dyn IDs; `generic_set_mode` runs from libata EH
after probe.
- Bug present since v2.6.35 (`1529c69adce1e`); code exists on this
lineage.
- 6-line, obviously correct; only `driver_data` was used post-probe.
- Reviewed/Acked by PCI and ATA maintainers; PCI maintainer committed
it.
- No new APIs/features.
- Self-contained; no missing helpers in this tree.
AGAINST:
- Common static-ID path was not buggy; trigger needs dyn-ID sysfs
(root).
- No user crash report / syzbot on this exact driver file.
- Part of a 9-patch series whose headline UAF is PCI-core patch 9; this
was added in v2 as “fix users which store pci_device_id.”
- No `Cc: stable` in the thread (absence is expected).
UNRESOLVED:
- lore.kernel.org HTTP 403 for live pages; used `b4 dig` mbox instead.
- Stable-list discussion UNVERIFIED (403).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — logic is local and reviewed;
Sashiko found no issues on v4-1.
2. Fixes a real bug that affects users? **PASS** — dangling
`pci_device_id` after dyn-ID removal / after probe lifetime; users of
`ata_generic` + `new_id` can hit it.
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
UAF → oops/KASAN (HIGH, rare trigger).
4. Small and contained? **PASS** — 6 lines, one file.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** for trees still on the old
pointer store. This 7.3-rc4 checkout already contains the commit;
that does not make the fix unsuitable — it confirms the code and
helpers exist here.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None (not a device ID / quirk / DT / build / docs exception).
Qualifies as a normal small UAF fix.
**Step 9.4: MAKE YOUR DECISION**
This tree is **Linux 7.3-rc4** (mainline). `ata_generic` is present; the
buggy store-the-`id`-pointer pattern lived here from 2010 until
`4f3075f629077`. The patch is a 3-line lifetime fix for a real UAF, not
a feature or refactor, and it applies in isolation.
Rare privileged trigger is not enough to reject a tiny, maintainer-acked
UAF fix in a storage driver. It meets stable-kernel-rules.
### What the commit solves (for stable users)
`ata_generic` used to keep a pointer to the `pci_device_id` passed into
probe. For IDs added through sysfs `new_id`, that object can be freed by
`remove_id` while the ATA host is still live. `generic_set_mode()` —
including from error handling — then dereferences freed memory. The fix
copies `driver_data` (the only field used later) and drops the pointer.
### Risk vs benefit
Benefit is avoiding a UAF/oops on a long-standing driver. Risk is
negligible. No prerequisites missing in this tree.
---
Verification:
- [Phase 1] Parsed tags on `4f3075f629077`: Reviewed-by Danilo
Krummrich, Acked-by Damien Le Moal, Link to v4-1; no Fixes/Reported-
by/Cc:stable
- [Phase 1] Subject/body: don’t store `pci_device_id`; dyn-ID lifetime
- [Phase 2] Diff: 3+ / 3- in `drivers/ata/ata_generic.c`;
`generic_set_mode` + `ata_generic_init_one`
- [Phase 2] Pre-fix file via `git show
4f3075f629077^:drivers/ata/ata_generic.c`: stored `(void *)id`, later
`id->driver_data & ATA_GEN_FORCE_DMA`
- [Phase 3] `git blame` / `git log -S private_data --
drivers/ata/ata_generic.c`: introduced `1529c69adce1e` (2010,
`v2.6.35-rc4`)
- [Phase 3] `git merge-base --is-ancestor 1529c69adce1e HEAD` — yes;
`4f3075f629077` — yes
- [Phase 3] Series: `3c28376273e8f`, `9a1b9aa5cedf3`, `1ae2920768f79`,
`c967b365d7b51`, `04fde70f782b6`, `3ffc4c9690c33`
- [Phase 4] `b4 dig -c 4f3075f629077`: patch.msgid.link v4-1; `-a`:
v1–v4; `-w`: linux-ide/linux-pci + Le Moal/Helgaas
- [Phase 4] `b4 dig -m`: cover letter genuine dyn-ID UAF; this patch
added in v2; no NAK; Sashiko OK
- [Phase 4] WebFetch lore/patch.msgid.link: HTTP 403; used b4 mbox
instead
- [Phase 4] Stable list: UNVERIFIED (403)
- [Phase 5] Callers: PCI probe; `ata_eh_set_mode()` in `libata-eh.c`
lines 3480–3482 and 3962–3963
- [Phase 5] `remove_id_store()` in `drivers/pci/pci-driver.c` kfree’s
dynid without unbind
- [Phase 5] `include/linux/pci.h` ~989: id only valid during probe
(after series)
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37;
kernelversion 7.3.0-rc4
- [Phase 6] Current file already has the fix (commit in 7.3-rc1)
- [Phase 7] `CONFIG_ATA_GENERIC` in `drivers/ata/Kconfig` — generic BIOS
ATA, PCI+BMDMA
- [Phase 8] Failure mode: UAF in EH `set_mode`; severity HIGH; trigger
privileged dyn-ID; risk of the patch itself very low
- UNVERIFIED: stable@ lore discussion (HTTP 403)
The patch is small, fixes a real use-after-free, and meets stable
criteria for this tree’s `ata_generic` code.
**YES**
drivers/ata/ata_generic.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index e70b6c089cf17..18ea740ca5829 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -51,11 +51,11 @@ enum {
static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
{
struct ata_port *ap = link->ap;
- const struct pci_device_id *id = ap->host->private_data;
+ unsigned long driver_data = (unsigned long)ap->host->private_data;
int dma_enabled = 0;
struct ata_device *dev;
- if (id->driver_data & ATA_GEN_FORCE_DMA) {
+ if (driver_data & ATA_GEN_FORCE_DMA) {
dma_enabled = 0xff;
} else if (ap->ioaddr.bmdma_addr) {
/* Bits 5 and 6 indicate if DMA is active on master/slave */
@@ -206,7 +206,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
return rc;
pcim_pin_device(dev);
}
- return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0);
+ return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id->driver_data, 0);
}
static const struct pci_device_id ata_generic[] = {
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] soundwire: intel_auxdevice: Add cs42l44 to wake_capable_list
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (65 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] ata: ata_generic: Don't store pci_device_id Sasha Levin
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] nvmet: zns: reject full zone report when buffer is too small Sasha Levin
` (449 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Charles Keepax, Vinod Koul, Sasha Levin, yung-chuan.liao,
linux-sound, linux-kernel
From: Charles Keepax <ckeepax@opensource.cirrus.com>
[ Upstream commit d08e4d9197396ceb906715d976b63aed0c5cc8e5 ]
Add cs42l44 to the wake_capable_list because it can generate
jack events whilst the bus is stopped.
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20260708122948.1502227-1-ckeepax@opensource.cirrus.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to judge this: it is a one-line Intel SoundWire wake quirk
for CS42L44, which this 7.3-rc4 tree already contains.
## Local tree
- `git describe HEAD`: `v7.3-rc4-27-gf0100363d8c37`
- `make kernelversion`: `7.3.0-rc4`
- Makefile: `VERSION=7 PATCHLEVEL=3 SUBLEVEL=0 EXTRAVERSION=-rc4`
- Commit under review: `d08e4d9197396ceb906715d976b63aed0c5cc8e5`
- `git merge-base --is-ancestor d08e4d9197396 HEAD`: yes (merged via
`soundwire-7.3-rc1`; not in `v7.2`)
Verdict is for this 7.3-rc4 checkout only. `intel_auxdevice.c`,
`wake_capable_list`, and `is_wake_capable()` are present here. This is a
host-side ID quirk in an existing Intel SoundWire master driver.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[soundwire/intel_auxdevice] [Add] [put CS42L44 on the Intel
wake-capable quirk list]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Fixes:` none (expected)
- `Reported-by:` none
- `Tested-by:` none
- `Reviewed-by:` none on the committed version
- `Acked-by:` none
- `Link:` `https://patch.msgid.link/20260708122948.1502227-1-
ckeepax@opensource.cirrus.com`
- `Cc: stable@vger.kernel.org`: none (expected)
- `Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>`
(Cirrus, chip vendor)
- `Signed-off-by: Vinod Koul <vkoul@kernel.org>` (SoundWire maintainer)
- Ignore any Sasha Levin SOB / `[Upstream commit]` markers (none in the
real commit)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: CS42L44 can raise jack events while the SoundWire bus is clock-
stopped, but the Intel master did not treat it as wake-capable.
- Symptom: headset plug/unplug while audio is idle is missed; bus/system
does not wake for jack detect.
- Version info: none in the message. Commit landed for 7.3-rc1.
- Root cause (from this patch plus `e66f91a2d10b9`): ACPI does not
export wake capability; the codec driver’s `wake_capable` flag is too
late (set at probe, after device-number assignment). The Intel master
uses a static mfg/part quirk table.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised cleanup. Explicit hardware-quirk / device-ID
addition.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/soundwire/intel_auxdevice.c` (`+1 / -0`)
- Function: none; one entry in `wake_capable_list[]`
- Scope: single-file surgical ID add
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: `{0x01fa, 0x4244}` was absent, so `is_wake_capable()` returned
false for CS42L44 unless firmware already set
`slave->prop.wake_capable`.
- After: match on Cirrus `mfg_id 0x01fa` + `part_id 0x4244`.
- Path: SoundWire enumeration / device-number allocation
(`intel_get_device_num_ida`, `generic_new_peripheral_assigned`), not
an error path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- Category: **hardware workaround / device ID in an existing quirk
table**
- Mechanism: Intel Lunar Lake-class wake requires a system-unique SDI
and IDA device numbers in a reserved range. Without the list entry,
CS42L44 is allocated a non-wake number, `program_sdi()` is skipped,
and jack IRQs while the bus is stopped are not handled.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: same pattern as CS42L43 (`0x4243`), CS42L45
(`0x4245`), CS42L49 (`0x4249`), CS42L43B (`0x2A30`/`0x2A3B`).
- Minimal: one array line; no API, locking, or structure change.
- Regression risk: very low. Extra list iteration is cheap; the new ID
only matches that part. Wrong SDI assignment would only affect that
exact codec, and the vendor authored the entry.
- Nearby gap (does not make this patch wrong):
`drivers/mfd/cs42l43-sdw.c` still has no `SDW_SLAVE_ENTRY` for
`0x4244`. DT only gained `cirrus,cs42l44` later (`d4c669890ed08`).
This commit is still the correct host-side quirk.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Table introduced in `e66f91a2d10b9` (2023-07-31, described as
`v6.5-rc1-6-ge66f91a2d10b9`): “add hybrid IDA-based device_number
allocation”.
- That commit states the quirk table is expected to grow for each new
headset codec because firmware does not provide wake capability.
- Line `0x4244` itself is this commit (`d08e4d9197396`, Charles Keepax,
2026-07-08).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Not applicable. The “bug” is an incomplete
quirk table, not a regression from a single earlier SHA.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same one-line additions: `fe600c8e2dc5d` (cs42l43),
`f87e5575a6bd1` (cs42l45), `b8f2d65fec19f` (cs42l49), `be6d8daaab654`
(cs42l43b), `4b8fc2b17272d` (CS47L47), `4e90368e8680d` (es9356).
Standalone, not `N/M`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Charles Keepax is a regular Cirrus SoundWire/ASoC contributor
and also authored the CS42L43B and CS42L49 wake-list entries. Vinod Koul
applied it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Depends only on `wake_capable_list` / `is_wake_capable()`,
present here since `e66f91a2d10b9`. Applies standalone. No new helper or
struct.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c d08e4d9197396`: `https://patch.msgid.link/20260708122948.15
02227-1-ckeepax@opensource.cirrus.com`
- `b4 dig -a`: v1 only; committed version is that v1
- Thread: submit (Keepax) + “Applied, thanks!” (Vinod Koul). No NAK, no
v2, no reviewer risk notes, no `Cc: stable` in-thread.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To `vkoul@kernel.org`; Cc Bard Liao, Pierre-Louis
Bossart, linux-sound, linux-kernel, Cirrus patches. Maintainer applied;
no extra Reviewed-by on this revision.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot. Vendor (Cirrus) patch. Later DT text:
“cs42l44 is a cost optimised variant of cs42l43b” (`d4c669890ed08`).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone 1/1. Related later: DT compatible only. MFD SoundWire
ID for `0x4244` is still missing in this tree.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable fetch returned 403. Web search found
`[PATCH AUTOSEL 6.19-6.12] ... add cs42l45 codec to wake_capable_list` —
same class of ID was auto-selected for stable. No evidence this CS42L44
patch was rejected for stable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `wake_capable_list[]` data only. Consumers: `is_wake_capable()`,
`intel_get_device_num_ida()`, `intel_put_device_num_ida()`,
`generic_new_peripheral_assigned()`.
**Step 5.2: TRACE CALLERS**
Record:
- `is_wake_capable()` is static; three call sites in this file (lines
135, 269, 283).
- `intel_get/put_device_num_ida` are `sdw_intel_ops.get_device_num` /
`put_device_num`.
- `generic_new_peripheral_assigned` is
`sdw_intel_ops.new_peripheral_assigned`.
- Context: Intel SoundWire enumeration / PM, not syscall-hot or IRQ
handler body.
**Step 5.3: TRACE CALLEES**
Record: `ida_alloc_range` / `ida_free` for wake devices;
`hw_ops->program_sdi()` when wake-capable.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: ACPI Intel SoundWire controller → peripheral enumeration →
device number → optional SDI programming. Reachable on Intel laptops
with this codec when audio clocks stop (idle/runtime PM). Not a
userspace-triggered memory-safety bug; it is a device-operation path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same Cirrus IDs already in the table (`0x4243`, `0x4245`,
`0x4249`, `0x2A30`, `0x2A3B`). `sdca_class.c` binds
`0x4245`/`0x4249`/`0x4747` but not `0x4244`. `cs42l43-sdw.c` binds
`0x4243` and `0x2A3B` only.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes, the Intel quirk table and lookup exist
(`drivers/soundwire/intel_auxdevice.c`). Without this ID, CS42L44 would
not be wake-capable here. `e66f91a2d10b9` is from 2023; the table is
long-lived. This commit is already in 7.3-rc1+, so the ID is present at
HEAD; the evaluation is whether that change belongs in this tree’s
stable stream, not whether 6.x is different.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply: insert `{0x01fa, 0x4244}` next to the other Cirrus
entries. No refactor needed on this tree.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This SHA is already an ancestor of HEAD. Sibling codec IDs are
already in the same table. No alternate CS42L44 wake fix.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/soundwire/` Intel master (`CONFIG_SOUNDWIRE_INTEL`).
**IMPORTANT** for Intel laptop audio, not core mm/VFS. Peripheral
relative to the whole kernel; standard for headset jack/wake.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Active (regular wake-list IDs, DMI quirks, cadence clock-stop
work). The table mechanism itself has been stable since 2023.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Intel SoundWire hosts with Cirrus CS42L44 (`mfg 0x01fa`, `part
0x4244`). No effect on other devices.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Jack insert/remove while the SoundWire bus is stopped (runtime
idle / clock stop). Common on laptops. Not a security trigger from
unprivileged syscalls.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Missed jack / wake events (headset not detected until something
else restarts the bus). **MEDIUM** functional hardware bug; not
oops/corruption. Covered by the hardware-quirk exception.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: restores jack-wake on CS42L44, same as sibling Cirrus codecs.
- Risk: very low (one static ID).
- Ratio: strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- One-line ID in an existing Intel SoundWire quirk table
- Real hardware: CS42L44 is a documented CS42L43B cost-down variant
(Cirrus + DT `cirrus,cs42l44`)
- Without it, jack events while the bus is stopped are dropped (by
design of `e66f91a2d10b9`)
- Same pattern already used for cs42l43/45/49/43b; cs42l45 was AUTOSEL’d
for stable
- Vendor author, SoundWire maintainer applied, v1 accepted
- Applies cleanly; no new API
AGAINST:
- Not a crash/UAF/security fix
- No `Reported-by` from end users
- MFD `cs42l43-sdw.c` still lacks `0x4244`, so codec bind on Intel SDW
is incomplete in this tree
- No in-thread `Cc: stable` (not a negative per rules)
UNRESOLVED:
- lore.kernel.org/stable search HTTP 403
- How many shipping Intel SKUs use CS42L44 (unverified; vendor patch is
the evidence)
The missing MFD ID is a separate gap. This patch only teaches the
**Intel master** to treat the part as wake-capable at enumeration, which
must happen before codec probe. That is exactly what this table is for.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one ID, established table,
maintainer applied
2. Fixes a real bug that affects users? **PASS** — missed jack/wake on
CS42L44
3. Important issue? **PASS** via hardware-quirk exception (broken jack
detect while bus stopped)
4. Small and contained? **PASS** — +1 line, one file
5. No new features or APIs? **PASS** — ID in existing quirk list, not a
new driver
6. Can apply to the local tree? **PASS** — `wake_capable_list` exists;
patch is a clean insert
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk / device ID addition to an existing driver**
(`wake_capable_list` in `intel_auxdevice.c`). Prompt: these are YES for
stable.
**Step 9.4: MAKE YOUR DECISION**
This tree has the Intel SoundWire master and the quirk table. Adding
CS42L44 is the same class of change as USB/PCI ID and codec quirks:
small, obviously correct, and required for real hardware. Benefit
outweighs risk.
---
## What the commit solves for this tree
On Intel SoundWire, device numbers for wake-capable codecs must be
assigned at enumeration from a reserved IDA range, and SDI must be
programmed. Firmware does not advertise wake capability, and the codec
driver has not probed yet, so the master uses `wake_capable_list`.
CS42L44 can generate jack IRQs while the bus is clock-stopped; without
`{0x01fa, 0x4244}` those events are lost. That is a real user-visible
headset-detect failure, not a new feature.
Risk is a single static table entry. No locking, alloc, or ABI change.
---
## Verification
- [Phase 1] `git show d08e4d9197396 --format=fuller`: tags as listed;
body is the two-line jack-event rationale
- [Phase 2] Diff: `+{0x01fa, 0x4244}` only in `wake_capable_list`
- [Phase 2] Read `intel_auxdevice.c`: `is_wake_capable()` used at lines
135, 269, 283
- [Phase 3] `git blame -L 53,77 drivers/soundwire/intel_auxdevice.c`:
table from `e66f91a2d10b9`; this ID from `d08e4d9197396`
- [Phase 3] `git show e66f91a2d10b9`: explains why the quirk table
exists and will grow
- [Phase 3] `git merge-base --is-ancestor d08e4d9197396 HEAD`: yes; not
an ancestor of `v7.2`; is in `v7.3-rc1`
- [Phase 3] No `Fixes:`; related one-liners listed above
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 lore thread; Vinod applied;
recipients include Liao, Bossart, linux-sound
- [Phase 4] WebSearch: AUTOSEL of the cs42l45 equivalent; CS42L44 thread
has no NAK
- [Phase 4] UNVERIFIED: stable@ lore (HTTP 403)
- [Phase 5] Callers confirmed by grep in
`drivers/soundwire/intel_auxdevice.c`
- [Phase 5] `cs42l43-sdw.c` id_table: `0x4243` and `0x2A3B` only — no
`0x4244` (verified)
- [Phase 6] `git describe HEAD` / `make kernelversion`: 7.3.0-rc4; file
and table present
- [Phase 6] `git show d4c669890ed08`: DT `cirrus,cs42l44` = cost-
optimised CS42L43B
- [Phase 8] Failure mode: missed jack/wake, not oops; quirk exception
applies
**YES**
drivers/soundwire/intel_auxdevice.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
index c0c8ffcecc6bf..347e06ad6edba 100644
--- a/drivers/soundwire/intel_auxdevice.c
+++ b/drivers/soundwire/intel_auxdevice.c
@@ -54,6 +54,7 @@ static struct wake_capable_part wake_capable_list[] = {
{0x01fa, 0x2A30},
{0x01fa, 0x2A3B},
{0x01fa, 0x4243},
+ {0x01fa, 0x4244},
{0x01fa, 0x4245},
{0x025d, 0x5682},
{0x025d, 0x700},
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] nvmet: zns: reject full zone report when buffer is too small
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (66 preceding siblings ...)
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.12] soundwire: intel_auxdevice: Add cs42l44 to wake_capable_list Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:15 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] ASoC: SOF: Intel: mtl: Power down DSP if it is left enabled in pre_fw_run() Sasha Levin
` (448 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Xixin Liu, Christoph Hellwig, Keith Busch, Sasha Levin, sagi, kch,
linux-nvme, linux-kernel
From: Xixin Liu <liuxixin@kylinos.cn>
[ Upstream commit 86985da12699360a2b20748c5a492ddd92db8c47 ]
Zone Management Receive uses the Partial Report (PR) bit in dword 13. On a
partial report (PR bit set), the host accepts an incomplete listing and
Number of Zones must not exceed the zone descriptors copied to the host
buffer. On a full report (PR bit clear), Number of Zones is the total
number of matching zones and every descriptor must fit in the buffer (ZNS
Command Set Specification Rev 1.2, section 3.4.2).
nvmet_bdev_zone_zmgmt_recv_work() already caps Number of Zones for partial
reports, but on a full report it may still succeed when the buffer only
holds part of the matching descriptors. Reject the command in that case.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111** (`pending-6.12`). The buggy Zone
Management Receive path is present here, and this is a small spec-
compliance fix that should be backported to this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
- Subsystem prefix: `nvmet: zns:`
- Action verb: **reject** (prevents an illegal success path)
- Claimed intent: fail a full (PR=0) zone report when the host buffer
cannot hold every matching descriptor
Record: [nvmet/zns] [reject] [fail full zone report when the data buffer
is too small]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
- Signed-off-by: Xixin Liu <liuxixin@kylinos.cn> (author)
- Reviewed-by: Christoph Hellwig <hch@lst.de> (NVMe/block maintainer)
- Signed-off-by: Keith Busch <kbusch@kernel.org> (NVMe maintainer;
applied the patch)
- No Fixes: tag (expected for this review pipeline)
- No Reported-by / Tested-by / Link / Cc: stable
- Ignore any pipeline-added Sasha Levin SOB / Upstream markers
Record: Author SOB + Hellwig Reviewed-by + Busch SOB. No syzbot, no user
report, no Fixes tag.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Zone Management Receive uses the Partial Report (PR) bit:
- PR=1 (partial): host accepts an incomplete listing; Number of Zones
must not exceed descriptors actually copied.
- PR=0 (full): Number of Zones is the total match count; every matching
descriptor must fit (ZNS Command Set Spec Rev 1.2 §3.4.2). If the
buffer is too small, the command must be aborted with Invalid Field in
Command.
`nvmet_bdev_zone_zmgmt_recv_work()` already caps Number of Zones for
PR=1, but for PR=0 it can still complete successfully when only some
matching descriptors were copied.
Record:
- Bug: full report succeeds with incomplete descriptors while Number of
Zones is the full match count
- Symptom: initiator sees SUCCESS plus a header that claims more zones
than were transferred
- Version info: none in the message; code dates to 2021
- Root cause: PR=0 path never checks `nr_zones > out_nr_zones`
Step 1.4: DETECT HIDDEN BUG FIXES
Not hidden. This is an explicit protocol-correctness fix: illegal
SUCCESS → INVALID_FIELD | DNR.
Record: [Not a disguised cleanup; it is a command-handling bug fix]
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
- File: `drivers/nvme/target/zns.c`
- Scope: ~10 insertions / 3 deletions in one function
- Function: `nvmet_bdev_zone_zmgmt_recv_work()`
- Classification: single-file surgical fix
Record: [zns.c, ~+10/-3] [nvmet_bdev_zone_zmgmt_recv_work] [surgical]
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Before (this tree, lines 301–309):
```301:309:drivers/nvme/target/zns.c
/*
- When partial bit is set nr_zones must indicate the number of zone
- descriptors actually transferred.
*/
if (req->cmd->zmr.pr)
rz_data.nr_zones = min(rz_data.nr_zones,
rz_data.out_nr_zones);
nr_zones = cpu_to_le64(rz_data.nr_zones);
status = nvmet_copy_to_sgl(req, 0, &nr_zones, sizeof(nr_zones));
```
After:
- PR=1: same cap as today
- PR=0 and `nr_zones > out_nr_zones`: set `error_loc` to `numd`, return
`NVME_SC_INVALID_FIELD | NVME_STATUS_DNR`, skip writing the header
- Otherwise: unchanged success path
The callback still copies only descriptors that fit (`if (rz->nr_zones <
rz->out_nr_zones)`), then increments `nr_zones` for every match. So
after `blkdev_report_zones()`, `nr_zones` is the match count and
`out_nr_zones` is buffer capacity. That comparison is exactly the
missing check.
Record: [PR=0 undersized buffer: SUCCESS + inflated nr_zones →
INVALID_FIELD | DNR]
Step 2.3: IDENTIFY THE BUG MECHANISM
Category: **logic / protocol correctness** (not UAF, leak, or race).
Mechanism: PR=0 must fail when the buffer cannot hold every matching
descriptor. The target currently reports SUCCESS and writes Number of
Zones = full match count while copying only `out_nr_zones` descriptors.
A host that iterates `report->nr_zones` entries then reads past its
buffer.
The status and `error_loc` match the existing too-small-header check in
`nvmet_bdev_validate_zone_mgmt_recv()` (lines 164–166).
Record: [Logic/spec] [PR=0 truncated full report incorrectly succeeds]
Step 2.4: ASSESS THE FIX QUALITY
Obviously correct against the spec and against the existing PR=1 cap.
Minimal. No API/data-structure change.
Regression risk is low:
- Linux kernel host always sets `c.zmr.pr = NVME_REPORT_ZONE_PARTIAL` in
`nvme_ns_report_zones()` — that path is unchanged
- PR=0 with an adequate buffer is unchanged
- Only PR=0 with a too-small buffer flips SUCCESS → error, which is the
specified behavior
- Failed commands already `goto out` in this function; `error_loc` /
`NVME_STATUS_DNR` are used throughout this file
Record: [High quality, surgical] [Low regression risk; only the illegal
success path changes]
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
`git blame -L 267,313 drivers/nvme/target/zns.c`: every line of this
function is from
`aaf2e048af2704` — `nvmet: add ZBD over ZNS backend support` (Chaitanya
Kulkarni, 2021-06-09)
`git merge-base --is-ancestor aaf2e048af2704 v6.12` succeeded. The bug
has been in this series from the start of 6.12 (and since ~v5.14).
Record: [Introduced by aaf2e048af2704, 2021] [Present in this 6.12 tree]
Step 3.2: FOLLOW THE FIXES: TAG
No Fixes: tag. The introducing commit is the original ZNS target
feature, not a later regression.
Record: [No Fixes tag] [Buggy code is the original 2021 implementation,
ancestor of HEAD]
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Recent `drivers/nvme/target/zns.c` history in this tree: identify NULL
deref, DNR rename, conv_zones_bitmap, etc. None already implement this
PR=0 rejection. Current source still has the old comment and the `if
(req->cmd->zmr.pr)` cap only.
Standalone 1/1 (cover letter on lore confirms a single patch).
Record: [No prior equivalent fix in this file] [Standalone; no series
prerequisites]
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Xixin Liu has other NVMe work in this tree (tcp/rdma), but this ZNS recv
check is not already here. Review weight comes from Hellwig + Busch, not
from the author being the subsystem maintainer.
Record: [Contributor, not nvmet maintainer] [Reviewed/applied by NVMe
maintainers]
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Diff uses `req->error_loc`, `offsetof(struct nvme_zone_mgmt_recv_cmd,
numd)`, `NVME_SC_INVALID_FIELD | NVME_STATUS_DNR`. All exist in this
tree (`NVME_STATUS_DNR` via `dd0b0a4a2c5d7`, already in 6.12). Context
in `zns.c` matches the pre-image exactly.
Record: [No missing helpers] [Applies standalone to this tree]
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
lore.kernel.org WebFetch returned 403. Thread recovered from the gnuweeb
mirror:
https://lore-kernel.gnuweeb.org/linux-
nvme/cover.1783579899.git.liuxixin@kylinos.cn/T/
- v1: 2026-07-09, nested `else { if (...) }`
- Hellwig: line too long; use `else if`
- v2: 2026-07-13, matches the candidate diff
- Hellwig: “Looks good” + Reviewed-by
- Busch: “Thanks, applied to nvme-7.3.”
- No NAK, no stable discussion, no security/crash report
- Author: “Tested on nvmet-tcp loopback with io-passthru.”
`b4 dig -c` was not used: the candidate SHA is not in this checkout.
Thread contents were verified from the archive instead.
Record: [v1→v2 style-only] [Hellwig RB, Busch applied] [No NAK / no Cc:
stable in review]
Step 4.2: CHECK WHO REVIEWED THE PATCH
Original To/Cc: linux-nvme, hch, sagi (Sagi Grimberg), kch (Chaitanya
Kulkarni). Right maintainers were on the thread.
Record: [Hellwig reviewed; Busch applied; Kulkarni/Grimberg CCed]
Step 4.3: SEARCH FOR THE BUG REPORT
No Reported-by, bugzilla, or syzbot. Same author also posted a host-side
defensive patch (`nvme: zns: cap zone report nr_zones by DMA buffer
size`) because hosts that trust Number of Zones can walk past the DMA
buffer. That is independent; this tree’s host `zns.c` has no
`max_in_buf` yet, and Linux host uses PR=1 anyway.
Record: [No end-user crash report] [Author also wrote a host-side bound
against inflated nr_zones]
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Cover is 0/1 + 1/1. Self-contained. Host cap patch is a separate
hardening change, not a prerequisite for the target rejection.
Record: [Standalone target fix] [Host companion not required here]
Step 4.5: CHECK STABLE MAILING LIST HISTORY
lore.kernel.org/stable search also 403. No evidence in the nvme thread
that stable was requested or rejected.
Record: [No stable-list discussion found] [UNVERIFIED: could not query
lore.kernel.org/stable directly]
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: [`nvmet_bdev_zone_zmgmt_recv_work`]
Step 5.2: TRACE CALLERS
- `nvmet_bdev_execute_zone_mgmt_recv()` queues that work
- Set as `req->execute` from `nvmet_bdev_zns_parse_io_cmd()` on
`nvme_cmd_zone_mgmt_recv`
- `nvmet_parse_io_cmd()` → `nvmet_bdev_zns_parse_io_cmd()` when
`req->ns->csi == NVME_CSI_ZNS` and `CONFIG_BLK_DEV_ZONED`
Record: [I/O path for ZNS namespaces on nvmet] [Triggered by Zone
Management Receive from an initiator]
Step 5.3: TRACE CALLEES
`nvmet_bdev_validate_zone_mgmt_recv`, `blkdev_report_zones` /
`nvmet_bdev_report_zone_cb`, `nvmet_copy_to_sgl`, `nvmet_req_complete`.
No new locks or allocations.
Record: [Existing report/copy/complete helpers only]
Step 5.4: FOLLOW THE CALL CHAIN
Reachable from NVMe-oF (TCP/RDMA/FC/loop) against a ZNS target
namespace. Userspace tools (`nvme zns report-zones`, libnvme, SPDK) can
send PR=0. Linux in-kernel host always uses PR=1, so it does not hit the
bug, but other initiators can.
Record: [Userspace/NVMe-oF reachable] [Linux kernel host does not use
PR=0]
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Only this one PR=0/PR=1 split in nvmet. Host always sets
`NVME_REPORT_ZONE_PARTIAL`. No sibling driver with the same missing
full-report check.
Record: [Single instance in nvmet ZNS]
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Yes. `make kernelversion` = 6.12.111; `git describe HEAD` =
`p-6.12-3-gc504cf0baa3d8`. Current `nvmet_bdev_zone_zmgmt_recv_work()`
still only caps PR=1. Introducer `aaf2e048af2704` is an ancestor of
v6.12 and of HEAD.
Record: [Bug exists at drivers/nvme/target/zns.c:305-306] [Since
aaf2e048af2704 / ~5.14]
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Pre-image matches this file exactly (`OLD FOUND` in a dry-run of the
hunk). `NVME_STATUS_DNR` and `numd` exist. No refactor in the way.
Record: [Expected clean apply]
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
`git log --grep` on this file found no “reject full zone report”. Host
`max_in_buf` is also absent. No equivalent fix.
Record: [Not already present]
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
`drivers/nvme/target/zns.c` — NVMe target ZNS backend, built as
`nvmet-$(CONFIG_BLK_DEV_ZONED)`.
Record: [nvmet ZNS] [IMPORTANT for NVMe-oF zoned exports; not core
mm/VFS]
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
nvmet is actively fixed in this 6.12 tree (TCP OOB, auth, RDMA leaks,
ZNS identify NULL deref). ZNS recv itself has been stable since 2021.
Record: [nvmet active; this function long-unchanged]
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Config-specific: `CONFIG_NVME_TARGET=y` and `CONFIG_BLK_DEV_ZONED=y`,
exporting a zoned bdev as a ZNS namespace. Initiators that send Zone
Management Receive with PR=0 and a buffer smaller than the matching
descriptor list.
Record: [Config-specific: nvmet + zoned bdev + PR=0 full report]
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Deterministic: PR=0 + `numd` too small for every matching zone. Not a
race. Linux kernel host does not trigger it (PR=1). Userspace and non-
Linux NVMe-oF initiators can. Needs access to the subsystem, not a
random unprivileged syscall on a machine that is not an NVMe target.
Record: [Deterministic protocol path] [Common for tools that request a
full report with a small buffer] [Not a local unprivileged syscall
unless nvmet is configured]
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Target kernel: no oops, leak, or deadlock — wrong SUCCESS instead of
Invalid Field.
Initiator: SUCCESS + Number of Zones = full match count + only a prefix
of descriptors transferred. A parser that trusts that count walks past
its buffer (userspace OOB / wrong zone map). Incomplete zone inventory
can then drive wrong zone management.
Record: [Incorrect SUCCESS / truncated full report] [Severity: MEDIUM —
protocol/data-integrity for zoned NVMe-oF, not a target oops]
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Benefit: spec-correct failure instead of a silently truncated zone map;
avoids initiator over-read and incomplete inventory. Small but real for
nvmet ZNS users.
Risk: ~10 lines, error path only, same status pattern already used in
this file. Linux in-kernel host path unchanged.
Record: [Benefit: medium for affected nvmet ZNS users] [Risk: very low]
[Favor backport]
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real, deterministic spec violation in command completion (ZNS 1.2
§3.4.2)
- SUCCESS with Number of Zones > descriptors transferred can make
initiators over-read or act on an incomplete zone map
- ~10-line surgical change, obviously correct
- Hellwig Reviewed-by, Busch applied; author tested nvmet-tcp loopback
- Buggy code has been in this 6.12 tree since the original ZNS target
code (2021)
- Applies cleanly; all symbols exist (`NVME_STATUS_DNR`, `numd`,
`error_loc`)
- No new API/feature
- Fits stable-kernel-rules “oh, that's not good” for storage protocol
results
AGAINST:
- Not a target oops/UAF/deadlock
- No syzbot or production Reported-by
- Niche: nvmet + zoned + PR=0
- Linux in-kernel host always uses PR=1
- No Cc: stable (not a negative under these review rules)
UNRESOLVED:
- Could not `b4 dig` a local SHA (commit not in this checkout)
- lore.kernel.org and git.kernel.org fetches were blocked; thread
verified via gnuweeb mirror
- Exact mainline SHA not confirmed locally
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — spec-aligned; Hellwig RB;
author tested loopback
2. Fixes a real bug that affects users? **PASS** — wrong SUCCESS on a
real NVMe-oF command
3. Important issue? **PASS** (MEDIUM) — not a kernel oops, but incorrect
zoned inventory / initiator over-read; “oh, that's not good” for a
storage protocol
4. Small and contained? **PASS** — one function, ~10 lines
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — pre-image matches 6.12.111
`zns.c`
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Not a device-ID, quirk, DT, build, or docs exception. It is a normal
small bugfix.
Step 9.4: MAKE YOUR DECISION
This 6.12 tree still has the original PR=0 hole. The fix is tiny,
maintainer-reviewed, and changes only the illegal success path. That is
appropriate for this stable tree.
Verification:
- [Phase 1] Tags: Xixin Liu SOB, Christoph Hellwig Reviewed-by, Keith
Busch SOB; no Fixes/Reported-by/Cc: stable
- [Phase 1] Body: PR=0 full report must fail when buffer cannot hold
every matching descriptor (ZNS 1.2 §3.4.2)
- [Phase 2] Diff: one hunk in `nvmet_bdev_zone_zmgmt_recv_work()`; PR=1
still capped; PR=0 adds `nr_zones > out_nr_zones` →
`NVME_SC_INVALID_FIELD | NVME_STATUS_DNR`
- [Phase 2] Callback already copies only `out_nr_zones` descriptors
while counting all matches — verified at
drivers/nvme/target/zns.c:227-246
- [Phase 3] `git blame`: function from aaf2e048af2704 (2021-06-09)
- [Phase 3] `git merge-base --is-ancestor aaf2e048af2704 HEAD` and `...
v6.12`: both true
- [Phase 3] No equivalent fix in `git log -- drivers/nvme/target/zns.c`
- [Phase 4] Thread: https://lore-kernel.gnuweeb.org/linux-
nvme/cover.1783579899.git.liuxixin@kylinos.cn/T/ — v1→v2 style only;
Hellwig RB; Busch applied to nvme-7.3
- [Phase 4] UNVERIFIED: b4 dig (SHA not in tree); lore.kernel.org HTTP
403
- [Phase 5] Callers: `nvmet_parse_io_cmd` →
`nvmet_bdev_zns_parse_io_cmd` → `nvmet_bdev_execute_zone_mgmt_recv`
(core.c:954-961, zns.c:315-318, 614-615)
- [Phase 5] Linux host uses `c.zmr.pr = NVME_REPORT_ZONE_PARTIAL`
(host/zns.c:197)
- [Phase 6] `make kernelversion` = 6.12.111; buggy `if
(req->cmd->zmr.pr)` still present; dry-run pre-image found;
`NVME_STATUS_DNR` and `numd` exist
- [Phase 7] Built only with `nvmet-$(CONFIG_BLK_DEV_ZONED)`
- [Phase 8] Failure mode: incorrect SUCCESS / truncated full report, not
a target crash
- UNVERIFIED: whether a later mainline follow-up changed this hunk after
nvme-7.3 apply
The problem is a spec-incorrect SUCCESS on a full zone report when the
host buffer is too small. That is a real command-handling bug in this
6.12 tree, the patch is small and already matches local code, and the
risk is limited to failing a command that was already returning
inconsistent data.
**YES**
drivers/nvme/target/zns.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/nvme/target/zns.c b/drivers/nvme/target/zns.c
index 95af4b67108c7..abf3435ca2900 100644
--- a/drivers/nvme/target/zns.c
+++ b/drivers/nvme/target/zns.c
@@ -299,11 +299,18 @@ static void nvmet_bdev_zone_zmgmt_recv_work(struct work_struct *w)
}
/*
- * When partial bit is set nr_zones must indicate the number of zone
- * descriptors actually transferred.
+ * Partial report (PR bit set): the host accepts an incomplete listing,
+ * so cap Number of Zones to the descriptors that fit in the buffer.
+ * Full report (PR bit clear): Number of Zones is the match count; fail
+ * if the buffer cannot hold every matching zone descriptor.
*/
- if (req->cmd->zmr.pr)
+ if (req->cmd->zmr.pr) {
rz_data.nr_zones = min(rz_data.nr_zones, rz_data.out_nr_zones);
+ } else if (rz_data.nr_zones > rz_data.out_nr_zones) {
+ req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd, numd);
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+ goto out;
+ }
nr_zones = cpu_to_le64(rz_data.nr_zones);
status = nvmet_copy_to_sgl(req, 0, &nr_zones, sizeof(nr_zones));
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ASoC: SOF: Intel: mtl: Power down DSP if it is left enabled in pre_fw_run()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (67 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] nvmet: zns: reject full zone report when buffer is too small Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] iommu/qcom: Publish pgtbl_ops before releasing init_mutex Sasha Levin
` (447 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Peter Ujfalusi, Bard Liao, Liam Girdwood, Mark Brown, Sasha Levin,
lgirdwood, daniel.baluta, perex, tiwai, sound-open-firmware,
linux-sound, linux-kernel
From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
[ Upstream commit 31fd7a0bbfa4b7e8aff11f278e817664c6a5f68b ]
It is expected that the DSP is in power down state when the firmware boot
is attempted.
If the DSP for any reason was left powered up then the DSP boot will
fail since the ROM boot sequence might not be able to run.
Make sure that the DSP is off before proceeding to boot it up.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Link: https://patch.msgid.link/20260730122857.5294-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Local tree is **6.1.188** (`pending-6.1`). The Meteor Lake SOF path this
patch targets is present here, so the question is whether the DSP-left-
on boot failure is worth a backport on this tree.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[ASoC / SOF Intel MTL] [Power down] Ensure DSP is off before
firmware boot in `pre_fw_run()`**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>`
(author; Intel SOF)
- `Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>` (Intel SOF)
- `Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>` (ASoC/SOF
maintainer)
- `Link: https://patch.msgid.link/20260730122857.5294-3-
peter.ujfalusi@linux.intel.com`
- `Signed-off-by: Mark Brown <broonie@kernel.org>` (ASoC maintainer,
applied)
- No `Fixes:`, no `Reported-by:`, no `Cc: stable` (absence is expected
for this review)
- Ignore any `Signed-off-by: Sasha Levin` / `[Upstream commit ...]`
pipeline markers
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Firmware boot is assumed to start with the DSP powered down.
If it is already up, the ROM boot sequence cannot run and DSP boot
fails.
- **Symptom:** SOF firmware boot failure → no audio on Meteor Lake.
- **Cover letter (series 0/2, verified via b4):** “We have seen reports
that for some undetermined reasons the DSP was on during system boot
and this caused firmware boot failure as the DSP cannot be booted up -
it was already in booted up state.”
- **Root cause:** DSP subsystem left powered (BIOS leftover, kexec,
failed prior boot, etc.); `pre_fw_run()` only powers up, never powers
down first.
- **Version info:** Applied by Mark Brown to `for-7.3` (next merge
window), not as a current-rc hotfix.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a disguised cleanup.** Explicit hardware recovery: if CPA
shows the DSP already on, power it down before the normal power-up
sequence. This is a real functional fix.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `sound/soc/sof/intel/mtl.c` only
- ~23 lines added, 0 removed
- New: `mtl_dsp_is_enabled()`
- Modified: `mtl_dsp_pre_fw_run()` — extra check at the start
- **Scope:** single-file, surgical
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `mtl_dsp_pre_fw_run()` always sets SPA to power the DSP
subsystem on, waits, then powers the gated DSP domain. No check of
current power state.
- **After:** Read `MTL_HFDSSCS`; if `MTL_HFDSSCS_CPA_MASK` is set, call
existing `mtl_power_down_dsp()`. On failure, `dev_warn` and continue.
Then the existing power-up sequence runs.
- **Path:** firmware boot (`snd_sof_run_firmware()`), probe and resume.
The new code runs only when the DSP is already enabled.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** hardware workaround / logic correctness (wrong assumed
power state)
- **Mechanism:** ROM boot needs a cold/off DSP. CPA=1 means the
subsystem is already on; setting SPA again does not run ROM init.
Powering down first restores a clean boot state.
- Same idea as SKL’s existing `hda_dsp_core_is_enabled()` handling in
`hda-loader-skl.c` (already in this tree).
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Quality:** Obviously correct. Uses existing `mtl_power_down_dsp()`
and the same CPA bit already used for power-up poll.
- **Minimal:** one helper + one guarded call; normal path unchanged.
- **Regression risk:** Low. Clean suspend already calls
`power_down_dsp()` (`hda_suspend()`), so IMR/resume should still see
CPA=0. The new path only fires on the abnormal “already on” case.
Power-down failure is warn-and-continue, not a hard fail.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- `mtl_dsp_pre_fw_run()` introduced in `064520e8aeaa2` (“ASoC: SOF:
Intel: Add support for MeteorLake (MTL)”, Bard Liao, 2022-06-15) —
**in this 6.1 tree**.
- `mtl_power_down_dsp()` added in `2090cb9bf5747` (2022-09-23) — **also
in this tree** (`git merge-base --is-ancestor` confirmed).
- Buggy “power up without checking current state” has been here for the
whole 6.1 lifetime of MTL.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Bug is the original MTL `pre_fw_run()` design,
not a later regression.
**Step 3.3: CHECK FILE HISTORY**
Record: Recent local history is MTL bring-up/PM (`064520e8aeaa2`,
`2090cb9bf5747`, `6ae87bab269b3`, timeout/dump tweaks). No existing
“power down if already on” logic. Standalone vs CAVS: this is patch
**2/2**; patch 1/2 is `hda.c` for older CAVS. MTL overrides
`.pre_fw_run` with `mtl_dsp_pre_fw_run`, so **this commit does not
depend on 1/2**.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Peter Ujfalusi is an Intel SOF regular. Reviewers are Intel SOF
(Bard Liao) and Liam Girdwood. High confidence in the hardware
diagnosis.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Needs `mtl_power_down_dsp()`, `MTL_HFDSSCS`, `MTL_HFDSSCS_CPA_MASK` —
all present.
- Upstream context has later PTL/ACE 2.0 register selection
(`PTL_HFPWRCTL2`, `SOF_INTEL_ACE_2_0`). **Those are context only, not
this change.** 6.1 `pre_fw_run()` is the original MTL-only version.
- In 6.1 `mtl_power_down_dsp()` is `static` and defined **after**
`mtl_dsp_pre_fw_run()` (line 401 vs 240). Upstream later made it a
header prototype. Backport needs a **static forward declaration** (or
a reorder). That is a trivial, mechanical adjustment, not a missing
feature.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 31fd7a0bbfa4` (hash from Mark Brown’s apply mail) matched
patch-id.
- Thread: https://patch.msgid.link/20260730122857.5294-3-
peter.ujfalusi@linux.intel.com
- Cover: `[PATCH 0/2] ASoC: SOF: Intel: hda/mtl: Handle powered on DSP
on boot`
- Full thread saved via `b4 mbox` (4 messages): cover, 1/2 hda, 2/2 mtl,
Mark Brown apply.
- **v1 only** (`b4 dig -a`); no v2/v3.
- **No NAKs.** Applied to `https://git.kernel.org/broonie/sound for-7.3`
as `31fd7a0bbfa4`.
- No reviewer `Cc: stable` in the thread.
**Step 4.2: CHECK WHO REVIEWED**
Record (`b4 dig -w`): To/Cc were Liam Girdwood, Mark Brown, linux-sound,
Kai Vehmanen, Bard Liao, Pierre-Louis Bossart. Right maintainers.
Reviewed-by from Bard Liao and Liam Girdwood.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No public bugzilla/syzbot link. Evidence is the cover letter:
Intel has reports of DSP-on-at-boot causing firmware boot failure.
Severity from reporters: **audio DSP does not boot**. User count:
unspecified (“reports”), not a single anecdotal one-off in the message,
but not named either.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Series is 2 independent platform hooks (hda CAVS vs mtl ACE).
This MTL patch is self-contained. No later follow-up found in the
thread.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable WebFetch returned 403. Web search found
no stable-list discussion of this subject. **UNVERIFIED:** no evidence
it was requested or rejected for stable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `mtl_dsp_is_enabled()` (new), `mtl_dsp_pre_fw_run()` (modified),
`mtl_power_down_dsp()` (callee, unchanged).
**Step 5.2: TRACE CALLERS**
Record:
- `sof_mtl_ops.pre_fw_run = mtl_dsp_pre_fw_run` (`sof_mtl_ops_init`)
- `snd_sof_dsp_pre_fw_run()` → `snd_sof_run_firmware()`
(`sound/soc/sof/loader.c`)
- `snd_sof_run_firmware()` from probe (`sound/soc/sof/core.c`) and
resume (`sound/soc/sof/pm.c`)
**Step 5.3: TRACE CALLEES**
Record: `snd_sof_dsp_read()` (CPA), `mtl_power_down_dsp()` →
`mtl_dsp_core_power_down()` then clear SPA and poll CPA=0. Same sequence
already used on suspend/remove.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Probe of `sof-audio-pci-intel-mtl` (PCI `8086:7e28`) → load
firmware → `pre_fw_run` → ROM boot. **Reachable on every MTL SOF boot**,
not a debug-only path. Unprivileged users do not trigger it directly; it
runs at device probe/resume.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: SKL loader already handles “core already enabled” (`hda-loader-
skl.c`). CAVS sibling is series 1/2. MTL/ACE had a gap this commit
fills.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `sound/soc/sof/intel/mtl.c` `mtl_dsp_pre_fw_run()`
(from ~line 240) powers on with no prior CPA check. Introduced with MTL
in v6.1 (`064520e8aeaa2`). PCI ID and `CONFIG_SND_SOC_SOF_METEORLAKE`
exist. Local `make kernelversion`: **6.1.188**.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Minor conflicts, not rework.**
- Upstream hunk context includes later `mtl_enable_interrupts(..., bool
enable)`, `EXPORT_SYMBOL_NS`, PTL `dsppwrctl`/`chip->hw_ip_version` —
**not in 6.1**.
- Logical change still maps 1:1 onto 6.1 `pre_fw_run()`.
- Need a forward declaration of static `mtl_power_down_dsp()`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No local commit with this subject or “power down if left
enabled” on `mtl.c`. Not already fixed.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **ASoC SOF Intel Meteor Lake** (`sound/soc/sof/intel/mtl.c`).
**IMPORTANT** for MTL laptops/desktops using SOF (not core mm/net).
Peripheral relative to the whole kernel, but this is the Intel audio DSP
path for that generation.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: MTL was added during 6.1 development and then mostly stable on
this branch (timeouts, dumps, PM ops). Mature for 6.1, not a brand-new
post-branch subsystem.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific** — `CONFIG_SND_SOC_SOF_METEORLAKE`, PCI
`8086:7e28`. 6.1 LTS users on Meteor Lake (e.g. Debian bookworm-class
kernels on Core Ultra hardware).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: DSP already powered when `pre_fw_run()` runs (BIOS, kexec,
leftover from a failed boot). Not every boot. Not userspace-triggerable
as a security issue. Intel reports it on **system boot**.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: SOF firmware boot failure → **no audio**. Not a
panic/UAF/corruption. **HIGH for affected hardware** (device does not
work), **MEDIUM** in whole-tree terms.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** MTL machines that otherwise fail DSP boot get working
audio. Matches the hardware-quirk exception.
- **Risk:** Low — ~20 lines, gated on CPA, uses existing power-down,
warn-and-continue on failure, suspend already powers down so IMR
resume should be unaffected.
- **Ratio:** Favorable for this tree.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real, reported firmware-boot failure when DSP is already on
- User-visible: no audio
- Small, obviously correct, Intel-reviewed
- Buggy code and `mtl_power_down_dsp()` both exist in 6.1
- Hardware workaround class (explicitly stable-appropriate)
- Standalone from series 1/2
- Normal boot/resume unchanged
**AGAINST:**
- Not a crash/security/corruption/deadlock
- Trigger is uncommon / “undetermined”
- Applied to for-7.3, not sent as -rc
- Needs a small backport (context + forward declaration)
**UNRESOLVED:**
- Stable list discussion (lore/stable 403)
- Exact BIOS/platforms in the unnamed reports
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — Intel review; uses existing
power-down + CPA
2. Fixes a real bug that affects users? **PASS** — reported DSP-on-at-
boot, firmware boot fail
3. Important issue? **PASS** — audio device fails to initialize
(hardware-workaround class)
4. Small and contained? **PASS** — one file, ~23 lines
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — logic applies; minor
context/prototype adaptation
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk/workaround** — force a known-good DSP power
state before ROM boot, analogous to USB/PCI reset-on-init quirks.
**Step 9.4: DECISION**
This is a small recovery for a real MTL SOF boot failure that exists in
6.1. The bug is “DSP already on → firmware never boots,” not a
theoretical cleanup. Risk is low because the new code only runs when CPA
is already set, and that path already exists for suspend/remove. It
should be backported to this tree.
---
### What the commit solves for stable users
On Meteor Lake, SOF expects the DSP subsystem off before ROM boot. If it
is already on, `pre_fw_run()` still only sets SPA; ROM init does not run
and probe/resume fails with no audio. The fix reads CPA and, if set,
calls the existing `mtl_power_down_dsp()` so the following power-up is a
clean boot.
### Stable rules / risk
Meets the rules: real bug, small, no new API, hardware workaround.
Benefit is working audio on affected MTL systems; regression risk is
low.
### Concerns
Literal `git am` will not apply (later PTL/`bool enable` context). A 6.1
backport is the same helper + call, plus a static forward declaration of
`mtl_power_down_dsp()`. Series 1/2 (`hda.c`) is not required for this
MTL change.
---
### Verification
- **[Phase 1]** Parsed tags from the provided message and the b4 mbox:
author Peter Ujfalusi; Reviewed-by Bard Liao, Liam Girdwood; applied
by Mark Brown; no Fixes/Reported-by/Cc: stable
- **[Phase 1]** Cover letter (mbox): Intel reports of DSP-on-at-boot
causing firmware boot failure
- **[Phase 2]** Diff: +23 lines in `mtl.c`; `mtl_dsp_is_enabled()` +
guarded `mtl_power_down_dsp()` in `mtl_dsp_pre_fw_run()`
- **[Phase 3]** `git describe HEAD` / `make kernelversion`: p-6.1-12 /
**6.1.188**
- **[Phase 3]** `git merge-base --is-ancestor 064520e8aeaa2 HEAD`: MTL
support present
- **[Phase 3]** `git merge-base --is-ancestor 2090cb9bf5747 HEAD`:
`mtl_power_down_dsp` present
- **[Phase 3]** `git blame -L 240,284 sound/soc/sof/intel/mtl.c`:
pre_fw_run still original 064520e8aeaa2; no CPA-down check
- **[Phase 3]** Confirmed `MTL_HFDSSCS` / `MTL_HFDSSCS_CPA_MASK` in
`mtl.h`
- **[Phase 3]** Function order: `mtl_dsp_pre_fw_run` @240,
`mtl_power_down_dsp` @401 (forward decl needed)
- **[Phase 4]** `b4 mbox` of 20260730122857.5294-3: cover + 1/2 + 2/2 +
apply; no NAK
- **[Phase 4]** `b4 dig -c 31fd7a0bbfa4`: lore match; v1 only; applied
to for-7.3 as 31fd7a0bbfa4
- **[Phase 4]** `b4 dig -w`: maintainers CC’d
- **[Phase 4]** lore.kernel.org WebFetch: 403
- **[Phase 5]** Callers: `snd_sof_run_firmware` ← probe (`core.c`) and
resume (`pm.c`)
- **[Phase 5]** `hda_suspend()` already calls `chip->power_down_dsp()` —
clean resume should have CPA=0
- **[Phase 5]** SKL already has similar “if core enabled” handling in
`hda-loader-skl.c`
- **[Phase 6]** `pci-mtl.c` PCI ID 8086:7e28;
`CONFIG_SND_SOC_SOF_METEORLAKE` in Kconfig
- **[Phase 6]** MTL overrides `.pre_fw_run`; series 1/2 not a dependency
- **[Phase 8]** Failure: SOF firmware boot fail / no audio, not oops
- **UNVERIFIED:** stable@ discussion (HTTP 403); named
reporters/machines
**YES**
sound/soc/sof/intel/mtl.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c
index 2242c96bfa519..f119e0e0651a2 100644
--- a/sound/soc/sof/intel/mtl.c
+++ b/sound/soc/sof/intel/mtl.c
@@ -236,6 +236,17 @@ int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable)
}
EXPORT_SYMBOL_NS(mtl_enable_interrupts, "SND_SOC_SOF_INTEL_MTL");
+static bool mtl_dsp_is_enabled(struct snd_sof_dev *sdev)
+{
+ int val;
+
+ val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS);
+ if (val & MTL_HFDSSCS_CPA_MASK)
+ return true;
+
+ return false;
+}
+
/* pre fw run operations */
static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
{
@@ -249,6 +260,18 @@ static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
u32 dsppwrsts;
const struct sof_intel_dsp_desc *chip;
+ /* Power down the DSP if it is left enabled to ensure clean boot state */
+ if (mtl_dsp_is_enabled(sdev)) {
+ dev_dbg(sdev->dev, "powering down DSP first\n");
+
+ ret = mtl_power_down_dsp(sdev);
+ if (ret < 0) {
+ dev_warn(sdev->dev,
+ "%s: failed to power down already-enabled DSP\n", __func__);
+ /* Continue anyway to attempt recovery */
+ }
+ }
+
chip = get_chip_info(sdev->pdata);
if (chip->hw_ip_version > SOF_INTEL_ACE_2_0) {
dsppwrctl = PTL_HFPWRCTL2;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] iommu/qcom: Publish pgtbl_ops before releasing init_mutex
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (68 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] ASoC: SOF: Intel: mtl: Power down DSP if it is left enabled in pre_fw_run() Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: move GPIO IRQ setup into request_resources Sasha Levin
` (446 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Mukesh Ojha, Konrad Dybcio, Will Deacon, Sasha Levin, robin.clark,
joro, iommu, linux-arm-msm, linux-arm-kernel, linux-kernel
From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
[ Upstream commit a05b67cd45ad09a19f41b2d37255da714512e0ca ]
qcom_domain->pgtbl_ops was assigned after mutex_unlock(). Another thread
calling qcom_iommu_init_domain() would see qcom_domain->iommu already set
(domain fully initialized) and skip re-initialization under the mutex.
If it then called qcom_iommu_map() before the first thread set pgtbl_ops,
it would observe a NULL ops pointer and return -ENODEV for valid mappings.
Move the assignment to before mutex_unlock() so that once the mutex is
released the domain is fully visible to concurrent operations.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3-rc4** (mainline). The driver is present, the
race is real, and the fix is a five-line lock-ordering correction. Below
is the full nine-phase review.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[iommu/qcom] [Publish] Publish pgtbl_ops before releasing
init_mutex`
Subsystem: Qualcomm IOMMU (`drivers/iommu/arm/arm-smmu/qcom_iommu.c`).
Verb “Publish … before” is a visibility/ordering fix (equivalent to
“ensure” / “prevent”).
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>`
- `Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>` (author)
- `Signed-off-by: Will Deacon <will@kernel.org>` (IOMMU/SMMU maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Link:`, or `Cc: stable`
(absence expected; not a negative)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `qcom_domain->pgtbl_ops` was stored after
`mutex_unlock(&init_mutex)`.
- **Symptom:** A concurrent `qcom_iommu_init_domain()` sees
`qcom_domain->iommu` already set, skips init, then `qcom_iommu_map()`
reads a NULL ops pointer and returns `-ENODEV` for valid mappings.
- **Root cause:** The “domain initialized” flag (`iommu`) is published
under the mutex; page-table ops are published after the mutex is
dropped, so the domain is only half-visible.
- **Version info:** None in the message. Blame shows the unlock-then-
assign pattern dates to the original driver (2017).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. Explicit race with a concrete failure (`-ENODEV`
on map). Not cleanup/refactor.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/iommu/arm/arm-smmu/qcom_iommu.c` — 2 insertions, 3
deletions
- Function: `qcom_iommu_init_domain()`
- Scope: single-file surgical reorder of three statements
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
**Before:** program context banks → `mutex_unlock(init_mutex)` →
`pgtbl_ops = …` → `return 0`.
**After:** program context banks → `pgtbl_ops = …` →
`mutex_unlock(init_mutex)` → `return 0`.
Error paths (`out_clear_iommu` / `out_unlock`) are unchanged. This is
the success-path publication of domain state.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Synchronization / race]**.
`qcom_domain->iommu` is set near the start of init (under the mutex) and
is the “already initialized” flag:
```227:229:drivers/iommu/arm/arm-smmu/qcom_iommu.c
mutex_lock(&qcom_domain->init_mutex);
if (qcom_domain->iommu)
goto out_unlock;
```
`qcom_iommu_map()` does not take `init_mutex`; it only checks
`pgtbl_ops`:
```436:439:drivers/iommu/arm/arm-smmu/qcom_iommu.c
struct io_pgtable_ops *ops = qcom_domain->pgtbl_ops;
if (!ops)
return -ENODEV;
```
Unlocking before the store lets another attach skip init and then map
with a NULL ops pointer. The fix publishes ops while still holding the
mutex so that once waiters proceed, the domain is fully usable.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct publish-under-lock. Minimal. No new locks,
APIs, or control flow besides statement order. Regression risk is very
low: the assignment is a plain pointer store of a fully constructed
object; holding the mutex a few extra instructions does not create
deadlock (map/unmap use `pgtbl_lock`, not `init_mutex`).
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: Unlock-then-assign was introduced in `0ae349a0f33fb`
(“iommu/qcom: Add qcom_iommu”, Rob Clark, 2017-08-09), first in
**v4.14-rc1**. The bug is ~9 years old in this driver, not a recent
regression.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Buggy code is the original 2017 driver, which
is an ancestor of this tree.
**Step 3.3: CHECK FILE HISTORY**
Record: Same-day series from Mukesh Ojha (applied 2026-07-22 by Will
Deacon):
- `3c748a5554f96` — leak of `pgtbl_ops` on error (patch 4/6)
- `a05b67cd45ad0` — this commit (patch 5/6)
- `cb776a03a5342` — clocks before ctx probe (patch 6/6)
This patch only reorders unlock vs assignment. It does **not** depend on
the leak fix.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Mukesh Ojha (Qualcomm) submitted a “Misc Fixes” series for the
legacy qcom_iommu driver. Not the IOMMU subsystem maintainer; Will
Deacon applied it. Konrad Dybcio (Qualcomm) reviewed.
**Step 3.5: DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. v2 series is 6 patches; this one has no code
dependency on the others. Can apply alone.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore (from `b4 dig -c a05b67cd45ad0`): https://patch.msgid.link/202607
17144608.3216274-6-mukesh.ojha@oss.qualcomm.com
- **v1:** `[PATCH 5/8]` 2026-06-23 — https://patch.msgid.link/2026062312
2034.1166295-6-mukesh.ojha@oss.qualcomm.com
- **v2:** `[PATCH v2 5/6]` 2026-07-17 (applied version; same diff as v1
for this patch)
- Konrad on v1: `Reviewed-by` plus a non-blocking note that a
`guard(mutex)` wrapper would also work. No NAK.
- Will Deacon applied the whole v2 series to `iommu (arm/smmu/updates)`
on 2026-07-22. No stable nomination, no risk flags.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): Mukesh Ojha, Rob Clark, Will Deacon, Joerg Roedel,
Alex Williamson, Robin Murphy, Konrad Dybcio; lists
`iommu@lists.linux.dev`, `linux-arm-msm`, `linux-arm-kernel`.
Appropriate maintainers were on Cc. Konrad reviewed; Will applied.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No `Reported-by`, syzbot, or bugzilla. Author analysis only.
UNVERIFIED whether anyone hit this in the field.
**Step 4.4: RELATED PATCHES AND SERIES**
Record: Part of “iommu/qcom: Misc Fixes”. Other patches (fault-log
polarity, pm_runtime, leak, clocks) are independent. v1 patches 6/8 and
8/8 were dropped after review; this patch was unchanged.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search for `pgtbl_ops qcom` did not show
this patch. Hits were unrelated (`arm-smmu-qcom` power-up). No evidence
it was rejected for stable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `qcom_iommu_init_domain()` (modified). Related:
`qcom_iommu_attach_dev()`, `qcom_iommu_map()`, `qcom_iommu_unmap()`,
`qcom_iommu_iova_to_phys()`.
**Step 5.2: TRACE CALLERS**
Record:
- `qcom_iommu_init_domain()` is only called from
`qcom_iommu_attach_dev()`.
- `attach_dev` is the IOMMU `.attach_dev` op
(`qcom_iommu_ops.default_domain_ops`).
- Core path: `__iommu_attach_device()` → `domain->ops->attach_dev()`.
- This driver `select ARM_DMA_USE_IOMMU`. `arm_iommu_attach_device()`
documents that more than one client may share a mapping, and calls
`iommu_attach_device()`. Parallel probe of two devices sharing a
mapping is a realistic concurrent `init_domain` on the same
`qcom_domain`. Group mutex serializes attach **within** a group;
`generic_device_group` means one device per group, so two devices are
two groups and are **not** serialized against each other.
**Step 5.3: TRACE CALLEES**
Record: `alloc_io_pgtable_ops()`, `qcom_scm_restore_sec_cfg()`, context-
bank MMIO, `mutex_lock/unlock`. SCM and register programming make the
critical section long; waiters pile up on `init_mutex` and then race the
post-unlock store.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable from device probe / DMA attach on Qualcomm “B family”
SMMU platforms (MSM8916/8937/8939/8953/8976, etc.). Not a syscall fuzzer
path; it is a normal boot/probe path. Userspace-triggered concurrent
attach is also possible via the ARM DMA mapping API / VFIO-style attach
of separate groups to one domain.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: `init_mutex` comment is “Protects iommu pointer” — the original
code treated `iommu` as the publication point and left `pgtbl_ops`
outside the lock. No sibling qcom function has the same bug.
`map`/`unmap`/`iova_to_phys` all NULL-check `pgtbl_ops` and return
`-ENODEV`/0 rather than crashing — so the race fails mappings instead of
oopsing.
semcode MCP: not available; used git grep and reads.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Tree: `v7.3-rc4-27-gf0100363d8c37`, `make kernelversion` =
**7.3.0-rc4**.
- File exists at `drivers/iommu/arm/arm-smmu/qcom_iommu.c`.
- `git merge-base --is-ancestor a05b67cd45ad0 HEAD` succeeds: this
commit is already in this checkout (landed as
`v7.2-rc2-7-ga05b67cd45ad0`).
- Pre-fix code existed here from v4.14 until that commit. The race is in
this driver’s design, not in code added after this tree branched.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Five-line reorder around a pattern present since 2017. File
moved in `e86d1aa8b60f7` (v5.8) from `drivers/iommu/qcom_iommu.c`; this
tree already uses the new path. Expected apply: **clean**. No
conflicting churn around the unlock.
**Step 6.3: RELATED FIXES ALREADY HERE**
Record: The leak fix `3c748a5554f96` is also here and is independent. No
alternate fix for this race.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: `[iommu / Qualcomm legacy SMMU] [IMPORTANT]`
Not mm/core, but IOMMU DMA for a family of Qualcomm SoCs still in DT
(phones, Dragonboard-class boards, embedded). Mapping failures break DMA
for those devices.
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Legacy driver (“Misc Fixes” cover letter). Recent Qualcomm
fixes; not a new subsystem. Mature code, long-present bug.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: **driver-specific / config-specific** — `CONFIG_QCOM_IOMMU` on
`ARCH_QCOM` (MSM8916, MSM8937, MSM8939, MSM8953, MSM8976, …). Not
universal.
**Step 8.2: TRIGGER CONDITIONS**
Record: Two threads attaching the same `qcom_iommu_domain` (shared ARM
DMA mapping, or two groups attached to one domain). After the first
drops `init_mutex` and before it stores `pgtbl_ops`, the second skips
init and maps. Window is a few instructions, but **preemption after
unlock** makes it realistic; SCM-held init also means waiters are ready
to run immediately. Not triggerable by an unprivileged syscall alone in
the usual case; it is a probe/attach race. No field `Reported-by`
(UNVERIFIED in production).
**Step 8.3: FAILURE MODE SEVERITY**
Record: **Failed IOMMU map (`-ENODEV`) for valid mappings** → DMA setup
failure / device non-functional. Not a KASAN UAF or panic (`map` NULL-
checks). **Severity: HIGH** (device DMA broken), not CRITICAL (no
oops/corruption).
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit:** Prevents a real attach/map race on Qualcomm IOMMU;
devices keep working under concurrent attach.
- **Risk:** Very low (3-statement reorder, no API/locking change).
- **Ratio:** Favorable.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real race: initialized flag published under lock, ops pointer
published after unlock.
- User-visible failure: valid maps return `-ENODEV` (DMA/device
failure).
- Bug in the driver since v4.14; this tree’s driver still has that
design.
- 5-line, obviously correct publish-under-lock.
- Reviewed by Konrad Dybcio; applied by Will Deacon.
- Self-contained; not a new feature.
- Used on real Qualcomm SoCs that still ship on LTS-class kernels.
**AGAINST:**
- No `Reported-by` / syzbot / crash log.
- Window is small; needs concurrent attach to the **same** domain.
- Failure is `-ENODEV`, not oops/UAF/corruption.
- Cover letter calls the series “Misc Fixes”; nobody Cc’d stable.
- Peripheral vs core (legacy qcom_iommu, not arm-smmu-v3).
**UNRESOLVED:**
- No confirmed production hit.
- lore.kernel.org HTML fetch returned 403; discussion recovered via `b4
dig`/`b4 mbox`.
- How often qcom platforms share one `dma_iommu_mapping` across devices
is not fully quantified; the ARM DMA API and `init_mutex` exist
specifically for that case.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — reorder is locally
checkable; Konrad R-b; Will applied; in mainline since v7.2-rc2.
2. Fixes a real bug that affects users? **PASS** — concurrent attach can
fail valid DMA maps.
3. Important issue? **PASS** — DMA map failure can take devices out; not
a panic, but not cosmetic.
4. Small and contained? **PASS** — 5 lines, one function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — same file/function; already
the current code here.
**Step 9.3: EXCEPTION CATEGORIES**
Record: None (not a device-ID/quirk/DT/build/doc exception). It is a
normal small race fix.
**Step 9.4: DECISION**
This tree is **7.3-rc4**. The Qualcomm IOMMU driver is here, and the
race is in the original 2017 init/map split, not in later architecture.
The patch is a correct, tiny publication-order fix: once `init_mutex` is
dropped, `pgtbl_ops` must already be visible so a concurrent attach
cannot skip init and then fail `qcom_iommu_map()`.
It meets stable rules: real bug, user-visible DMA failure, surgical
change, no new API, no prerequisites. Benefit outweighs the tiny race
window and lack of a field report.
---
## Verification
- [Phase 1] Parsed tags: Reviewed-by Konrad Dybcio; SOB Mukesh Ojha +
Will Deacon; no Fixes/Reported-by/Cc-stable
- [Phase 2] Diff: 2+/3- in `qcom_iommu_init_domain()`; move `pgtbl_ops`
store before `mutex_unlock`
- [Phase 2] Confirmed `map()` NULL-checks ops and returns `-ENODEV`;
`init_domain` early-outs on `qcom_domain->iommu`
- [Phase 3] `git blame`: unlock-then-assign from `0ae349a0f33fb`
(v4.14-rc1, Rob Clark)
- [Phase 3] No Fixes tag; leak fix `3c748a5554f96` is independent
- [Phase 3] `git merge-base --is-ancestor a05b67cd45ad0 HEAD` → yes
(already in this 7.3-rc4 checkout)
- [Phase 3] `git describe a05b67cd45ad0` → `v7.2-rc2-7-ga05b67cd45ad0`
- [Phase 4] `b4 dig -c a05b67cd45ad0`: v2 5/6 at
patch.msgid.link/20260717144608.3216274-6-…
- [Phase 4] `b4 dig -a`: v1 5/8 (2026-06-23) → v2 5/6 (2026-07-17); this
hunk unchanged
- [Phase 4] `b4 dig -w`: iommu maintainers + linux-arm-msm Cc’d
- [Phase 4] Konrad v1 review: R-b; optional `guard(mutex)` suggestion
only; Will applied v2
- [Phase 4] lore.kernel.org WebFetch 403; used b4 mbox instead
- [Phase 4] stable@ search: this commit not discussed; unrelated arm-
smmu-qcom hits
- [Phase 5] Callers: only `qcom_iommu_attach_dev` ← IOMMU `.attach_dev`
← `__iommu_attach_device`
- [Phase 5] `ARM_DMA_USE_IOMMU` / `arm_iommu_attach_device()` allows
shared mappings across devices
- [Phase 5] semcode unavailable; used git grep + file reads
- [Phase 6] `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion` = 7.3.0-rc4
- [Phase 6] Current file already has assignment before unlock (this
commit)
- [Phase 7] DT: msm8916/8937/8939/8953/8976 use `qcom,msm-iommu-v1/v2`
- [Phase 8] Failure: `-ENODEV` on valid map, severity HIGH; not oops
- UNVERIFIED: production reproduction; exact share-mapping frequency on
qcom boards
The fix is small, surgical, and meets the stable criteria for this
tree’s Qualcomm IOMMU driver.
**YES**
drivers/iommu/arm/arm-smmu/qcom_iommu.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index 792585321bd11..1a046122fca0d 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -306,13 +306,12 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
ctx->domain = domain;
}
- mutex_unlock(&qcom_domain->init_mutex);
-
/* Publish page table ops for map/unmap */
qcom_domain->pgtbl_ops = pgtbl_ops;
- return 0;
+ mutex_unlock(&qcom_domain->init_mutex);
+ return 0;
out_clear_iommu:
qcom_domain->iommu = NULL;
out_unlock:
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: move GPIO IRQ setup into request_resources
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (69 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] iommu/qcom: Publish pgtbl_ops before releasing init_mutex Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] hfs: validate catalog CNIDs before instantiating inodes Sasha Levin
` (445 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Tomer Maimon, Linus Walleij, Sasha Levin, andrew, avifishman70,
tali.perry1, openbmc, linux-gpio, linux-kernel
From: Tomer Maimon <tmaimon77@gmail.com>
[ Upstream commit b8edfde12e355030e708394c0fa11632559c7ac5 ]
npcmgpio_irq_startup() calls pinctrl_gpio_direction_input(), which may
sleep while taking the pinctrl core mutex. That makes IRQ startup trip
lockdep when CONFIG_PROVE_LOCKING is enabled.
Move the direction change into irq_request_resources() and keep startup
limited to the ack and unmask operations that are safe in atomic
context.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **v7.3-rc4** (`7.3.0-rc4`). The NPCM8XX pinctrl driver
is present, and this change is a real sleep-in-atomic IRQ fix, not a
feature add.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[pinctrl/npcm8xx] [move] move GPIO IRQ setup into
request_resources**
Subsystem `pinctrl: npcm8xx`. Verb is “move”, but the body is a
correctness fix: take a may-sleep call out of `irq_startup`.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Tomer Maimon `<tmaimon77@gmail.com>` (author; NPCM
maintainer)
- Signed-off-by: Linus Walleij `<linusw@kernel.org>` (pinctrl
maintainer)
- No Fixes, Reported-by, Tested-by, Reviewed-by, Acked-by, Link, or Cc:
stable
Absence of Fixes/Cc: stable is expected for this review and is not a
negative signal.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: `npcmgpio_irq_startup()` calls `pinctrl_gpio_direction_input()`,
which takes the pinctrl mutex and may sleep.
- Symptom: lockdep splat with `CONFIG_PROVE_LOCKING` on IRQ startup.
- Root cause: IRQ startup runs in atomic context; mutex_lock there is
illegal.
- Fix: do the direction change in `irq_request_resources()`; leave
startup as ack+unmask only.
- No version range, stack trace, or reproducer in the message.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a hidden fix. It is an explicit locking/context bug. Cover
letter of the v1 series called the set a “cleanup” from a Nuvoton tree
comparison, but this patch itself describes a real sleep-in-atomic
problem.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` (+23 / -6, 29 lines)
- Functions: `npcmgpio_irq_startup` (changed),
`npcmgpio_irq_request_resources` (added),
`npcmgpio_irq_release_resources` (added), `npcmgpio_irqchip` (changed)
- Scope: single-file surgical irqchip callback change
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: `irq_startup` called `npcmgpio_direction_input()` then
ack/unmask. Resource helpers came from `GPIOCHIP_IRQ_RESOURCE_HELPERS`
(`gpiochip_irq_reqres` / `gpiochip_irq_relres`).
- After: `irq_startup` only ack+unmask. New `irq_request_resources` does
`npcmgpio_direction_input()` then `gpiochip_reqres_irq()`. New
`irq_release_resources` calls `gpiochip_relres_irq()`. Macro helpers
removed because custom callbacks replace them.
- Path: GPIO `request_irq()` setup, not a probe-only path.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **Synchronization / illegal sleep in atomic context**
`irq_startup()` is invoked from `__setup_irq()` while `desc->lock` is
held via `raw_spin_lock_irqsave()` (`kernel/irq/manage.c`: lock at 1589,
`irq_startup()` at 1766, unlock at 1807).
`pinctrl_gpio_direction_input()` takes `pinctrldev_list_mutex` and
`pctldev->mutex` (`drivers/pinctrl/core.c`). Mutex in that context is
sleep-in-atomic. `irq_request_resources()` runs before that spinlock and
is allowed to sleep.
Step 2.4: ASSESS THE FIX QUALITY
Record: Quality is high. Same pattern as `pinctrl-ingenic.c` and
`pinctrl-st.c`. Resource get/put is preserved. Direction-input errors
are now returned instead of ignored. Regression risk is low: startup no
longer re-applies input on later startups, which matches other drivers;
first `request_irq()` still sets input before unmask. No API or data-
structure change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: Buggy `npcmgpio_irq_startup()` / `GPIOCHIP_IRQ_RESOURCE_HELPERS`
came from `acf4884a571709` (“pinctrl: nuvoton: add NPCM8XX pinctrl and
GPIO driver”, 2023-08-28), first in **v6.7-rc1**. The bug is as old as
the driver.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Introducer is the original driver commit above.
`git merge-base --is-ancestor acf4884a571709 HEAD` is true in this tree.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Submitted as **[PATCH v1 6/8]** “pinctrl: npcm8xx: fix pinmuxing
and configuration handling”. Siblings (bmcuart1 pins, RMII, RG2 drive
strength, event clear, rename, JM1/SMB7 flags, debounce) do not change
the irqchip callbacks this patch needs. Standalone. No follow-up on
these IRQ helpers after this commit.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Tomer Maimon is listed under ARM/NUVOTON NPCM ARCHITECTURE in
MAINTAINERS. Recent npcm8xx work is this same 8-patch set plus earlier
pin-table updates. Maintainer-authored.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Needs existing `gpiochip_reqres_irq` / `gpiochip_relres_irq` and
`GPIOCHIP_IRQ_RESOURCE_HELPERS`, both present here. No series
prerequisite for this hunk. Can apply standalone to this driver.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record: `b4 dig -c b8edfde12e355` →
https://patch.msgid.link/20260715122923.1938327-7-tmaimon77@gmail.com
Only **v1**. Lore HTTP fetch returned 403; full thread was saved with
`b4 dig -m`. Linus Walleij (24 Jul 2026): “No comments so patches
applied.” No NAK, no stable nomination, no requested respin.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: `b4 dig -w` To/Cc: Tomer Maimon, Andrew Jeffery, Linus Walleij,
Bartosz Golaszewski, openbmc, linux-gpio, linux-kernel, Avi Fishman,
Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair. Right lists and
maintainers. Only explicit reply is Walleij applying the series.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by, syzbot, or bugzilla. Issue was found by
comparing upstream with Nuvoton’s tree. Symptom claimed is lockdep with
`CONFIG_PROVE_LOCKING`. No public user crash report found.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: 8-patch pinmux/config series. This IRQ move does not depend on
the others. npcm7xx still calls `npcmgpio_direction_input()` from
`irq_startup()` — same class of bug, different driver, not a dependency.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search via curl returned 403. UNVERIFIED
whether stable@ already discussed this. No evidence in the gpio thread
of a stable NAK.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `npcmgpio_irq_startup`, `npcmgpio_irq_request_resources`,
`npcmgpio_irq_release_resources`, plus `npcmgpio_irqchip` initializer.
Step 5.2: TRACE CALLERS
Record:
- irqchip ops invoked from IRQ core: `irq_request_resources()` /
`irq_release_resources()` / `irq_startup()` in `kernel/irq/manage.c`
and `kernel/irq/chip.c`
- Chip registered in `npcm8xx_gpio_register()` via `girq->chip`
- Reachable from `request_irq()` / `gpiod_to_irq()` users on NPCM8XX
GPIO banks
Step 5.3: TRACE CALLEES
Record: `npcmgpio_direction_input` → `pinctrl_gpio_direction_input`
(mutex) + generic `bank->direction_input`; `npcmgpio_irq_ack` / `unmask`
(MMIO); `gpiochip_reqres_irq` / `gpiochip_relres_irq`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: userspace or driver `request_irq` on a GPIO line → `__setup_irq`
→ `irq_request_resources` (sleep OK) →
`raw_spin_lock_irqsave(&desc->lock)` → `irq_startup` (atomic). Path is
reachable whenever GPIO IRQs are used (BMC buttons, hotplug, etc.). Not
an obscure config-only path if `PINCTRL_NPCM8XX` is enabled (`depends on
ARCH_NPCM || COMPILE_TEST`).
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same “direction_input in irq_request_resources” pattern in
ingenic and ST pinctrl. Sibling `pinctrl-npcm7xx.c` still has the old
startup-time `direction_input` call.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Driver is `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c`.
Introduced v6.7 (`acf4884a571709`). `git merge-base --is-ancestor
acf4884a571709 HEAD` succeeded. Pre-fix startup still present at parent
`b8edfde12e355^`. Local kernel: **v7.3-rc4** (`7.3.0-rc4`).
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Expected apply: **clean**. Hunks are local to the irqchip struct
and two small callbacks. `GPIOCHIP_IRQ_RESOURCE_HELPERS` and
`gpiochip_reqres_irq()` exist here. Reverse-apply of the committed diff
checked cleanly against current file.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No earlier alternate fix for this irq_startup sleep. Current
HEAD already contains `b8edfde12e355` because this checkout is mainline
after the pinctrl-v7.3 pull; that is the upstream commit under review,
not a prior independent fix. No later corrective commit.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **pinctrl / GPIO irqchip for Nuvoton NPCM8XX (Arbel BMC)**.
Criticality: **PERIPHERAL** for general kernels, **IMPORTANT** for
OpenBMC/NPCM845 systems. Not mm/fs/net core.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: File is actively updated (pin tables, debounce, RMII, this IRQ
fix). Driver is mature since v6.7, not brand-new staging code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: **driver-specific / platform-specific**: NPCM8XX
(`CONFIG_PINCTRL_NPCM8XX`), typically OpenBMC on NPCM845. Not universal.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger is GPIO IRQ request (`request_irq` / irqchip startup).
Common for BMC GPIO IRQs. Unprivileged userspace can hit it if a GPIO
irq is exported; typical path is kernel drivers during bring-up. Not a
rare race: with lockdep it fires on every such startup. Mutex contention
can turn it into a real sleep-under-spinlock.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Failure mode: mutex_lock while `desc->lock` is held and IRQs are
off.
- With `CONFIG_PROVE_LOCKING` / `DEBUG_ATOMIC_SLEEP`: lockdep/WARN
(always)
- If `pctldev->mutex` is contended: **scheduling while atomic** → BUG
Severity: **HIGH** (illegal atomic sleep; crash if contended), not a
silent data-corruption bug.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: medium-high for NPCM8XX/OpenBMC (correct IRQ request, no
lockdep/sleep-in-atomic); zero for other platforms
- Risk: **low** (~20 net lines, irqchip callbacks only, established
pattern)
- Ratio: favorable
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real sleep-in-atomic: `pinctrl_gpio_direction_input()` takes mutexes;
`irq_startup()` runs under `raw_spin_lock_irqsave(&desc->lock)`
- Deterministic on GPIO IRQ request with lockdep
- Can BUG if the pinctrl mutex is contended
- Small, obviously correct, matches ingenic/ST
- Keeps `gpiochip_reqres_irq` / `gpiochip_relres_irq`
- Driver exists in this tree since v6.7
- Author is NPCM maintainer; applied by Linus Walleij
- Standalone vs the rest of the 8-patch series
AGAINST:
- No user crash report / syzbot / Fixes tag
- Author framed the user-visible issue as lockdep, not production oops
- NPCM8XX-only
- Cover letter called the series a vendor-tree cleanup
- npcm7xx still has the same pattern (does not make this patch wrong)
UNRESOLVED:
- lore.kernel.org HTTP 403; stable@ discussion not independently fetched
(thread itself was retrieved via b4)
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — context split is the
documented irqchip model; applied by pinctrl maintainer. No extra
Tested-by.
2. Fixes a real bug that affects users? **PASS** — illegal mutex in IRQ
startup on GPIO `request_irq`.
3. Important issue? **PASS** — sleep-in-atomic / lockdep; possible BUG
if mutex contended. Not a new feature.
4. Small and contained? **PASS** — one file, ~29 lines.
5. No new features or APIs? **PASS** — only irqchip callback placement.
6. Can apply to the local tree? **PASS** — driver and helpers exist;
hunks match.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID, quirk, DT, build, or docs-only change).
Qualifies as a normal bugfix.
Step 9.4: MAKE YOUR DECISION
This tree has the NPCM8XX driver and the buggy startup path. The patch
is a small, correct move of a may-sleep call to
`irq_request_resources()`, which is the sleepable side of
`request_irq()`. That meets stable rules for this checkout.
Verification:
- [Phase 1] Tags: only Tomer Maimon and Linus Walleij SOBs; no
Fixes/Reported-by/stable Cc
- [Phase 2] Diff: 23 insertions, 6 deletions in `pinctrl-npcm8xx.c`;
direction_input moved; GPIOCHIP_IRQ_RESOURCE_HELPERS replaced by
custom reqres/relres
- [Phase 2] `pinctrl_gpio_direction()` locks `pctldev->mutex`;
`pinctrl_get_device_gpio_range()` locks `pinctrldev_list_mutex`
- [Phase 2] `__setup_irq()`: `irq_request_resources()` before
`desc->lock`; `irq_startup()` while lock held (`manage.c` 1574–1766,
unlock 1807)
- [Phase 3] Blame: bug from `acf4884a571709` (v6.7-rc1); `git merge-base
--is-ancestor` true for intro and for `b8edfde12e355`
- [Phase 3] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; `make
kernelversion`: 7.3.0-rc4
- [Phase 3] Series 1/8–8/8 identified; this patch does not depend on the
others
- [Phase 4] `b4 dig -c b8edfde12e355`: lore msgid
20260715122923.1938327-7; v1 only
- [Phase 4] `b4 dig -w`: Walleij, Golaszewski, Andrew Jeffery, openbmc,
linux-gpio
- [Phase 4] mbox: Walleij “No comments so patches applied”; no
NAK/stable Cc
- [Phase 4] UNVERIFIED: stable@ archive (HTTP 403)
- [Phase 5] Same pattern in `ingenic_gpio_irq_request` and
`st_gpio_irq_request_resources`; npcm7xx still uses startup-time
direction_input
- [Phase 6] File present; reverse `git apply --check` of the commit diff
succeeded
- [Phase 8] Failure mode: lockdep always; scheduling-while-atomic if
mutex contended — HIGH for this SoC, not universal
- UNVERIFIED: whether an unprivileged gpiochip ioctl is the common
trigger vs kernel drivers (both reach `request_irq`)
**YES**
drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 29 ++++++++++++++++++-----
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 28464463ff833..0347a471f9226 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -295,17 +295,33 @@ static void npcmgpio_irq_unmask(struct irq_data *d)
static unsigned int npcmgpio_irq_startup(struct irq_data *d)
{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- unsigned int gpio = irqd_to_hwirq(d);
-
- /* active-high, input, clear interrupt, enable interrupt */
- npcmgpio_direction_input(gc, gpio);
npcmgpio_irq_ack(d);
npcmgpio_irq_unmask(d);
return 0;
}
+static int npcmgpio_irq_request_resources(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ unsigned int gpio = irqd_to_hwirq(d);
+ int ret;
+
+ ret = npcmgpio_direction_input(gc, gpio);
+ if (ret)
+ return ret;
+
+ return gpiochip_reqres_irq(gc, gpio);
+}
+
+static void npcmgpio_irq_release_resources(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ unsigned int gpio = irqd_to_hwirq(d);
+
+ gpiochip_relres_irq(gc, gpio);
+}
+
static struct irq_chip npcmgpio_irqchip = {
.name = "NPCM8XX-GPIO-IRQ",
.irq_ack = npcmgpio_irq_ack,
@@ -313,8 +329,9 @@ static struct irq_chip npcmgpio_irqchip = {
.irq_mask = npcmgpio_irq_mask,
.irq_set_type = npcmgpio_set_irq_type,
.irq_startup = npcmgpio_irq_startup,
+ .irq_request_resources = npcmgpio_irq_request_resources,
+ .irq_release_resources = npcmgpio_irq_release_resources,
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
- GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static const int gpi36_pins[] = { 36 };
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] hfs: validate catalog CNIDs before instantiating inodes
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (70 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: move GPIO IRQ setup into request_resources Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] PCI: cadence: Add missing MODULE_DEVICE_TABLE() Sasha Levin
` (444 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: David Maximiliano Hermitte, syzbot+97e301b4b82ae803d21b,
George Anthony Vernon, Tetsuo Handa, Viacheslav Dubeyko,
Sasha Levin, frank.li, linux-fsdevel, linux-kernel
From: David Maximiliano Hermitte <davemadmaxxx@gmail.com>
[ Upstream commit 53c3c138d672765c26884c55728307a65c634328 ]
hfs_cat_find_brec() first resolves a catalog thread record by CNID and
then looks up the corresponding catalog record by parent/name. On a
corrupted filesystem image, the second lookup may find a record whose
CNID does not match the CNID that was requested.
Validate the record found by the second lookup before returning it.
Read the already-found record with hfs_bnode_read(), require the exact
fixed size for file and directory records, reject other record types,
and verify that the stored CNID matches the requested CNID.
Also validate reserved CNIDs in hfs_read_inode() before populating the
inode, propagate hfs_read_inode() failures from the resource-fork lookup
path, and reject bad resource-fork and root inodes.
Keep hfs_write_inode() unchanged, so corrupted catalog records are
rejected before reaching its existing reserved-CNID BUG() path.
Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
Cc: George Anthony Vernon <contact@gvernon.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: David Maximiliano Hermitte <davemadmaxxx@gmail.com>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
Link: https://lore.kernel.org/r/20260708215636.73815-1-davemadmaxxx@gmail.com
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
commit is `53c3c138d6727` and is already in this mainline history (first
contained in `v7.3-rc1`). The evaluation below is whether that fix is
suitable to take into stable from this tree: HFS is present, the `BUG()`
path is ancient, and the patch is self-contained.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[hfs] [validate] Validate catalog CNIDs before instantiating
inodes** — “validate” here is a correctness/safety check, not a feature.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Reported-by:** syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
(fuzzer, reproducible)
- **Closes:**
https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
- **Cc:** George Anthony Vernon, Tetsuo Handa
- **Signed-off-by:** David Maximiliano Hermitte (author); Viacheslav
Dubeyko (HFS maintainer, twice)
- **Reviewed-by:** Viacheslav Dubeyko
- **Link:** https://lore.kernel.org/r/20260708215636.73815-1-
davemadmaxxx@gmail.com
- **No Fixes:** tag (expected)
- **No Cc: stable** (expected; not a negative)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `hfs_cat_find_brec()` resolves a thread by CNID, then looks
up the catalog record by parent/name. On a corrupted image that second
lookup can return a record whose stored CNID does not match the
requested CNID.
- **Symptom/failure mode:** A corrupted catalog record is turned into an
inode with a reserved CNID (`i_ino < HFS_FIRSTUSER_CNID` and not
root/extents/catalog). Later writeback hits `BUG()` in
`hfs_write_inode()`.
- **Version info:** none in the message; syzbot first crash is
2022-11-25.
- **Root cause (author):** missing validation of the second catalog
lookup, plus missing reserved-CNID checks at inode instantiation;
resource-fork lookup ignored `hfs_read_inode()` failures.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. Explicit syzbot crash fix: reject bad
catalog records so they never reach the reserved-CNID `BUG()`.
---
## PHASE 2: DIFF ANALYSIS - LINE BY LINE
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `fs/hfs/catalog.c`: +40 / -1 — add `hfs_cat_validate_found_cnid()`,
call it from `hfs_cat_find_brec()`
- `fs/hfs/hfs_fs.h`: +19 — add inline `hfs_is_valid_cnid()`
- `fs/hfs/inode.c`: +12 / -1 — CNID checks in `hfs_read_inode()`;
propagate errors and `is_bad_inode()` in `hfs_file_lookup()`
- `fs/hfs/super.c`: +5 — reject bad root inode in `hfs_fill_super()`
- **Total:** +76 / -2 across 4 HFS files
- **Scope:** single-subsystem surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **`hfs_cat_find_brec`:** Before: thread lookup, then `return
hfs_brec_find(fd)` with no check that the found record’s CNID matches.
After: on success, read the found record, require exact file/dir size,
reject other types, require `found_cnid == cnid`, else `-EIO`.
- **`hfs_read_inode`:** Before: populate inode from any file/dir record,
including reserved CNIDs 0,1,5–15. After: `hfs_is_valid_cnid()`;
invalid → `-EIO` before `i_ino` is set.
- **`hfs_file_lookup` (rsrc):** Before: ignored `hfs_read_inode()`
return, then `mark_inode_dirty()`. After: propagate errors;
`is_bad_inode()` → `-EIO` + `iput`.
- **`hfs_fill_super`:** After `hfs_iget()`, `is_bad_inode(root)` →
`iput` and fail mount instead of `d_make_root()` on a bad inode.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** memory-safety / logic — corrupted on-disk metadata →
kernel `BUG()` (oops, invalid opcode).
- **Mechanism:** Reserved CNIDs instantiated as normal inodes; writeback
`hfs_write_inode()` does `BUG()` in the default branch of
`inode->i_ino < HFS_FIRSTUSER_CNID`. Also bounds/type checks on
catalog record length.
- **Not:** leak, UAF, or locking fix.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct relative to HFS CNID rules: user CNIDs ≥ 16;
reserved 2=root dir, 3=extents file, 4=catalog file; others invalid
for catalog-instantiated inodes.
- `iget5_locked` `set()` returning non-zero → `inode_insert5()` returns
NULL; `hfs_iget()` already treats NULL as failure.
- New `hfs_read_inode()` code does not sleep (safe under
`inode_hash_lock`).
- Maintainer asked to leave `hfs_write_inode()` unchanged; defense is at
instantiation. Remaining `BUG()` is only if some other path still
creates a reserved-CNID inode.
- **Regression risk:** low. Could reject a theoretically weird volume
with catalog entries using CNIDs 1 or 5–15; that is invalid HFS and
those inodes would `BUG()` on writeback anyway.
- No public API / data-structure change.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: `hfs_write_inode()` reserved-CNID `BUG()` and
`hfs_cat_find_brec()` date to **1da177e4c3f41 (Linux-2.6.12-rc2,
2005)**. Long-standing, not a newly introduced bug.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Buggy behavior is original HFS catalog/inode
code, not a recent regression.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Nearby HFS work (`hfs_correct_next_unused_CNID`, MDB locking) is
independent. This commit is standalone, not `patch X/Y`. After it, later
`fs/hfs/{inode,catalog,super,hfs_fs.h}` commits are unrelated (MDB,
delayed work, ENOSPC). No follow-up fix to this patch.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Only this HFS commit from David Maximiliano Hermitte. Weight
comes from **Reviewed-by / Signed-off-by Viacheslav Dubeyko** (HFS
maintainer). Earlier related attempts: George Vernon, Tetsuo Handa
(syzbot thread).
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Uses existing `hfs_bnode_read()`, `hfs_brec_find()`,
`is_bad_inode()`, `HFS_*_CNID`, `hfs_read_inode()` already returning
`int` since 2.6.12. **Can apply standalone.**
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig:**
https://patch.msgid.link/20260708215636.73815-1-davemadmaxxx@gmail.com
- **Revisions:** v1 (2026-07-02) → v3 RESEND → v4 → **v5 (applied)**
- Maintainer review drove exact size checks, signed `rec_len`, keep
`hfs_write_inode()` unchanged, preserve `hfs_file_lookup()` error
codes
- v5: Slava: “Looks good. Thanks a lot for the fix.” + Reviewed-by
- Tetsuo: not a NAK; points at sashiko notes on *pre-existing* issues
- Author revalidated with HFS build and QEMU syzbot repro
- **No NAKs** of the committed approach
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (b4 dig -w): Viacheslav Dubeyko, Tetsuo Handa, George Vernon,
Jori Koolstra, linux-fsdevel, syzbot. Maintainer reviewed and merged.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record (syzbot, live page):
- Title: **kernel BUG in hfs_write_inode**
- First crash: **2022-11-25**; last listed ~35d before the page
snapshot; **243695 crashes**; C and syz reproducers
- Stack: `hfs_write_inode` ← writeback `wb_workfn` (kworker), invalid
opcode at `BUG()`
- Security assessment: DenialOfService yes, FilesystemTrigger yes,
**Unprivileged: no** (needs a mountable image)
- Duplicate: “invalid opcode in hfs_write_inode”
- Fix commit listed as `53c3c138d672`
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Single-patch series (v1–v5 of the same change). Earlier
alternate approaches (replace `BUG()` with `-EIO`/`-EFSCORRUPTED`,
broader `BUG()` removal) were **not** what merged; this validation-at-
instantiation patch is standalone.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — lore.kernel.org fetches returned 403. No `Cc:
stable` in the fsdevel thread. That absence is not a reason to reject.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `hfs_cat_validate_found_cnid` (new), `hfs_cat_find_brec`,
`hfs_is_valid_cnid` (new inline), `hfs_read_inode`, `hfs_file_lookup`,
`hfs_fill_super`. `hfs_write_inode` unchanged.
**Step 5.2: TRACE CALLERS**
Record:
- `hfs_cat_find_brec()` — only `hfs_fill_super()` (root at mount)
- `hfs_read_inode()` — `iget5_locked` set callback from `hfs_iget()`
(`hfs_lookup` / `hfs_fill_super`) and direct call from
`hfs_file_lookup()` (rsrc)
- `hfs_write_inode()` — `s_op->write_inode` from writeback (crash site)
**Step 5.3: TRACE CALLEES**
Record: `hfs_bnode_read`, `hfs_brec_find`, `be32_to_cpu`,
`is_bad_inode`, `iput`. No new allocations/locks.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable from **mounting an HFS image** and from **lookup /
rsrc** on a mounted volume. Syzbot C repro mounts a crafted image;
writeback then `BUG()`s. Userspace-triggerable if the caller can mount
HFS (`CONFIG_HFS_FS`).
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: HFS+ already special-cases reserved vs user CNIDs in
`hfsplus_iget()` (`fs/hfsplus/super.c`). Classic HFS lacked that for
catalog-instantiated inodes. Same class of bug, HFS-only fix.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `BUG()` still in `hfs_write_inode()` at `fs/hfs/inode.c`
(lines 479–491), present since 2.6.12. Validation from this commit is
already applied here (`hfs_is_valid_cnid` in `hfs_fs.h`,
`hfs_cat_validate_found_cnid` in `catalog.c`). Introduced: original HFS
port, not post-7.3.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Expected apply: clean / minor context** on trees that still
have `hfs_cat_find_brec`, `hfs_read_inode`, `hfs_file_lookup`,
`hfs_fill_super`. New code does not depend on `inode_set_ctime_to_ts`,
`set_default_d_op`, or CNID-correction helpers. Constants live in
`include/linux/hfs_common.h` here; older trees may still have them in
`fs/hfs/hfs.h` — only a context/include issue, not a logic dependency.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This is the fix (`53c3c138d6727`). No earlier equivalent in-
tree. Not in `v7.2`.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **fs/hfs** — **PERIPHERAL** (legacy Mac HFS, `CONFIG_HFS_FS`,
not the VFS core). Still a real on-disk filesystem; a `BUG()` on
corrupted images is a kernel crash, not a cosmetic warning.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained under Viacheslav Dubeyko (`hfs-v7.3-tag1`
and other recent HFS tags). Mature code with ongoing syzbot/hardening.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Config/driver-specific:** `CONFIG_HFS_FS`. Anyone who can
mount HFS (including fuzzers, forensic mounts, old Mac volumes). Not
universal.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Mount / use a **corrupted HFS image**. Syzbot has a C repro;
240k+ crashes over ~4 years. Not unprivileged without mount capability.
Timing-independent once the bad inode is instantiated and dirtied
(`hfs_file_lookup` does `mark_inode_dirty` on rsrc).
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **`BUG()` / invalid opcode in writeback kworker → oops.**
**Severity: CRITICAL** (kernel crash). DoS, not a demonstrated
privilege-escalation.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** high for HFS users and any tree that enables HFS — stops
a years-old reproducible `BUG()`.
- **Risk:** low — +76 lines, HFS-only, reviewed, tested with QEMU repro;
failure mode on bad images becomes `-EIO` / failed mount instead of
oops.
- **Ratio:** strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Syzbot kernel `BUG()` since 2022, C repro, hundreds of thousands of
crashes
- Crash in writeback (`wb_workfn` → `hfs_write_inode`)
- Small, contained HFS-only change (+76/-2)
- Maintainer Reviewed-by after v1–v5
- Bug in code since 2.6.12; no missing prerequisites in this tree
- Matches stable rules: real crash, obviously correct validation, no new
API
**AGAINST:**
- HFS is a legacy/peripheral FS
- Needs ability to mount HFS (not unprivileged syscall-only)
- `hfs_write_inode()` `BUG()` remains as a backstop if another path
instantiates a reserved CNID
- No `Cc: stable` (expected for this review queue)
**UNRESOLVED:**
- lore.kernel.org/stable search (HTTP 403)
- Whether every older stable series has identical hunk context
(`hfs_common.h` vs `hfs.h`)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — maintainer review, QEMU
repro, syzbot
2. Fixes a real bug that affects users? **PASS** — reproducible `BUG()`
on corrupted HFS
3. Important issue? **PASS** — kernel oops (CRITICAL)
4. Small and contained? **PASS** — 4 files, +76/-2, HFS only
5. No new features or APIs? **PASS** — validation only
6. Can apply to the local tree? **PASS** — code is present; patch is
self-contained (already merged here as of 7.3-rc1)
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not ID/quirk/DT/docs. Ordinary **crash fix** on filesystem
corruption.
**Step 9.4: MAKE YOUR DECISION**
This is a real, long-standing, syzbot-reproduced kernel `BUG()` on
corrupted HFS catalog data. The fix is small, reviewed, and stops bad
CNIDs from becoming inodes that writeback will crash on. That is
appropriate for stable.
---
### What the commit solves and why it matters
On a corrupted HFS catalog, a thread lookup by CNID can be followed by a
parent/name lookup that returns a **different** record. That record can
carry a reserved CNID (0, 1, 5–15, …). Instantiating it and dirtying it
(notably the resource-fork path, which previously ignored
`hfs_read_inode()` errors) causes **writeback to `BUG()`** in
`hfs_write_inode()`. Stable kernels that still ship HFS will oops the
same way; rejecting the record with `-EIO` is the right user-visible
behavior.
### Stable rules / risk
Surgical, HFS-only, no new APIs, maintainer-acked, fuzzer-proven.
Residual risk is failing mount/lookup on already-invalid volumes that
used to oops instead.
### Concerns
Older trees may need a trivial context tweak if CNID macros are still in
`fs/hfs/hfs.h`. No semantic prerequisites. The remaining `BUG()` in
`hfs_write_inode()` is intentional per the maintainer.
### Verification
- **[Phase 1]** Tags: syzbot Reported-by, Closes syzkaller URL,
Reviewed-by Dubeyko, lore Link; no Fixes/Cc-stable
- **[Phase 2]** Diff: +76/-2 in catalog.c, hfs_fs.h, inode.c, super.c;
validation + error propagation
- **[Phase 3]** `git describe HEAD` → v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` → 7.3.0-rc4
- **[Phase 3]** Commit `53c3c138d6727`; `git merge-base --is-ancestor
53c3c138d6727 HEAD` → yes
- **[Phase 3]** `git merge-base --is-ancestor 53c3c138d6727 v7.2` → not
in v7.2; `git describe --contains` → v7.3-rc1~222^2~9
- **[Phase 3]** Blame: `BUG()` in `hfs_write_inode` from 1da177e4c3f41
(2.6.12-rc2)
- **[Phase 3]** `hfs_read_inode` already `static int` since 2.6.12; pre-
fix `hfs_file_lookup` discarded its return value
- **[Phase 4]** `b4 dig -c 53c3c138d6727` → msgid
20260708215636.73815-1; v1/v3/v4/v5; v5 applied
- **[Phase 4]** `b4 dig -w`: Dubeyko, Handa, fsdevel, syzbot
- **[Phase 4]** `b4 dig -m`: Slava “Looks good” + Reviewed-by; asked to
leave `hfs_write_inode` unchanged
- **[Phase 4]** WebFetch syzbot: kernel BUG in hfs_write_inode,
2022-11-25, C repro, 243695 crashes
- **[Phase 4]** lore.kernel.org WebFetch: 403 — stable-list search
UNVERIFIED
- **[Phase 5]** Callers: `hfs_cat_find_brec` only from `hfs_fill_super`;
`hfs_iget` from dir lookup + mount; rsrc via `hfs_file_lookup`
- **[Phase 5]** `inode_insert5()` treats failed `set()` as NULL inode
(verified `fs/inode.c`)
- **[Phase 6]** Local files already contain the new helpers; `BUG()`
path still present
- **[Phase 8]** Failure mode: oops in kworker writeback, severity
CRITICAL
- **UNVERIFIED:** stable@ discussion (lore 403); exact hunk context on
every LTS series
**YES**
fs/hfs/catalog.c | 41 ++++++++++++++++++++++++++++++++++++++++-
fs/hfs/hfs_fs.h | 19 +++++++++++++++++++
fs/hfs/inode.c | 13 ++++++++++++-
fs/hfs/super.c | 5 +++++
4 files changed, 76 insertions(+), 2 deletions(-)
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index ccdbbffaaf7c1..f3fd84cffed5f 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -182,6 +182,40 @@ int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2)
key2->cat.CName.name, key2->cat.CName.len);
}
+static int hfs_cat_validate_found_cnid(struct hfs_find_data *fd, u32 cnid)
+{
+ hfs_cat_rec rec;
+ u32 found_cnid;
+ int rec_len;
+
+ rec_len = fd->entrylength;
+ if (rec_len <= 0 || (size_t)rec_len > sizeof(rec))
+ return -EIO;
+
+ memset(&rec, 0, sizeof(rec));
+ hfs_bnode_read(fd->bnode, &rec, fd->entryoffset, rec_len);
+
+ switch (rec.type) {
+ case HFS_CDR_FIL:
+ if ((size_t)rec_len != sizeof(struct hfs_cat_file))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.file.FlNum);
+ break;
+ case HFS_CDR_DIR:
+ if ((size_t)rec_len != sizeof(struct hfs_cat_dir))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.dir.DirID);
+ break;
+ default:
+ return -EIO;
+ }
+
+ if (found_cnid != cnid)
+ return -EIO;
+
+ return 0;
+}
+
/* Try to get a catalog entry for given catalog id */
// move to read_super???
int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
@@ -208,7 +242,12 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
return -EIO;
}
memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
- return hfs_brec_find(fd);
+
+ res = hfs_brec_find(fd);
+ if (res)
+ return res;
+
+ return hfs_cat_validate_found_cnid(fd, cnid);
}
static inline
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 86b5ae62247be..724b28bb8c6c4 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -156,6 +156,25 @@ extern int hfs_cat_move(u32 cnid, struct inode *src_dir,
extern void hfs_cat_build_key(struct super_block *sb, btree_key *key,
u32 parent, const struct qstr *name);
+/*
+ * Validate the CNID of a catalog record.
+ */
+static inline bool hfs_is_valid_cnid(u32 cnid, u8 type)
+{
+ if (likely(cnid >= HFS_FIRSTUSER_CNID))
+ return true;
+
+ switch (cnid) {
+ case HFS_ROOT_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_EXT_CNID:
+ case HFS_CAT_CNID:
+ return type == HFS_CDR_FIL;
+ default:
+ return false;
+ }
+}
+
/* dir.c */
extern const struct file_operations hfs_dir_operations;
extern const struct inode_operations hfs_dir_inode_operations;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index f1796e4b07e83..e815e9a8ac6f2 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -365,6 +365,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
rec = idata->rec;
switch (rec->type) {
case HFS_CDR_FIL:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->file.FlNum), rec->type))
+ return -EIO;
+
if (!HFS_IS_RSRC(inode)) {
hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen,
rec->file.PyLen, be16_to_cpu(rec->file.ClpSize));
@@ -386,6 +389,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
inode->i_mapping->a_ops = &hfs_aops;
break;
case HFS_CDR_DIR:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->dir.DirID), rec->type))
+ return -EIO;
+
inode->i_ino = be32_to_cpu(rec->dir.DirID);
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
HFS_I(inode)->fs_blocks = 0;
@@ -565,13 +571,18 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
res = hfs_brec_read(&fd, &rec, sizeof(rec));
if (!res) {
struct hfs_iget_data idata = { NULL, &rec };
- hfs_read_inode(inode, &idata);
+ res = hfs_read_inode(inode, &idata);
}
hfs_find_exit(&fd);
if (res) {
iput(inode);
return ERR_PTR(res);
}
+
+ if (is_bad_inode(inode)) {
+ iput(inode);
+ return ERR_PTR(-EIO);
+ }
HFS_I(inode)->rsrc_inode = dir;
HFS_I(dir)->rsrc_inode = inode;
igrab(dir);
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 97546d6b41f47..933aa04480899 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -372,6 +372,11 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (!root_inode)
goto bail_no_root;
+ if (is_bad_inode(root_inode)) {
+ iput(root_inode);
+ goto bail_no_root;
+ }
+
set_default_d_op(sb, &hfs_dentry_operations);
res = -ENOMEM;
sb->s_root = d_make_root(root_inode);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] PCI: cadence: Add missing MODULE_DEVICE_TABLE()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (71 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] hfs: validate catalog CNIDs before instantiating inodes Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:19 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] mmc: dw_mmc: stop and complete DMA also in STATE_DATA_BUSY state Sasha Levin
` (443 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Manivannan Sadhasivam, Aksh Garg, Sasha Levin,
lpieralisi, kwilczynski, bhelgaas, linux-pci, linux-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 93aac16f1eb9a181f9bdde620b464f6cc5fa8369 ]
The driver has an OF match table wired to .of_match_table, but does
not export the table with MODULE_DEVICE_TABLE().
Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias
information is generated for OF based module autoloading.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Aksh Garg <a-garg7@ti.com>
Link: https://patch.msgid.link/20260704122835.14277-1-pengpeng@iscas.ac.cn
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable backport analysis: `PCI: cadence: Add missing
MODULE_DEVICE_TABLE()`
Local tree: **Linux 7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). Verdict
is for this checkout only.
Candidate: `93aac16f1eb9a181f9bdde620b464f6cc5fa8369`
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1 — Subject line**
Record: `[PCI/cadence] [Add] missing MODULE_DEVICE_TABLE() so OF module
aliases are generated`
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>` (author)
- `Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>` (PCI
controller maintainer; applied the patch)
- `Reviewed-by: Aksh Garg <a-garg7@ti.com>`
- `Link:
https://patch.msgid.link/20260704122835.14277-1-pengpeng@iscas.ac.cn`
- No `Fixes:`, no `Reported-by:`, no `Cc: stable` (absence is expected
for this review)
- No syzbot / KASAN / crash report
**Step 1.3 — Body**
Record:
[Bug] OF match table is wired to `.of_match_table` but not exported via
`MODULE_DEVICE_TABLE()`.
[Symptom] `depmod` / udev / `modprobe` do not get `of:N*T*Ccdns,cdns-
pcie-host` / `cdns,cdns-pcie-ep` aliases, so the module does not
autoload.
[Version info] None in the message.
[Root cause] Missing alias publication, not a runtime logic error. The
mailing-list body (mbox) states this is a source-level fix with no
hardware reproducer.
**Step 1.4 — Hidden bug fix?**
Record: Not disguised. It is an explicit autoload/modalias fix. Same
class as `PCI: j721e: Fix module autoloading`.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1 — Inventory**
Record:
[Files] `drivers/pci/controller/cadence/pcie-cadence-plat.c` (+1 / −0)
[Functions] none changed; one statement added after
`cdns_plat_pcie_of_match[]`
[Scope] single-file, one-line surgical change
**Step 2.2 — Code flow**
Record: Before: match table exists and is used for probe matching, but
`scripts/mod/file2alias.c` never sees it, so the `.ko` has no OF
aliases. After: `MODULE_DEVICE_TABLE(of, cdns_plat_pcie_of_match)`
creates the `__mod_of__cdns_plat_pcie_of_match` alias
(`include/linux/module.h`). Normal module-build path only; no
probe/runtime behavior change.
**Step 2.3 — Bug mechanism**
Record: [Category] logic/correctness for modular OF drivers (missing
userspace alias). [Mechanism] without the macro, a modular `pcie-
cadence-plat` never autoloads from DT. Sibling Cadence drivers already
export tables (`pci-j721e.c`, `pci-sky1.c`, `pcie-sg2042.c`).
**Step 2.4 — Fix quality**
Record: Obviously correct and minimal. Regression risk is effectively
none: it only adds module metadata. Does not change locking, probe, or
APIs. Reviewer AI notes about probe `return 0` and drvdata type mismatch
are **pre-existing** and not introduced here.
---
## PHASE 3: GIT HISTORY
**Step 3.1 — Blame**
Record: Match table introduced in `bd22885aa188f` (“PCI: cadence:
Refactor driver to use as a core library”, 2019). Driver was
`builtin_platform_driver` + `bool` Kconfig until `611627a4e5e4a` (“PCI:
cadence: Add module support for platform controller driver”,
2025-11-14). That commit is in **v6.19**. Bug (missing table export for
a loadable module) starts there.
**Step 3.2 — Fixes: tag**
Record: No `Fixes:` tag. The introducing commit is `611627a4e5e4a`
(module support). It **is** an ancestor of this tree.
**Step 3.3 — File history**
Record: Recent: HPA support, module support, then this one-liner.
Standalone; not `patch X/Y`. No later revert on this file.
**Step 3.4 — Author**
Record: Pengpeng Hou also did `e145af8c14474` `PCI: spacemit: Add
missing MODULE_DEVICE_TABLE()` the same day. Applied by Manivannan
Sadhasivam (PCI controller maintainer).
**Step 3.5 — Dependencies**
Record: Needs `module_platform_driver` + tristate Kconfig from
`611627a4e5e4a`. Both are in this 7.3 tree. Applies standalone here.
---
## PHASE 4: MAILING LIST / EXTERNAL
**Step 4.1 — Original discussion**
Record: `b4 dig -c 93aac16f1eb9a` →
https://patch.msgid.link/20260704122835.14277-1-pengpeng@iscas.ac.cn
`b4 dig -a`: **v1 only**, 2026-07-04.
Thread (mbox): Aksh Garg Reviewed-by; Manivannan “Applied, thanks!” to
`93aac16f1eb9a`. No NAK, no stable nomination, no concern about this
line.
**Step 4.2 — Recipients (`b4 dig -w`)**
Record: PCI maintainers (Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Bjorn Helgaas), Rob Herring, linux-pci, linux-
kernel.
**Step 4.3 — Bug report**
Record: None. Author did not claim a hardware reproducer.
**Step 4.4 — Related series**
Record: Same-day sibling `PCI: spacemit: Add missing
MODULE_DEVICE_TABLE()`. Precedent in-tree: `9a7f144e18dc5` `PCI: j721e:
Fix module autoloading` (`Fixes:` + `Cc: stable`) — same one-line OF
table export.
**Step 4.5 — Stable list**
Record: UNVERIFIED. lore.kernel.org returned a bot-check page; WebFetch
of the msgid URL returned 403. No stable-list discussion was retrieved.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1 — Functions**
Record: No function bodies changed. Data: `cdns_plat_pcie_of_match[]`.
Driver: `cdns_plat_pcie_driver` / `cdns_plat_pcie_probe`.
**Step 5.2 — Callers**
Record: Probe is the platform-driver callback. Match table used only in
this file. Triggered when DT has `cdns,cdns-pcie-host` or `cdns,cdns-
pcie-ep`.
**Step 5.3 — Callees**
Record: Unchanged. `MODULE_DEVICE_TABLE` is a compile-time alias for
`file2alias.c`.
**Step 5.4 — Reachability**
Record: Reachable on OF platforms that describe Cadence PCIe with those
compatibles and build `CONFIG_PCIE_CADENCE_PLAT=m`. No in-tree
`.dts`/`.dtsi` uses those strings (only DT binding examples). So the in-
tree user set is small; out-of-tree / FPGA / IP reference boards may
still use the generic compatible.
**Step 5.5 — Similar patterns**
Record: Same missing-table pattern already fixed for j721e, mvebu, qcom-
ep, spacemit, and the other Cadence glue drivers in this directory.
---
## PHASE 6: LOCAL TREE CROSS-CHECK
**Step 6.1 — Does the buggy code exist here?**
Record: Yes. This tree has tristate `PCIE_CADENCE_PLAT`,
`module_platform_driver`, and the OF table. Module support is in v6.19+.
Without `MODULE_DEVICE_TABLE`, modular autoload is broken. (The one-line
fix is present at line 166 of the current file; that is not used as
“already selected” circular reasoning — it confirms the surrounding code
matches the patch.)
**Step 6.2 — Backport difficulty**
Record: Clean apply on this tree: one line next to the existing table.
**Step 6.3 — Related fixes already here?**
Record: j721e/sky1/sg2042 already have `MODULE_DEVICE_TABLE`. Nothing
else replaces this plat-driver export.
---
## PHASE 7: SUBSYSTEM CONTEXT
**Step 7.1**
Record: `[drivers/pci/controller/cadence] [IMPORTANT for Cadence-IP
SoCs; PERIPHERAL vs core mm/net]`. PCIe host not coming up is serious
for those boards, not universal.
**Step 7.2**
Record: Active PCI controller area (HPA, module support, several glue
drivers). Plat driver itself is mature (2019) with occasional fixes.
---
## PHASE 8: IMPACT AND RISK
**Step 8.1 — Who is affected**
Record: Driver-specific / config-specific: `CONFIG_PCIE_CADENCE_PLAT=m`
plus DT compatible `cdns,cdns-pcie-*`. Built-in builds are unaffected.
No in-tree board DTS match; population is reference/FPGA/out-of-tree DT.
**Step 8.2 — Trigger**
Record: Boot (or coldplug) on matching DT with the driver as a module.
Common for modular embedded images. Unprivileged users cannot trigger a
crash; they just never get the controller unless something else loads
the module.
**Step 8.3 — Failure mode**
Record: [Failure] module not autoloaded → PCIe host/endpoint never
probes → downstream devices missing. [Severity] **MEDIUM** (functional
miss, not oops/corruption). Workaround: `modprobe` or `=y`.
**Step 8.4 — Risk vs benefit**
Record: Benefit: hardware actually binds on modular kernels. Risk: very
low (modinfo aliases only). Ratio: favorable. Same class as device-ID /
autoload fixes that stable already takes (j721e was `Cc: stable`).
---
## PHASE 9: SYNTHESIS
**Step 9.1 — Evidence**
For:
- Real autoload bug on a driver this tree can build as a module
- One line, obviously correct, maintainer-applied, reviewed
- Sibling Cadence drivers already export tables; j721e’s identical fix
was stable-tagged
- Zero runtime regression surface
- Fits “device ID / make existing hardware work” exception more than a
feature
Against:
- No user report, no `Fixes:`/`Cc: stable` on this patch
- Author stated no hardware reproduction
- No in-tree DTS uses these compatibles
- Not a crash, UAF, or data-corruption bug
- Stable mailing-list history UNVERIFIED
Unresolved: whether anyone on stable@ already rejected or requested this
(lore blocked).
**Step 9.2 — Stable rules (this tree)**
1. Obviously correct and tested? **PASS** — one documented macro; v1
applied as-is after Reviewed-by.
2. Real bug that affects users? **PASS** — modular OF autoload fails;
users who `=m` this controller do not get PCIe without a manual load.
3. Important (crash/security/corruption/deadlock)? **PASS** at “oh,
that’s not good” / device-ID-class — PCIe does not come up. Not
CRITICAL.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS** — metadata for IDs that already
exist.
6. Can apply to this tree? **PASS** — table, `module_platform_driver`,
and tristate Kconfig are all here.
**Step 9.3 — Exception category**
Record: Closest to **device ID / hardware enablement**: publishing
existing OF IDs for autoload, not a new driver.
**Step 9.4 — Decision**
This 7.3 tree can build the Cadence platform controller as a module.
Without `MODULE_DEVICE_TABLE(of, ...)`, userspace never sees the aliases
and the host/endpoint driver does not autoload. That is a real, user-
visible functional bug, a one-line contained fix, and the same pattern
already sent to stable for `pci-j721e`. Risk is negligible. It should be
included in this tree.
---
## What the commit solves (for stable users)
On kernels where `CONFIG_PCIE_CADENCE_PLAT=m`, udev/modprobe cannot
match DT nodes `cdns,cdns-pcie-host` / `cdns,cdns-pcie-ep` to `pcie-
cadence-plat.ko`. The controller never probes unless the module is
loaded by hand. The patch only emits the standard OF aliases. No new
ABI, no probe-path change.
Risk vs benefit: benefit is “PCIe works on modular images”; risk is
alias-only. Backport on this tree is a clean one-line apply;
prerequisite module support (`611627a4e5e4a`, v6.19) is already present.
---
## Verification
- [Phase 1] Parsed tags: author Hou, SOB+apply Manivannan Sadhasivam,
Reviewed-by Aksh Garg, Link msgid; no Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: +1 line `MODULE_DEVICE_TABLE(of,
cdns_plat_pcie_of_match)` in `pcie-cadence-plat.c`
- [Phase 2] Confirmed macro in `include/linux/module.h` creates
`file2alias` alias
- [Phase 3] `git describe HEAD` / `make kernelversion`: **7.3.0-rc4**
- [Phase 3] `git blame`: table from `bd22885aa188f` (2019);
`MODULE_DEVICE_TABLE` line from `93aac16f1eb9a`
- [Phase 3] Introducer of modular bug: `611627a4e5e4a` (bool→tristate,
`builtin_platform_driver`→`module_platform_driver`); first tag
**v6.19**; `git merge-base --is-ancestor 611627a4e5e4a HEAD` true
- [Phase 3] `git merge-base --is-ancestor 93aac16f1eb9a HEAD` true (used
only to confirm context, not as “already selected”)
- [Phase 3] No revert of this commit on the file after it
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 only; lore msgid above; PCI
maintainers on To; Reviewed-by + Applied; no NAK
- [Phase 4] WebFetch lore URL: 403; lore search: bot wall. Stable-list
discussion **UNVERIFIED**
- [Phase 5] `git grep cdns_plat_pcie`: confined to plat driver + header
+ sky1 using the of_data struct
- [Phase 5] `git grep` of compatibles in `arch/`: **no** dts/dtsi users;
only DT binding examples
- [Phase 5] Sibling `MODULE_DEVICE_TABLE` already in j721e, sky1, sg2042
- [Phase 6] Local file has match table + `module_platform_driver` +
tristate Kconfig; patch applies as a single added line
- [Phase 6] Precedent `9a7f144e18dc5` j721e autoload fix has `Fixes:` +
`Cc: stable`
- [Phase 8] Failure mode: no autoload → PCIe missing; severity MEDIUM,
not oops
- UNVERIFIED: whether this was discussed on stable@ (lore blocked)
**YES**
drivers/pci/controller/cadence/pcie-cadence-plat.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pci/controller/cadence/pcie-cadence-plat.c b/drivers/pci/controller/cadence/pcie-cadence-plat.c
index 0456845dabb96..0f9cf2a9f0034 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-plat.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-plat.c
@@ -167,6 +167,7 @@ static const struct of_device_id cdns_plat_pcie_of_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, cdns_plat_pcie_of_match);
static struct platform_driver cdns_plat_pcie_driver = {
.driver = {
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] mmc: dw_mmc: stop and complete DMA also in STATE_DATA_BUSY state
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (72 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] PCI: cadence: Add missing MODULE_DEVICE_TABLE() Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] libbpf: Fix ring buffer consumer loop on 32-bit position wrap Sasha Levin
` (442 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Marek Szyprowski, Shawn Lin, Ulf Hansson, Sasha Levin, jh80.chung,
linux-mmc, linux-kernel
From: Marek Szyprowski <m.szyprowski@samsung.com>
[ Upstream commit cb3fcb8d118b874178251d1f02613f60d25e4ddc ]
When transfer was stopped in STATE_DATA_BUSY state, there was no call to
dma_ops->cleanup function, so the DMA mapped buffer was never properly
unmapped. Fix this by calling dw_mci_stop_dma() function also in that
state to ensure proper cleanup call when DMA transfer was used.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is mainline **v7.3-rc4** (`origin/master`). The
candidate is `cb3fcb8d118b8` (`mmc: dw_mmc: stop and complete DMA also
in STATE_DATA_BUSY state`): a one-line DMA-cleanup hole in a host used
on Exynos, Rockchip, and similar SoCs.
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
Record: **[mmc/dw_mmc] [stop and complete] Call DMA stop/cleanup in
`STATE_DATA_BUSY` so mapped buffers are unmapped.**
**Step 1.2 — Tags**
Record:
- Signed-off-by: Marek Szyprowski (author; DMA-mapping maintainer)
- Reviewed-by: Shawn Lin (dw_mmc co-maintainer)
- Signed-off-by: Ulf Hansson (MMC maintainer)
- No Fixes:, Reported-by, Tested-by, Link:, or Cc: stable (absence is
expected here)
**Step 1.3 — Body**
Record: **Bug:** finishing a transfer in `STATE_DATA_BUSY` never called
`dma_ops->cleanup`, so a DMA-mapped SG list was left mapped.
**Symptom:** DMA mapping leak (DMA-API/IOMMU leftover mappings). **Root
cause:** `dw_mci_stop_dma()` already runs in the sending-data / error
paths, but not in `STATE_DATA_BUSY` before `host->data = NULL`.
**Versions:** none stated.
**Step 1.4 — Hidden bug fix?**
Record: **No disguise.** It is an explicit resource-cleanup fix.
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
Record: `drivers/mmc/host/dw_mmc.c` **+1 / −0**. Function:
`dw_mci_work_func()`. **Single-file, one-line surgical fix.**
**Step 2.2 — Flow**
Record: In `case STATE_DATA_BUSY:`, after `EVENT_DATA_COMPLETE` and
`dw_mci_stop_fault_timer()`, **before** `host->data = NULL`, the code
now calls `dw_mci_stop_dma(host)`. That function stops the DMA engine if
`host->using_dma` and then runs `dma_ops->cleanup()`. Previously this
state only nulled `host->data` and completed the request.
**Step 2.3 — Bug mechanism**
Record: **Resource leak / DMA mapping leak.** `dw_mci_dma_cleanup()`
unmaps only when `host->data` is set and `host_cookie == COOKIE_MAPPED`.
Clearing `host->data` first made later cleanup a no-op.
Verified paths:
- Success: IDMAC/EDMAC `dw_mci_dmac_complete_dma()` already calls
cleanup, then `EVENT_XFER_COMPLETE` moves the machine into
`STATE_DATA_BUSY`. Second cleanup is a no-op (`COOKIE_UNMAPPED`).
- Error from `STATE_SENDING_DATA`: already calls `dw_mci_stop_dma()`.
- **DMA start failure then PIO fallback:** `dw_mci_submit_data_dma()`
sets `using_dma = 1` after a successful map, then on
`dma_ops->start()` failure calls `stop()` but **not** cleanup, and
**does not** clear `using_dma`. PIO then completes via
`STATE_DATA_BUSY`. Without this line the mapping is left. Verified:
`using_dma` is assigned only at lines 998 and 1010; PIO fallback
(lines 1070–1103) never clears it.
- `COOKIE_PRE_MAPPED` block I/O still unmaps in `dw_mci_post_req()`;
this change does not double-unmap that path.
**Step 2.4 — Fix quality**
Record: **Obviously correct** and matches the other data-path states.
Cleanup is idempotent. `dw_mci_start_request()` zeros `pending_events`,
so the extra `EVENT_XFER_COMPLETE` bit from `dw_mci_stop_dma()` does not
leak into the next request. **Regression risk: low.**
`dmaengine_terminate_async()` / IDMAC reset after a completed transfer
is the same stop used on errors; IDMAC start already resets the engine.
## Phase 3: Git history
**Step 3.1 — Blame**
Record: `host->data = NULL` in `STATE_DATA_BUSY` is from
**f95f3850f7a9e1** (Will Newton, 2011-01-02), first in **v2.6.38**. The
hole is old.
**Step 3.2 — Fixes: tag**
Record: **None.** Related older fix **faecf41106123** (“fix unmap sg
twice when finding data err”, 2016) made cleanup skip IDMAC complete
when `EVENT_DATA_ERROR` is set, so `stop_dma()` is the unmap path on
errors. That makes missing `stop_dma()` in `STATE_DATA_BUSY` more
important, not less.
**Step 3.3 — File history**
Record: Recent dw_mmc work is refactor (board struct, PM macros). This
commit is standalone, not `N/M`. No follow-up in `cb3fcb8d118b8..HEAD`
except an unrelated `dw_mci_pmops` move.
**Step 3.4 — Author**
Record: Marek Szyprowski is the DMA-mapping maintainer; first dw_mmc
commit in this file. Shawn Lin (dw_mmc maintainer) reviewed it. Ulf
Hansson applied it.
**Step 3.5 — Dependencies**
Record: **None.** It only calls existing `dw_mci_stop_dma()`. Applies
standalone.
## Phase 4: Mailing list
**Step 4.1**
Record: https://patch.msgid.link/20260603083935.3201411-1-
m.szyprowski@samsung.com
**v1 only** (no v2/v3). Thread (3 messages via `b4 dig -m`):
1. Patch (3 Jun 2026)
2. Shawn Lin: Reviewed-by
3. Ulf Hansson: “Applied for next, thanks! Please, let me know if you
think there is reason to tag this for stable kernels too.” **No
reply** in the thread.
**Step 4.2**
Record: CCs were linux-mmc, Jaehoon Chung, Shawn Lin, Ulf Hansson — the
right maintainers.
**Step 4.3**
Record: No syzbot/bugzilla. Author describes a mapping leak, not a crash
log.
**Step 4.4**
Record: Standalone, not part of a series.
**Step 4.5**
Record: **UNVERIFIED** — lore.kernel.org/stable is behind bot protection
(403/Anubis). linux-mmc thread has Ulf’s open stable question and no
nomination.
## Phase 5: Code semantics
**Step 5.1**
Record: Modified: `dw_mci_work_func`. Callee: `dw_mci_stop_dma` →
`dma_ops->stop` / `dma_ops->cleanup` (`dw_mci_idmac_stop_dma` or
`dw_mci_edmac_stop_dma`, then `dw_mci_dma_cleanup`).
**Step 5.2**
Record: `dw_mci_work_func` is the host BH work (`host->bh_work`), queued
from IRQ/timeout/DMA complete. Reachable on every data transfer for this
host.
**Step 5.3**
Record: Completes MMC requests (`dw_mci_data_complete`,
`dw_mci_request_end` → `mmc_request_done`).
**Step 5.4**
Record: Userspace (block I/O, ioctl, card init) triggers it via the MMC
core. **Yes, reachable from userspace** on DW MMC hardware.
**Step 5.5**
Record: Same `dw_mci_stop_dma()` already used in `STATE_SENDING_CMD`
(cmd+data error) and twice in `STATE_SENDING_DATA`. This fills the
missing sibling.
## Phase 6: This tree
**Step 6.1**
Record: Tree is **v7.3-rc4** (`git describe`:
`v7.3-rc4-27-gf0100363d8c37`, `VERSION=7 PATCHLEVEL=3`). Candidate **is
an ancestor of HEAD**. Buggy pattern existed here before that commit;
introduced in v2.6.38.
**Step 6.2**
Record: **Clean apply** on this tree (already applied). Context
(`dw_mci_stop_fault_timer` then `host->data = NULL`) is present.
**Step 6.3**
Record: No other fix for this hole. faecf41106123 is a related double-
unmap fix, not a substitute.
## Phase 7: Subsystem
**Step 7.1**
Record: **MMC host (Synopsys DesignWare).** **IMPORTANT** — eMMC/SD on
Exynos, Rockchip, Hisilicon, StarFive, BlueField, K3 (`MMC_DW_*` in
Kconfig). Not core mm/VFS, not staging.
**Step 7.2**
Record: File is actively maintained (refactors in 2026 plus this fix).
The state machine itself is old and stable.
## Phase 8: Impact and risk
**Step 8.1**
Record: **Driver-specific / config-specific** (`CONFIG_MMC_DW`). Large
ARM/embedded population.
**Step 8.2**
Record: Hits whenever `STATE_DATA_BUSY` finishes a DMA-using request
that did not already go through `stop_dma()`. Common path still unmaps
via the DMA complete callback or `post_req`. The leak is real on **DMA-
submit failure → PIO**, and on any DATA_BUSY completion that never ran
complete/stop. Unprivileged block I/O can reach the host.
**Step 8.3**
Record: **DMA mapping leak.** Leftover mappings: DMA-API warnings, IOMMU
table growth, coherency issues if pages are reused while still mapped.
**Severity: HIGH** on the leak path, **MEDIUM** overall because the hot
success path already unmaps.
**Step 8.4**
Record: **Benefit: high** for DW MMC users (correct DMA lifetime, stop
IDMAC after data-complete). **Risk: very low** (1 line, idempotent
cleanup). **Ratio: favorable.**
## Phase 9: Synthesis
**For backporting**
- Real DMA-mapping leak; author is the DMA-mapping maintainer.
- One line, same helper already used in sibling states.
- dw_mmc co-maintainer Reviewed-by; MMC maintainer applied it.
- Hardware is common; bug dates to v2.6.38.
- Cleanup is idempotent; next request clears pending events.
- No series dependency, no follow-up revert.
**Against**
- No Fixes:/Cc: stable (expected in this pipeline).
- Ulf explicitly asked whether it belonged in stable; author never
answered.
- No crash/syzbot report; success-path unmap often already happened.
- Leak is most clearly proven on the DMA-start-failure → PIO path, not
every transfer.
**Unresolved**
- No stable@ discussion found (lore blocked).
- Exact reproducer Marek hit is not in the mail (only the mechanism).
**Stable rules**
1. Obviously correct and tested? **PASS** — 1-line, reviewed, in
mainline since 2026-07-06.
2. Real user-affecting bug? **PASS** — leftover DMA mappings on DW MMC.
3. Important (crash/security/corruption/deadlock)? **PASS** — mapping
leak can WARN, exhaust IOMMU, and cause coherency bugs; not a panic,
but it is a real DMA-lifetime bug, not style.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features/APIs? **PASS**.
6. Applies to this tree? **PASS**.
**Exception category:** none (not a device ID / quirk / DT / build / doc
patch). It is a normal contained bugfix.
Ulf’s “tag for stable?” question is caution, not a NAK. The instructions
say missing stable tags must not drive a NO. On technical merit this
belongs in stable: tiny, correct, and it closes a DMA unmap hole in a
widely deployed MMC host.
Verification:
- [Phase 1] Parsed tags: Marek SOB, Shawn Lin R-b, Ulf SOB; no
Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: +1 line `dw_mci_stop_dma(host)` in `STATE_DATA_BUSY`
before `host->data = NULL`
- [Phase 2] `dw_mci_stop_dma`/`dw_mci_dma_cleanup` read; cleanup gated
on `COOKIE_MAPPED`
- [Phase 2] IDMAC/EDMAC complete path already calls cleanup; `using_dma`
not cleared on DMA-start failure (lines 998, 1010, 1039–1045, 1070)
- [Phase 3] blame: f95f3850f7a9e1 (v2.6.38); candidate cb3fcb8d118b8;
related faecf41106123 double-unmap
- [Phase 3] `git merge-base --is-ancestor cb3fcb8d118b8 HEAD` — true; no
follow-up fix on dw_mmc.c
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 only; Shawn R-b; Ulf applied and
asked about stable; no author reply
- [Phase 4] lore WebFetch 403; mbox used instead
- [Phase 5] callers: BH work from IRQ/DTO/DMA complete; userspace via
MMC core
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4
- [Phase 7] MAINTAINERS: Jaehoon Chung, Shawn Lin; Kconfig MMC_DW_*
platforms
- [Phase 8] Failure mode: DMA mapping leak, severity HIGH on leak path
- UNVERIFIED: stable@ archive search (Anubis); exact runtime stack Marek
saw
**YES**
drivers/mmc/host/dw_mmc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index c5db92bbb0946..90cc41901edaa 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2213,6 +2213,7 @@ static void dw_mci_work_func(struct work_struct *t)
}
dw_mci_stop_fault_timer(host);
+ dw_mci_stop_dma(host);
host->data = NULL;
set_bit(EVENT_DATA_COMPLETE, &host->completed_events);
err = dw_mci_data_complete(host, data);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] libbpf: Fix ring buffer consumer loop on 32-bit position wrap
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (73 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] mmc: dw_mmc: stop and complete DMA also in STATE_DATA_BUSY state Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] wifi: mt76: mt7921: fix memory leak when skb_linearize fails in mcu rx event Sasha Levin
` (441 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Israel Téllez García, Andrii Nakryiko, Sasha Levin,
eddyz87, ast, daniel, memxor, bpf, linux-kernel
From: Israel Téllez García <i.tellez@btesa.com>
[ Upstream commit fdd4fad0bbbd08501465c5f9b556963093c5d58a ]
ringbuf_process_ring() walks the records between the consumer and the
producer with an ordering comparison:
while (cons_pos < prod_pos) {
cons_pos and prod_pos mirror the kernel's ring positions and are
unsigned long here too, so on 32-bit they wrap at 2^32 bytes of traffic.
When producer_pos has wrapped and consumer_pos has not, prod_pos is the
smaller of the two, the loop body never runs and no record is consumed.
Since consumer_pos only advances inside that loop, it never wraps either
and the consumer stops delivering samples for good, with no error
returned to the caller: ring_buffer__poll() keeps reporting zero
records while the kernel side fills up and starts dropping.
Compare the distance instead. The consumer never runs ahead of the
producer, so prod_pos - cons_pos is the amount of unconsumed data and
stays correct across the wrap.
64-bit hosts are unaffected in practice: the counters would need 16 EiB
to wrap. This is the userspace counterpart of the kernel-side walk fixed
in "bpf: Fix pending_pos walk on 32-bit ring position wrap"; a 32-bit
consumer hits whichever of the two comes first.
Signed-off-by: Israel Téllez García <i.tellez@btesa.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260814124843.22041-5-i.tellez@btesa.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit message forensics
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[libbpf] [Fix] ring buffer consumer loop on 32-bit position
wrap**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Signed-off-by:** Israel Téllez García `<i.tellez@btesa.com>`
(author)
- **Signed-off-by:** Andrii Nakryiko `<andrii@kernel.org>` (libbpf/BPF
maintainer)
- **Link:** `https://lore.kernel.org/bpf/20260814124843.22041-5-
i.tellez@btesa.com`
- No `Reported-by`, `Tested-by`, `Reviewed-by`, `Acked-by`, or `Cc:
stable` on the original patch
- Original submission had **no `Fixes:` tag**. `b4 am` later attached a
lore trailer: `Fixes: bf99c936f947 ("libbpf: Add BPF ring buffer
support")` (DKIM/kernel.org). That SHA is the 2020 introduction of BPF
ringbuf in libbpf, and it is in this tree.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `ringbuf_process_ring()` uses `while (cons_pos < prod_pos)`
on `unsigned long` positions. On 32-bit those wrap at 2^32 bytes.
After producer wrap, `prod_pos` is small and `cons_pos` is still
large, so the loop never runs.
- **Symptom:** `ring_buffer__poll()` / consume APIs keep returning 0
with no error; the kernel ring fills and drops samples permanently.
- **Root cause:** ordering comparison is not wrap-safe; consumer_pos
only advances inside that loop, so it never wraps either.
- **Version info:** 64-bit is unaffected in practice (16 EiB to wrap).
Explicitly the userspace counterpart of the kernel `pending_pos` walk.
Field data for that sibling: four armv7 i.MX7 Dual devices on 6.6.52
stalled after exactly 4295491360 bytes (~2^32 + one 512 KiB ring).
- **Author’s fix:** `prod_pos - cons_pos > 0` (unsigned distance).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. Subject and body describe a real wrap-induced stall.
Not cleanup/refactor.
---
## Phase 2: Diff analysis
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `tools/lib/bpf/ringbuf.c` — **1 line changed** (`+1 / -1`)
- Function: `ringbuf_process_ring()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `while (cons_pos < prod_pos)` — fails after producer wrap
on 32-bit.
- **After:** `while (prod_pos - cons_pos > 0)` — unsigned modular
distance; stays true while unconsumed data exists.
- Path: normal consume path (`ring_buffer__poll` / `__consume` /
`__consume_n` / `ring__consume*`), not an error/init-only path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** logic/correctness (32-bit wrap / unsigned comparison)
- **Mechanism:** same class as kernel `pending_pos`. Unsigned `unsigned
long` counters are documented to wrap
(`Documentation/bpf/ringbuf.rst`). Distance arithmetic is already used
in this tree in `ring__avail_data_size()` (`return prod_pos -
cons_pos`) and kernel `ringbuf_avail_data_sz()`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: matches the kernel-side pattern already in this
tree (`while (prod_pos - pend_pos > 0)` in `kernel/bpf/ringbuf.c`).
- Minimal: one condition.
- Regression risk: low. On 64-bit equivalent until astronomical wrap. If
consumer ever ran ahead of producer, the new check would wrap and keep
looping; the author and kernel invariant say that does not happen.
Same assumption the kernel pending_pos fix already shipped here.
---
## Phase 3: Git history investigation
**Step 3.1: BLAME THE CHANGED LINES**
Record: Buggy `while (cons_pos < prod_pos)` introduced in
**`bf99c936f9478`** (“libbpf: Add BPF ring buffer support”, 2020-06-01)
by Andrii Nakryiko. Present since BPF ringbuf existed. Surrounding `cnt
>= n` bits are later (`13e8125a22763`, 2024) and unrelated.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: Original mail had no `Fixes:`. Trailer names `bf99c936f947`,
which **is in this tree**. Kernel sibling `19de99ea47e3c` (“bpf: Fix
pending_pos walk on 32-bit ring position wrap”) **is already in this
tree**; its `Fixes:` target `cfa1a2329a691` is also here.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Recent `tools/lib/bpf/ringbuf.c` commits are consume_n
overflow/return-value fixes, not wrap handling. This is standalone:
series patch 4/4. Cover letter: patches 1–3 are kernel; 4 is libbpf.
Patches 2–3 are overwrite-mode `ringbuf_avail_data_sz()` —
**overwrite_pos does not exist in this 6.12 tree**. Nakryiko dropped
patch 3 anyway.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Israel Téllez García authored the kernel wrap fix already on
this branch (`19de99ea47e3c`). Andrii Nakryiko (libbpf maintainer)
applied both.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: No code dependency. One-line condition change in a function that
already exists. `git apply --check` on the original mbox succeeded (exit
0). Does not need overwrite-mode patches.
---
## Phase 4: Mailing list and external research
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Series: **[PATCH v2 bpf 0/4] bpf: Fix ring buffer position wrap
handling on 32-bit**
- Lore: `https://lore.kernel.org/bpf/20260814124843.22041-1-
i.tellez@btesa.com`
- This patch: `...22041-5-i.tellez@btesa.com` (4/4)
- v1: `https://lore.kernel.org/bpf/20260806130214.66028-1-
i.tellez@btesa.com/` (kernel pending_pos only; v2 added sites 2–4)
- v2 change for patch 1: drop `(long)` cast per Nakryiko; unsigned
difference is enough
- Cover: patch 1 was the field-observed stall; patch 4 is the userspace
counterpart. “A 32-bit consumer hits whichever of the two comes
first.”
- No NAK on patch 4. Patch 3 was dropped by both author and Nakryiko
(ordering of overwrite_pos loads).
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc included Andrii Nakryiko, Alexei
Starovoitov, Daniel Borkmann, Eduard Zingerman, Martin KaFai Lau, Song
Liu, Jiri Olsa, `bpf@vger.kernel.org`. Applied by Nakryiko.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla for the libbpf loop itself. Field evidence is
on the kernel sibling: four armv7 devices, exact 2^32-byte trigger, 8–17
h uptime, one patched device then passed 10 GiB. Cover: “Userspace kept
consuming normally until the producer stopped” — meaning the kernel
stall fired first. Once that kernel fix is in (it is, here), this libbpf
loop is the next wrap failure.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record:
1. Kernel pending_pos — **already in this tree**
2. Overwrite-mode avail-data — **N/A here** (no overwrite_mode)
3. producer_pos vs overwrite_pos load order — dropped; **N/A here**
4. **This libbpf loop** — candidate
- User-ringbuf peek (`u64` locals, `cons_pos >= prod_pos`) was called
out as a separate issue and is **not** this commit. Confirmed still
present at `kernel/bpf/ringbuf.c:687`.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — lore.kernel.org/stable returned Anubis bot-
challenge (403/HTML). No stable-list discussion retrieved.
---
## Phase 5: Code semantic analysis
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `ringbuf_process_ring()` only. (semcode MCP not available; used
hunk headers + grep.)
**Step 5.2: TRACE CALLERS**
Record: All in-tree callers of `ringbuf_process_ring()`:
- `ring_buffer__consume_n()`
- `ring_buffer__consume()`
- `ring_buffer__poll()`
- `ring__consume_n()` / `ring__consume()`
These are the public libbpf ringbuf consume APIs. Reachable from any
userspace consumer of `BPF_MAP_TYPE_RINGBUF` (tracing, networking,
etc.). `bpftool` in this tree links `tools/lib/bpf`.
**Step 5.3: TRACE CALLEES**
Record: `smp_load_acquire` on positions/len, `roundup_len()`,
`r->sample_cb()`, `smp_store_release` of consumer_pos. No
allocation/locking in the changed condition.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace path: app/bpftool → `ring_buffer__poll/consume` →
`ringbuf_process_ring`. Trigger: ~4 GiB cumulative ring traffic on
32-bit. Unprivileged if the process already has the map fd (typical
tracing daemon). Not a kernel oops, but permanent event loss.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record:
- Same buggy compare in
`tools/testing/selftests/bpf/benchs/bench_ringbufs.c:305` (benchmark
only; not this commit).
- Wrap-safe distance already in `ring__avail_data_size()` and kernel
`ringbuf_avail_data_sz()`.
- Kernel pending_pos already converted to distance in this tree.
---
## Phase 6: Cross-referencing against the local tree
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Local tree is **6.12.111** (`git describe`:
`p-6.12-3-gc504cf0baa3d8`, Makefile `VERSION=6 PATCHLEVEL=12
SUBLEVEL=111`).
```247:247:tools/lib/bpf/ringbuf.c
while (cons_pos < prod_pos) {
```
`struct ring` uses `unsigned long *consumer_pos` / `*producer_pos`
(lines 29–30). Bug introduced in v5.8-era libbpf ringbuf
(`bf99c936f9478`), long before 6.12. Positions are still `unsigned long`
in kernel `struct bpf_ringbuf`.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply.** `git apply --check` on the original patch mbox
exited 0. Function shape matches the hunk (`ringbuf_process_ring(struct
ring *r, size_t n)` with `cons_pos`/`prod_pos` as `unsigned long`).
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Kernel pending_pos wrap fix **is** here (`19de99ea47e3c`).
Userspace loop still has `cons_pos < prod_pos`. No alternate libbpf wrap
fix in this file.
---
## Phase 7: Subsystem and maintainer context
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **libbpf** (`tools/lib/bpf/`) — userspace helper shipped with
the kernel, used by bpftool and in-tree BPF tools. Criticality:
**IMPORTANT** for BPF users, especially 32-bit embedded collectors. Not
core mm/sched, but this tree already backports libbpf ringbuf fixes
(`087d757fb4736`, `00f0e08f23fc0`).
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained; libbpf ringbuf APIs grew through 6.12
(`ring__consume_n`, etc.). The wrap bug is old (2020), not a new-feature
leftover.
---
## Phase 8: Impact and risk assessment
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Config/platform-specific:** 32-bit hosts using in-tree libbpf
to consume `BPF_MAP_TYPE_RINGBUF` (armv7/i.MX and similar LTS/embedded).
64-bit unaffected in practice.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: After ~4 GiB of ring traffic, if producer wraps while consumer
still has unconsumed bytes. Common with epoll/batching. Timing-dependent
at the wrap, then **sticky forever**. Unprivileged if the process
already holds the map. The sibling bug was reproduced at 441–862
records/s over hours — not a theoretical corner.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Permanent silent stop of sample delivery; kernel then drops
events; APIs return 0 with no error. **HIGH** data/event loss (not a
kernel oops). Restart of the consumer is required.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit: high for 32-bit BPF consumers.** Kernel producer wrap is
already fixed here, so this is now the remaining stall. Same class as
a field-proven 6.6.52 armv7 outage.
- **Risk: very low.** One comparison, same idiom as kernel code already
on this branch.
- Ratio: strongly favors backport.
---
## Phase 9: Final synthesis
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real wrap bug; documented that 32-bit positions wrap
- Permanent silent event loss, no error
- One-line, obviously correct, applies cleanly
- Kernel counterpart already in this 6.12.y tree — without this,
producer keeps going and userspace is the next stall
- Field-proven sibling on armv7 (core LTS/embedded)
- Maintainer SOB (Nakryiko); v2 reviewed
- No new APIs; no overwrite-mode dependency
**AGAINST:**
- Userspace libbpf (some distros use github libbpf, not in-tree)
- 32-bit only in practice
- Original field report hit kernel pending_pos first
- No `Cc: stable` on the original mail (expected for this review queue;
not a negative)
**UNRESOLVED:**
- Could not query lore.kernel.org/stable (bot wall)
- Could not confirm whether standalone libbpf already carries this
(irrelevant: verdict is for in-tree `tools/lib/bpf`)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — same unsigned-distance idiom
as kernel code already here; series tested on armv7 for the sibling;
maintainer applied it.
2. Fixes a real bug that affects users? **PASS** — 32-bit ringbuf
consumers stall after wrap.
3. Important issue (crash, security, corruption, deadlock)? **PASS** at
HIGH — permanent silent event loss, not an oops, but equivalent
operational failure for tracing/telemetry.
4. Small and contained? **PASS** — 1 line, 1 file.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — `git apply --check`
succeeded; buggy loop present.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/docs exception. Ordinary small bugfix.
**Step 9.4: DECISION**
This belongs on **this** 6.12.y tree. The buggy `cons_pos < prod_pos`
loop is here; the matching kernel wrap fix is already here; the one-line
change applies cleanly and closes the remaining 32-bit stall for in-tree
libbpf consumers.
### What the commit solves and why it matters here
On 32-bit, ring positions are 32-bit `unsigned long` and are documented
to wrap. After producer wrap, the consumer loop never runs, never
advances `consumer_pos`, and never recovers. `ring_buffer__poll()`
reports 0 forever while the kernel drops samples. 6.12.y already
contains the kernel `pending_pos` wrap fix, so a 32-bit producer can now
wrap; this userspace loop is the next failure. 32-bit ARM collectors are
a real LTS audience (the sibling was seen on i.MX7 Dual).
### Risk vs benefit
Benefit is high for 32-bit BPF ringbuf users; risk is a one-line
comparison already used in-kernel on this branch.
---
### Verification
- **[Phase 1]** Parsed subject/tags/body from the candidate and from
`/tmp/ringbuf-mbox/wrap-p5`; `Fixes:` only as a later lore trailer to
`bf99c936f947`
- **[Phase 2]** Diff is one condition in `ringbuf_process_ring()`;
current tree still has `while (cons_pos < prod_pos)` at line 247
- **[Phase 3]** `git blame` → `bf99c936f9478` (2020); `git merge-base
--is-ancestor` confirms that SHA, `cfa1a2329a691`, and kernel wrap fix
`19de99ea47e3c` are in HEAD
- **[Phase 3]** `git log --oneline -- tools/lib/bpf/ringbuf.c` — no
userspace wrap fix present
- **[Phase 4]** `b4 dig -c 19de99ea47e3c -a/-w` → v2 4-patch series;
this is 4/4
- **[Phase 4]** Cover letter and patches from `/tmp/ringbuf-
series/*.cover` and `.mbx`; Nakryiko dropped patch 3 (`/tmp/ringbuf-
mbox/nakryiko`)
- **[Phase 4]** lore.kernel.org HTTP 403 / Anubis; used `b4` mboxes
instead
- **[Phase 5]** grep callers of `ringbuf_process_ring` in
`tools/lib/bpf/ringbuf.c`; public consume/poll APIs
- **[Phase 6]** `git describe HEAD` → `p-6.12-3-gc504cf0baa3d8`; `make
kernelversion` → `6.12.111`
- **[Phase 6]** `git apply --check /tmp/ringbuf-mbox/wrap-p5` exit 0
- **[Phase 6]** `overwrite_pos` / `overwrite_mode` absent from
`kernel/bpf/ringbuf.c` in this tree
- **[Phase 7/8]** `Documentation/bpf/ringbuf.rst` documents 32-bit wrap;
kernel sibling commit describes four armv7 devices
- **UNVERIFIED:** stable@ lore discussion; whether distro standalone
libbpf already has this
**YES**
tools/lib/bpf/ringbuf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
index 00ec4837a06de..c8fe57401a8b5 100644
--- a/tools/lib/bpf/ringbuf.c
+++ b/tools/lib/bpf/ringbuf.c
@@ -244,7 +244,7 @@ static int64_t ringbuf_process_ring(struct ring *r, size_t n)
do {
got_new_data = false;
prod_pos = smp_load_acquire(r->producer_pos);
- while (cons_pos < prod_pos) {
+ while (prod_pos - cons_pos > 0) {
len_ptr = r->data + (cons_pos & r->mask);
len = smp_load_acquire(len_ptr);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] wifi: mt76: mt7921: fix memory leak when skb_linearize fails in mcu rx event
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (74 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] libbpf: Fix ring buffer consumer loop on 32-bit position wrap Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] PCI: switchtec: Add Microchip PCI1008 device ID Sasha Levin
` (440 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Prashant Rahul, Felix Fietkau, Sasha Levin, lorenzo, ryder.lee,
matthias.bgg, angelogioacchino.delregno, linux-wireless,
linux-kernel, linux-arm-kernel, linux-mediatek
From: Prashant Rahul <prashantrahul23@gmail.com>
[ Upstream commit 4361f1660101270611eb5dc39799f620b35f2e4d ]
The ownership of sk_buff skb is passed to mt7921_queue_rx_skb, each
path inside it under the switch case handles cleaning of skb and it
is true for mt7921_mcu_rx_event as well.
mt7921_mcu_rx_event, on a success path, either queues skb via
mt76_mcu_rx_event or cleans it immediately inside
mt7921_mcu_uni_rx_unsolicited_event.
However inside mt7921_mcu_rx_event, if skb_linearize fails, the function
returns immediately and never bothers cleaning skb which leaks skb.
Since skb is fully owned at this point, it is safe to call
dev_kfree_skb which fixes the leak.
Granted, the skb_linearize failure is rare as it can only fail under
heavy memory usage, but at the same time, leaking memory under heavy
memory usage can worsen the OOM condition.
Signed-off-by: Prashant Rahul <prashantrahul23@gmail.com>
Link: https://patch.msgid.link/20260716-mt7921-mem-leak-v1-1-6e9c0ea19f63@gmail.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable backport analysis: mt7921 MCU RX skb leak
**Tree decided:** `pending-6.6` (6.6.157), SHA `04810563abb71`.
At the start of this evaluation `git describe`/`make kernelversion`
reported **6.6.157**. The working copy later moved to v7.3-rc4; every
presence/absence claim below was rechecked against **`pending-6.6`**,
not that later checkout.
The candidate is mainline `4361f16601012` (`wifi: mt76: mt7921: fix
memory leak when skb_linearize fails in mcu rx event`).
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1 — Subject**
Record: **[wifi: mt76: mt7921]** **[fix]** memory leak when
`skb_linearize` fails in MCU RX event.
**Step 1.2 — Tags**
- `Signed-off-by: Prashant Rahul <prashantrahul23@gmail.com>` (author)
- `Link: https://patch.msgid.link/20260716-mt7921-mem-
leak-v1-1-6e9c0ea19f63@gmail.com`
- `Signed-off-by: Felix Fietkau <nbd@nbd.name>` (mt76 maintainer;
applied the patch)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence of Fixes/Cc-stable is expected for this
review).
Record: Maintainer SOB; msgid shows **v1 patch 1/1** (standalone).
**Step 1.3 — Body**
Record:
- **Bug:** `mt7921_queue_rx_skb` transfers skb ownership into
`mt7921_mcu_rx_event`. Success paths free or queue the skb. If
`skb_linearize()` fails, the function returns without freeing.
- **Symptom:** skb leak. Author notes failure is rare (ENOMEM) but
leaking under memory pressure can worsen OOM.
- **Root cause:** missing `dev_kfree_skb` on the linearize error path.
- **Version info in message:** none.
**Step 1.4 — Hidden bug fix?**
Record: **No disguise.** This is an explicit leak fix, not cleanup-as-
fix.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1 — Inventory**
Record:
- File: `drivers/net/wireless/mediatek/mt76/mt7921/mcu.c` (**+3 / −1**)
- Function: `mt7921_mcu_rx_event`
- Scope: **single-file surgical fix**
**Step 2.2 — Flow**
Before (pending-6.6 `mcu.c:312-313`):
```
if (skb_linearize(skb))
return;
```
After:
```
if (skb_linearize(skb)) {
dev_kfree_skb(skb);
return;
}
```
Record: **error path only.** Success paths unchanged.
**Step 2.3 — Bug mechanism**
Record: **[resource leak]** On `skb_linearize` failure (`-ENOMEM` for
nonlinear skbs), the still-owned skb is dropped. Caller
`mt7921_queue_rx_skb` does not free after `PKT_TYPE_RX_EVENT`. Other
switch arms in the same caller (`dev_kfree_skb` / `napi_consume_skb`)
and other arms of `mt7921_mcu_rx_event` (`dev_kfree_skb`,
`mt76_mcu_rx_event` queue) already consume the skb.
**Step 2.4 — Fix quality**
Record: **Obviously correct.** Matches established kernel pattern (`if
(skb_linearize(skb)) { dev_kfree_skb(_any)(skb); return; }`). Same free
helper already used in this MCU event path. No API/lock/data-structure
change. Regression risk: **very low** (could only be a double-free if
linearize already freed; it does not — see Phase 5).
---
## PHASE 3: GIT HISTORY
**Step 3.1 — Blame**
Record: Leak introduced by **`f0ff5d3aa64812`** (`mt76: mt7921: make all
event parser reusable between mt7921s and mt7921e`, Sean Wang,
2021-10-19). That commit added `skb_linearize` + early return and never
freed on failure. Present since ~5.16-era; **`git merge-base --is-
ancestor f0ff5d3aa64812 pending-6.6` succeeds.**
**Step 3.2 — Fixes: tag**
Record: **None.** Introducer identified by blame: `f0ff5d3aa64812`,
which **is** in this 6.6 tree.
**Step 3.3 — File history (pending-6.6)**
Recent 6.6 work on this file is CLC firmware validation, not MCU RX. No
competing leak fix. Record: **standalone**; not part of a multi-patch
series.
**Step 3.4 — Author**
Prashant Rahul has **no other commits** in this tree’s mt76 history.
Applied by **Felix Fietkau**, listed maintainer of MEDIATEK MT76 in
`MAINTAINERS`. Record: one-off contributor; **maintainer-applied**.
**Step 3.5 — Dependencies**
The hunk only needs `mt7921_mcu_rx_event` + `skb_linearize` +
`dev_kfree_skb`, all present. Mailing-list patch context matches 6.6
(the extra `MCU_EVENT_RSSI_NOTIFY` in later mainline is **below** the
change). Record: **applies standalone**.
---
## PHASE 4: MAILING LIST / EXTERNAL
**Step 4.1 — Original discussion**
- `b4 dig -c <msgid>` / `b4 mbox`: no match (404).
- lore.kernel.org: **403**.
- Recovered from Openwall and Ratatoskr:
https://lists.openwall.net/linux-kernel/2026/07/16/1707
msgid `20260716-mt7921-mem-leak-v1-1-6e9c0ea19f63@gmail.com`
Record: **v1, single patch**, applied as submitted (`4361f16601012`
matches that diff). No v2/v3.
**Step 4.2 — Recipients (`b4 dig -w` unavailable; headers from
Openwall)**
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen, Sean Wang
(mt76 maintainers/reviewers), plus MediaTek ARM contacts. Cc: linux-
wireless, linux-kernel, linux-mediatek, linux-arm-kernel. Record:
**correct maintainer set**.
**Step 4.3 — Bug report**
Record: **No syzbot/bugzilla.** Static ownership analysis; author states
the leak is rare.
**Step 4.4 — Series**
Record: **1/1 standalone.** No sibling mt7925/mt7915 patches required
for this tree (only mt7921 has this `skb_linearize` in pending-6.6).
**Step 4.5 — Stable list**
Search for this subject on lore stable returned unrelated hits. Record:
**no prior stable NAK found** (lore 403 limited this).
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1 — Functions**
Record: `mt7921_mcu_rx_event` only.
**Step 5.2 — Callers**
`mt7921_queue_rx_skb()` (`mac.c`) `case PKT_TYPE_RX_EVENT:` calls it and
does **not** free afterwards.
That `rx_skb` hook is registered for **PCIe, USB, and SDIO**:
- `mt7921/pci.c`, `usb.c`, `sdio.c` → `.rx_skb = mt7921_queue_rx_skb`
- Invoked from `mt76_dma_rx_process` (NAPI), `mt76u` USB RX,
`mt76s_process_rx_queue` (SDIO)
Record: **hot RX path** for MT7921E/S/U.
**Step 5.3 — Callees**
`skb_linearize` → `__skb_linearize` → `__pskb_pull_tail`; returns
`-ENOMEM` on failure and **does not free** the skb
(`include/linux/skbuff.h`: “If there is no free memory -ENOMEM is
returned”). Success continues to `mt7921_mcu_uni_rx_unsolicited_event` /
`mt76_mcu_rx_event` / `mt7921_mcu_rx_unsolicited_event`.
**Step 5.4 — Reachability**
Nonlinear MCU events are real:
- SDIO `mt76s_build_rx_skb` uses `skb_add_rx_frag` when payload >
`MT_SKB_HEAD_LEN` — this is **why** `f0ff5d3aa64812` added linearize
(“paged fragment skb for the SDIO device”).
- USB `mt76u_build_rx_skb` same pattern.
- DMA `mt76_add_fragment` builds fraglists for multi-buffer RX.
Record: reachable from normal firmware MCU events; unprivileged users
can generate MCU traffic by using WiFi. Failure needs **ENOMEM during
linearize**.
**Step 5.5 — Similar patterns**
In pending-6.6, `skb_linearize` appears **only here** under mt76. No
duplicate site left unfixed in this tree.
---
## PHASE 6: LOCAL TREE (pending-6.6 / 6.6.157)
**Step 6.1 — Buggy code present?**
Record: **Yes.**
`pending-6.6:drivers/net/wireless/mediatek/mt76/mt7921/mcu.c:312-313`:
```
if (skb_linearize(skb))
return;
```
`git merge-base --is-ancestor 4361f16601012 pending-6.6` → **false**
(fix not here).
`git merge-base --is-ancestor f0ff5d3aa64812 pending-6.6` → **true**
(bug intro is here).
Bug age: **2021**, well before 6.6.
**Step 6.2 — Backport difficulty**
Submitted hunk is 4 lines around `skb_linearize` with context that
matches 6.6 (`struct mt76_connac2_mcu_rxd *rxd` then the if).
`MCU_EVENT_RSSI_NOTIFY` is later mainline-only context **below** the
edit. Record: **clean apply / trivial**.
**Step 6.3 — Related fixes already here?**
`git log --grep=skb_linearize` on mt76 in this tree: **empty**. No
alternate fix. Record: **none**.
---
## PHASE 7: SUBSYSTEM CONTEXT
**Step 7.1**
Record: **wifi / mt76 / mt7921**. Criticality: **IMPORTANT** — MT7921E
is a common laptop WiFi 6 adapter (PCIe); USB/SDIO variants exist
(`MT7921E/S/U` in Kconfig). Not core mm/net, not staging.
**Step 7.2**
Record: Mature driver (MCU support from `1c099ab44727c8`, 2021). 6.6
still receives mt76 bugfixes (CLC, etc.).
---
## PHASE 8: IMPACT AND RISK
**Step 8.1 — Who is affected**
Record: **driver-specific**, users with MediaTek MT7921 (very common on
laptops). Config: `CONFIG_MT7921E/S/U`.
**Step 8.2 — Trigger**
Record: Firmware MCU RX event whose skb is nonlinear, **and**
`skb_linearize` fails (GFP/ENOMEM). Unprivileged WiFi use can generate
events; the failure itself is **uncommon**. SDIO long events are the
originally cited nonlinear case; USB/DMA can also fragment.
**Step 8.3 — Failure mode**
Record: **skb leak under memory pressure**, which can deepen OOM. Not a
panic/UAF. Severity: **MEDIUM–HIGH** (hot-path leak, not a one-time
probe leak).
**Step 8.4 — Risk/benefit**
- Benefit: **medium** — stops a real leak on a widely shipped chip; most
valuable when the system is already under memory pressure.
- Risk: **very low** — 3 lines, error path, same free as sibling paths.
- Ratio: **favor backport**.
---
## PHASE 9: SYNTHESIS
**Step 9.1 — Evidence**
**For:**
- Real leak with verified ownership (caller does not free).
- Code and introducer are in 6.6.157; fix is not.
- Tiny, obviously correct, maintainer-applied.
- MT7921 is production hardware, not staging.
- Leak on an RX path under OOM is a stability issue, not a style
cleanup.
**Against:**
- Trigger is rare (`skb_linearize` ENOMEM).
- No crash/syzbot/CVE.
- No explicit `Cc: stable` (not a negative per the review rules).
**Unresolved:** Full lore thread (403/404); no reviewer comments beyond
maintainer merge. Does not change the technical verdict.
**Step 9.2 — Stable rules**
1. Obviously correct and tested — **PASS** (3-line ownership fix; in
mainline via Felix).
2. Real bug affecting users — **PASS** (skb leak on MT7921 MCU RX).
3. Important (crash/security/corruption/deadlock) — **PASS** as an RX-
path leak that can worsen OOM; not a panic, but in the leak class
stable regularly takes.
4. Small and contained — **PASS** (4 lines, one function).
5. No new features/APIs — **PASS**.
6. Can apply to this tree — **PASS** (hunk matches 6.6).
**Step 9.3 — Exceptions**
Record: none needed (not an ID/quirk/DT/build/doc exception). Ordinary
small leak fix.
**Step 9.4 — Decision**
Backport to **this** 6.6.157 tree. The bug exists here, the fix is
surgical, and regression risk is negligible.
---
## What the commit solves for stable users
On MT7921, firmware MCU events are handed to `mt7921_mcu_rx_event` with
full skb ownership. Nonlinear events (especially SDIO, also USB/DMA
fragments) are linearized first. If that allocation fails, 6.6 returns
and leaks the skb. Under memory pressure that leak makes OOM worse.
Adding `dev_kfree_skb(skb)` on that path closes the leak without
changing success behavior.
## Risk vs benefit
Benefit is a real leak fix on a common WiFi chip; risk is a three-line
error-path free that matches existing code in the same function.
## Concerns
None material: no prerequisites, no API change, no locking, expected
clean apply. Trigger rarity is the only weak point and is not enough to
reject a contained leak fix.
---
## Verification
- **[Phase 1]** Parsed tags: author SOB, Link msgid, Felix Fietkau SOB;
no Fixes/Reported-by/Cc-stable.
- **[Phase 2]** Diff: +3/−1 in `mt7921_mcu_rx_event`; adds
`dev_kfree_skb` on `skb_linearize` failure.
- **[Phase 3]** `git blame` on pending-6.6: leak from `f0ff5d3aa64812`
(2021-10-19); `git merge-base --is-ancestor f0ff5d3aa64812
pending-6.6` true.
- **[Phase 3]** `git show f0ff5d3aa64812`: added `if
(skb_linearize(skb)) return;` with no free.
- **[Phase 3]** `git log --author=Prashant Rahul`: no other mt76 commits
in this history.
- **[Phase 4]** Openwall/Ratatoskr: v1 1/1, same diff as
`4361f16601012`; mt76 maintainers on To:.
- **[Phase 4]** `b4 mbox` msgid: 404; lore.kernel.org: 403.
**UNVERIFIED:** full review replies / explicit stable nomination.
- **[Phase 5]** Callers: `mt7921_queue_rx_skb` (no free on
`PKT_TYPE_RX_EVENT`); hooked from pci/usb/sdio `.rx_skb`.
- **[Phase 5]** `skb_linearize` documented to return `-ENOMEM` and not
free; USB/SDIO `skb_add_rx_frag` makes nonlinear skbs.
- **[Phase 6]** `git describe` at start: `p-6.6-3-g04810563abb71`, `make
kernelversion` 6.6.157.
- **[Phase 6]** `git grep` on `pending-6.6`: leak at `mcu.c:312-313`.
- **[Phase 6]** `git merge-base --is-ancestor 4361f16601012 pending-6.6`
false.
- **[Phase 8]** Failure mode: skb leak under ENOMEM on MCU RX; severity
MEDIUM–HIGH.
- **UNVERIFIED:** complete lore thread text after 403.
The fix is small, matches stable leak-fix practice, and the buggy code
is in this 6.6 tree.
**YES**
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 8c8b35cba856c..f63ef02542387 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -354,8 +354,10 @@ void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_connac2_mcu_rxd *rxd;
- if (skb_linearize(skb))
+ if (skb_linearize(skb)) {
+ dev_kfree_skb(skb);
return;
+ }
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] PCI: switchtec: Add Microchip PCI1008 device ID
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (75 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] wifi: mt76: mt7921: fix memory leak when skb_linearize fails in mcu rx event Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:14 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.6] wifi: mac80211_hwsim: clear PMSR request state on abort Sasha Levin
` (439 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Logan Gunthorpe, Bjorn Helgaas, Sasha Levin, kurt.schwemmer,
linux-pci, linux-kernel
From: Logan Gunthorpe <logang@deltatee.com>
[ Upstream commit 0d8a6306c680ee534be131e360f0cafa2bada7be ]
Add the Microchip PCI1008 device ID to the core switchtec management
driver's PCI ID table. Without it, the management endpoint on a PCI1008
switch is not bound by this driver, preventing userspace tools from
configuring or monitoring the switch and leaving NTB functionality
unavailable.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260714212010.230606-3-logang@deltatee.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line PCI ID addition to an existing Switchtec driver. The
local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`).
`SWITCHTEC_PCI100X_DEVICE` and the PCI1001–PCI1006 IDs are already here,
so the patch is applicable.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: [PCI: switchtec] [Add] [Microchip PCI1008 device ID to the
existing switchtec management driver’s PCI ID table]
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Logan Gunthorpe <logang@deltatee.com> (author; listed
maintainer of PCI DRIVER FOR MICROSEMI SWITCHTEC)
- Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> (PCI maintainer)
- Link:
https://patch.msgid.link/20260714212010.230606-3-logang@deltatee.com
- No Fixes: tag (expected)
- No Reported-by / Tested-by / Reviewed-by / Acked-by / Cc: stable on
this commit
- Ignore any Sasha Levin SOB (none on the real commit)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: PCI1008 management endpoint is not bound because 0x1008 is
missing from `switchtec_pci_tbl`.
- Symptom: userspace cannot configure/monitor the switch via
`/dev/switchtecX`; NTB is unavailable (probe requests
`ntb_hw_switchtec` only after this driver binds).
- Version info: series was based on v7.2-rc3; applied by Helgaas for
v7.3.
- Root cause: incomplete ID table for a new PCI100x SKU, not a logic
bug.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a hidden cleanup. It is an explicit device-ID enablement.
Stable rules treat “just add a device ID” as an accepted class.
===============================================================
PHASE 2: DIFF ANALYSIS
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pci/switch/switchtec.c` (+1 / −0)
- Function/data: `switchtec_pci_tbl[]` (static PCI ID table)
- Scope: single-file, one-line surgical change
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: PCI1001–PCI1006 (vendor `PCI_VENDOR_ID_EFAR` / 0x1055) match
via `SWITCHTEC_PCI100X_DEVICE`; 0x1008 does not.
- After: 0x1008 matches the same way as 0x1001–0x1006, with `driver_data
= SWITCHTEC_GEN4`.
- Path: PCI enumeration → `pci_driver.id_table` match →
`switchtec_pci_probe()`.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- Category: hardware enablement / device ID addition
- Mechanism: without the ID, the management function is unbound. Probe
also does `request_module_nowait("ntb_hw_switchtec")` for
`PCI_CLASS_BRIDGE_OTHER`, so NTB never attaches.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: same macro and generation as sibling PCI100x IDs.
- Minimal: one table line, no API/behavior change for other devices.
- Regression risk: very low; only PCI1008 (vendor 0x1055, device 0x1008)
is newly bound.
- Red flags: none.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- PCI1001–PCI1006: `a3282f84b2151` (“PCI: switchtec: Add Microchip
PCI100X device IDs”, 2025-01-20), first described as
`v6.13-rc1-1-ga3282f84b2151`.
- Sentinel `{0}`: original driver from 2017 (`080b47def5e5e2`).
- PCI1008 line: this commit `0d8a6306c680e`.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Not applicable.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `a3282f84b2151` added the PCI100X macro, IDs 0x1001–0x1006, and
matching `SWITCHTEC_PCI100X_QUIRK` entries.
- Series companions (same author/date):
- `8b326de3cc02c` dmaengine: switchtec-dma: Add PCI1008 device ID
(msgid -2)
- `00a479ba1d012` PCI: switchtec: Add Microchip PCI1008 to NTB DMA
alias quirk (msgid -4)
- This commit is standalone for the management driver. The quirk is
needed for NTB DMA under IOMMU; DMA ID is a different PCI function.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Logan Gunthorpe is a listed maintainer (`MAINTAINERS`: PCI
DRIVER FOR MICROSEMI SWITCHTEC). He authored the original switchtec
driver and this ID series.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Needs `SWITCHTEC_PCI100X_DEVICE` and `SWITCHTEC_GEN4` — both present
here.
- Does not need the dmaengine or quirk commits to compile or bind the
management device.
- Applies standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 0d8a6306c680e`:
https://patch.msgid.link/20260714212010.230606-3-logang@deltatee.com
- Series: v1 only, `[PATCH v1 0/3] switchtec: add new device IDs`
(2026-07-14)
- Cover: IDs for PCI driver, DMA driver, and NTB quirk; based on
v7.2-rc3; intended for the PCI tree
- Sashiko: “found no issues” on this patch
- Bjorn Helgaas (2026-07-17): “Applied to pci/switchtec for v7.3,
thanks!”
- No NAKs. Unrelated Sashiko note on `quirk_switchtec_ntb_dma_alias()`
pointer arithmetic was explicitly not a blocker.
- No Cc: stable in the thread.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`):
- To: linux-pci, dmaengine, Vinod Koul, Bjorn Helgaas
- Cc: Frank Li, Kelvin Cao (Microchip)
- Vinod Acked-by on the dmaengine ID
- PCI maintainer applied the series
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot. Author is the subsystem maintainer adding a
new SKU. Cover letter says Sashiko reminded him the management ID and
NTB quirk were also required.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 3 independent one-line ID/quirk additions. This patch is 2/3 and
self-contained. Companion quirk is valuable for PCI1008 NTB+IOMMU but is
a separate candidate.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned HTTP 403. Thread mbox has
no “stable” mentions. UNVERIFIED: whether -stable already discussed this
ID.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: No function body changed. Data: `switchtec_pci_tbl[]`.
Consumers: `switchtec_pci_driver.id_table`, `MODULE_DEVICE_TABLE(pci,
...)`. Probe: `switchtec_pci_probe()`.
**Step 5.2: TRACE CALLERS**
Record: PCI core matches `id_table` at enumeration/hotplug. Probe
creates `/dev/switchtecX`, enables MRPC, and may load
`ntb_hw_switchtec`. NTB uses `class_interface` on `switchtec_class` (no
second PCI ID table).
**Step 5.3: TRACE CALLEES**
Record: Probe calls `stdev_create`, `switchtec_init_pci`,
`switchtec_init_isr`, `cdev_device_add`. Existing paths; ID only selects
them for this device.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable when a PCI1008 is present (`CONFIG_PCI_SW_SWITCHTEC`).
Unprivileged users do not enumerate PCI IDs; impact is hardware owners
of this switch.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same family already lists 0x1001–0x1006. DMA driver has 0x1008.
`quirks.c` has `SWITCHTEC_PCI100X_QUIRK(0x1008)` from the companion
commit.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `drivers/pci/switch/switchtec.c` has
`SWITCHTEC_PCI100X_DEVICE` and PCI1001–PCI1006. Without 0x1008, PCI1008
would not bind. Prerequisite `a3282f84b2151` is an ancestor (`git merge-
base --is-ancestor` succeeded). PCI100X support dates to v6.13-rc1.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply. Adjacent lines are the existing PCI100x block. No
refactor conflicts in this checkout.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No alternate PCI1008 ID in switchtec.c besides this line.
Companion DMA ID and NTB quirk are also present here as separate
commits.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: [PCI switch management driver `drivers/pci/switch/`] [PERIPHERAL
— specific Microchip/Microsemi Switchtec hardware; NTB/management users]
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature (driver since 2017). Recent work is mostly new IDs (Gen5,
Gen6, PCI100x). Typical stable ID-table churn.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific / config-specific (`CONFIG_PCI_SW_SWITCHTEC`).
Only PCI1008 (0x1055:0x1008). Other Switchtec IDs unchanged.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Trigger is plugging/booting with a PCI1008. Common for that
hardware; impossible otherwise. Not a userspace-triggerable crash.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Device not bound → no `/dev/switchtecX`, no NTB. Severity MEDIUM
for those systems (hardware unusable for management/NTB), LOW for
everyone else. Not a panic/UAF.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: high for PCI1008 owners (management + NTB enablement);
documented stable exception.
- Risk: very low (one ID line, existing macro).
- Ratio: strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Stable rules: “fix a real bug … or just add a device ID”
(`Documentation/process/stable-kernel-rules.rst`).
- Existing driver + PCI100X macro in this tree.
- One line, same pattern as PCI1001–PCI1006.
- Maintainer-authored, PCI maintainer applied, no NAKs.
- Real user impact: management chardev and NTB never attach without the
ID.
AGAINST:
- Not a crash/security fix; new SKU enablement only.
- Affects a niche PCIe switch.
- Companion quirk is a separate patch (NTB DMA under IOMMU still
incomplete without it). That does not make this ID wrong or unsafe.
UNRESOLVED:
- lore.kernel.org HTTP 403; stable@ discussion not verified beyond the
saved thread (no “stable” hits there).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — identical to existing
PCI100x entries; applied by PCI maintainer.
2. Fixes a real bug that affects users? **PASS** — PCI1008 otherwise
unbound (or qualifies as a device ID addition).
3. Important issue? **PASS** under the device-ID exception (not a
panic).
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS** — ID only; no new ioctls/sysfs.
6. Can apply to the local tree? **PASS** — `SWITCHTEC_PCI100X_DEVICE`
and sibling IDs present.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Device ID addition to an existing driver.
**Step 9.4: DECISION**
This is the standard stable device-ID case. The driver and PCI100x
helper exist in this tree, the change is one table line, and without it
PCI1008 management/NTB never bind. Risk is negligible.
The companion NTB DMA alias quirk is a separate one-line candidate; this
ID patch does not depend on it.
Verification:
- [Phase 1] Parsed tags: Logan Gunthorpe SOB, Bjorn Helgaas SOB, lore
Link; no Fixes/Reported-by/Cc: stable
- [Phase 1] `git describe HEAD` / Makefile: local tree is 7.3.0-rc4
(`v7.3-rc4-27-gf0100363d8c37`)
- [Phase 2] Diff: +1 line in `switchtec_pci_tbl[]` —
`SWITCHTEC_PCI100X_DEVICE(0x1008, SWITCHTEC_GEN4)`
- [Phase 2] Confirmed probe uses `id_table` and requests
`ntb_hw_switchtec` for bridge class
- [Phase 3] `git blame`: PCI1001–1006 from `a3282f84b2151` (v6.13-rc1);
PCI1008 from `0d8a6306c680e`
- [Phase 3] `git merge-base --is-ancestor a3282f84b2151 HEAD` succeeded
- [Phase 3] Series companions: `8b326de3cc02c` (DMA ID), `00a479ba1d012`
(NTB quirk)
- [Phase 4] `b4 dig -c 0d8a6306c680e`: lore URL found; v1-only 3-patch
series
- [Phase 4] `b4 dig -w`: linux-pci, Bjorn Helgaas, Vinod Koul, Microchip
Cc
- [Phase 4] mbox: Helgaas applied for v7.3; Sashiko clean on this patch;
Vinod Acked DMA ID; no NAK
- [Phase 4] UNVERIFIED: stable@ mailing list (lore HTTP 403)
- [Phase 5] NTB binds via `switchtec_class` class_interface; this ID is
required for NTB attach
- [Phase 6] File in tree has PCI100x macro and IDs; patch applies
cleanly
- [Phase 7] Maintainer entry: Logan Gunthorpe for Switchtec
- [Phase 8] Failure: device unbound, not a kernel crash; device-ID
exception applies
- [Phase 9] stable-kernel-rules.rst line 15 explicitly allows device ID
additions
**YES**
drivers/pci/switch/switchtec.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index f32ddfa79da99..30566c2d9f806 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1874,6 +1874,7 @@ static const struct pci_device_id switchtec_pci_tbl[] = {
SWITCHTEC_PCI100X_DEVICE(0x1004, SWITCHTEC_GEN4), /* PCI1004 16XG4 */
SWITCHTEC_PCI100X_DEVICE(0x1005, SWITCHTEC_GEN4), /* PCI1005 16XG4 */
SWITCHTEC_PCI100X_DEVICE(0x1006, SWITCHTEC_GEN4), /* PCI1006 16XG4 */
+ SWITCHTEC_PCI100X_DEVICE(0x1008, SWITCHTEC_GEN4), /* PCI1008 16XG4 */
{0}
};
MODULE_DEVICE_TABLE(pci, switchtec_pci_tbl);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] wifi: mac80211_hwsim: clear PMSR request state on abort
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (76 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] PCI: switchtec: Add Microchip PCI1008 device ID Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Limit mic boost on Positivo N15RPE-S Sasha Levin
` (438 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Zhao Li, Johannes Berg, Sasha Levin, johannes, linux-wireless,
linux-kernel
From: Zhao Li <enderaoelyther@gmail.com>
[ Upstream commit 37a77bd1395e8261d1760ae39c7f5eb637300550 ]
mac80211_hwsim saves the in-flight cfg80211 PMSR request and its wdev
in data->pmsr_request / data->pmsr_request_wdev when a measurement
starts, and clears them only when it reports completion.
mac80211_hwsim_abort_pmsr() never cleared that saved state. cfg80211
owns the request and frees it once the abort callback returns
(cfg80211_pmsr_process_abort() calls rdev_abort_pmsr() then
kfree(req)), so after an abort data->pmsr_request dangles. A later
hwsim PMSR report then dereferences the freed request in
hwsim_pmsr_report_nl() and completes it; a use-after-free.
Clear data->pmsr_request and data->pmsr_request_wdev once the abort
matches the active request. Move the wmediumd/virtio notification check
below the clear so the saved state is dropped even when no notification
is sent.
Assisted-by: Codex:gpt-5
Assisted-by: Claude:opus-4.8
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Link: https://patch.msgid.link/20260708195911.84365-2-enderaoelyther@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@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: **[wifi: mac80211_hwsim]** **[clear]** in-flight PMSR request
pointers when abort matches, so cfg80211’s free cannot leave a dangling
`data->pmsr_request`.
**Step 1.2: Tags**
Committed message (pipeline-stripped):
- Link: `https://patch.msgid.link/20260708195911.84365-2-
enderaoelyther@gmail.com`
- Assisted-by: Codex:gpt-5, Claude:opus-4.8
- Signed-off-by: Zhao Li; Johannes Berg
- No Fixes:/Cc: stable/Reported-by in the committed text (expected for
this pipeline)
Original mailing-list submission (from the saved mbox, not used as
circular “already selected” evidence):
- Fixes: `5530c04c87c5` (“mac80211_hwsim: add PMSR request support via
virtio”)
- Cc: `stable@vger.kernel.org`
- Cover letter: `[PATCH 0/8] wifi: fix PMSR lifetime and frame
validation issues`
**Step 1.3: Body**
Record:
- **Bug:** `mac80211_hwsim_abort_pmsr()` never NULLs
`data->pmsr_request` / `data->pmsr_request_wdev`. cfg80211 owns the
request and `kfree(req)` after `rdev_abort_pmsr()`.
- **Symptom:** later `hwsim_pmsr_report_nl()` uses the freed request →
use-after-free. Abort also leaves a non-NULL pointer so a new start
can see `-EBUSY` forever.
- **Root cause:** abort notifies wmediumd/virtio but does not drop saved
state; an early `return` when wmediumd/virtio is absent skips even the
mutex.
- **Version:** not stated in the message. Introduction is v6.4-rc1
(verified in Phase 3).
**Step 1.4: Hidden bug fix?**
Record: **No.** This is an explicit UAF fix, not cleanup disguised as a
fix.
---
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/net/wireless/virtual/mac80211_hwsim_main.c` (+7 / −3)
- Function: `mac80211_hwsim_abort_pmsr()` only
- Scope: single-file surgical fix
**Step 2.2: Flow change**
Record:
- **Before:** read `data->wmediumd`; if no wmediumd and no virtio,
**return unlocked** with saved pointers intact. If notification is
sent, still never NULL the pointers.
- **After:** take the mutex, match `data->pmsr_request == request`, then
set both pointers to NULL **before** the notification check. Missing
wmediumd/virtio is `goto out` (unlock), not an early return.
**Step 2.3: Bug mechanism**
Record: **Use-after-free / dangling pointer** (also a lifetime/refcount-
style leak of a cfg80211-owned object). cfg80211 frees the request;
hwsim keeps the pointer; `hwsim_pmsr_report_nl()` later calls
`cfg80211_pmsr_report()` / `cfg80211_pmsr_complete()` on it.
**Step 2.4: Fix quality**
Record: Obviously correct: abort that matches the in-flight request must
drop the saved pointers because cfg80211 will free the object. Mutex
already covers start/abort/report. Regression risk is low: a late report
after abort now hits `if (!data->pmsr_request) return -EINVAL`, which is
the intended post-abort behavior. No API/data-structure change.
---
## Phase 3: Git history
**Step 3.1: Blame**
Record: Pre-fix abort body is entirely from **`8ba1da95053e0`**
(“mac80211_hwsim: add PMSR abort support via virtio”, Jaewan Kim,
2023-03-22). Pointers are stored in **`5530c04c87c59`** (start/request
support, same day). First appears in **v6.4-rc1**. Present for a long
time in this lineage.
**Step 3.2: Fixes: target**
Record: Original Fixes: `5530c04c87c5` is an ancestor of HEAD (`git
merge-base --is-ancestor` exit 0). Closest actual miss is abort itself
(`8ba1da95053e0`), also an ancestor. Related: `2bef4d1fb8b34` (NULL
deref in `hwsim_pmsr_report_nl`, 2023) — different bug, already here.
**Step 3.3: File history**
Record: Neighbor `aeea930c7a878` (“authenticate PMSR report senders”) is
series patch 2/8, parent of this commit, **independent** (touches
`hwsim_pmsr_report_nl()`, not abort). File split `340f2ab83a5c9` / move
`f79cbc77abde2` already in this tree. No extra prerequisite for the
abort clear.
**Step 3.4: Author**
Record: Zhao Li is not the wireless maintainer. Same-day sibling is the
report-sender auth patch. Maintainer **Johannes Berg** applied this
commit.
**Step 3.5: Dependencies**
Record: Standalone. Uses existing `data->pmsr_request`, `data->mutex`,
`hwsim_virtio_enabled`. Series 1/8; does not need 2/8–8/8. Can apply
without `aeea930c7a878`.
---
## Phase 4: Mailing list
**Step 4.1: Original discussion**
Record:
- Lore URL: https://patch.msgid.link/20260708195911.84365-2-
enderaoelyther@gmail.com
- Cover: https://patch.msgid.link/20260708195911.84365-1-
enderaoelyther@gmail.com
- Series: **v1 only** as this patch (`b4 dig -a` “v2” is a different
nl80211 color-change patch; false match)
- Johannes on the cover (2026-07-21): will take the two hwsim patches
for **wireless-next**; **“I don’t think hwsim is all that relevant in
deployed systems.”** Not a NAK of the UAF. He did apply this patch the
same day.
- No reviewer asked for changes to this hunk. Other series patches
(probe-resp, S1G TWT) were called out as LLM-pattern issues; **this
patch was not**.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: linux-wireless, Johannes Berg, Jaewan Kim (original PMSR
author), Intel/Qualcomm/Marvell names, **stable@vger.kernel.org**. Right
lists for a hwsim UAF.
**Step 4.3: Bug report**
Record: No syzbot/bugzilla. Found by review. Cover letter: KASAN hwsim
boot; after the fix, a stale `REPORT_PMSR` got `-EINVAL` with no KASAN
splat. Author-tested, not an external user report.
**Step 4.4: Series**
Record: 8 patches, mixed subsystems. This one is self-contained. 2/8
(sender auth) is a separate spoofing fix, not required to stop the abort
UAF (it only narrows who can fire `hwsim_pmsr_report_nl()`).
**Step 4.5: Stable list**
Record: lore.kernel.org returned HTTP 403 via WebFetch. Original
submission **did** Cc stable. Johannes’s “not relevant in deployed
systems” is the only maintainer comment on hwsim priority. **No NAK and
no “do not backport” found in the mbox.**
---
## Phase 5: Semantic / call chain
**Step 5.1: Functions**
Record: `mac80211_hwsim_abort_pmsr()` only. Consumers of the pointers:
`mac80211_hwsim_start_pmsr()`, `hwsim_pmsr_report_nl()`.
**Step 5.2: Callers**
Record:
- `ieee80211_ops.abort_pmsr` → `drv_abort_pmsr()` →
`ieee80211_abort_pmsr()` → `rdev_abort_pmsr()` →
`cfg80211_pmsr_process_abort()` which **then `kfree(req)`**.
- Abort work: `cfg80211_pmsr_free_wk` / `cfg80211_pmsr_wdev_down`.
- Socket teardown: `nl80211` URELEASE → `cfg80211_release_pmsr()`.
**Step 5.3: Callees**
Record: mutex, `genlmsg_new`, `mac80211_hwsim_send_pmsr_request`,
virtio/wmediumd unicast. After the fix, notification is best-effort;
**state drop is not**.
**Step 5.4: Reachability**
Record: Yes, from userspace on this tree:
1. `NL80211_CMD_PEER_MEASUREMENT_START` (`GENL_UNS_ADMIN_PERM`) with
PMSR capa on an hwsim radio (wmediumd or virtio).
2. Close the nl80211 socket or take the wdev down → abort → cfg80211
frees `req`.
3. `HWSIM_CMD_REPORT_PMSR` has **no** `GENL_UNS_ADMIN_PERM` (verified at
the genl op). Combined with a leftover pointer, that is the UAF.
4. Extra path: wmediumd URELEASE sets `data->wmediumd = 0`
(`hwsim_register_wmediumd(net, 0)`). Old abort **returned
immediately** and never cleared.
**Step 5.5: Similar patterns**
Record: Same lifetime bug described for iwlwifi MLD in series 3/8
(`mld->ftm_initiator.req` left dangling). hwsim abort was the incomplete
half of start-saves/complete-clears.
---
## Phase 6: This checkout
**Step 6.1: Local tree and buggy code**
Record:
- `git describe HEAD`: **v7.3-rc4-27-gf0100363d8c37**
- `make kernelversion`: **7.3.0-rc4**
- Buggy abort (save on start, clear only in `hwsim_pmsr_report_nl()`)
exists here; pre-image at `37a77bd1395e8^` still has the early return
and no NULL. Introduced v6.4-rc1; **not after this branch point**.
**Step 6.2: Backport difficulty**
Record: **Clean apply** on this tree’s `mac80211_hwsim_main.c`. Function
and fields (`pmsr_request`, `pmsr_request_wdev`, `mutex`) are present.
**Step 6.3: Related fixes already here**
Record: No earlier abort-clear. `2bef4d1fb8b34` is a different NULL
check. `aeea930c7a878` is sender auth, not this UAF.
---
## Phase 7: Subsystem
**Step 7.1**
Record: **drivers/net/wireless/virtual** (mac80211_hwsim). Kconfig:
“Simulated radio testing tool… not needed for normal wireless LAN
usage.” Criticality: **PERIPHERAL** as hardware, but **IMPORTANT** as a
virtual/test driver shipped as a module and used by
CI/syzkaller/wmediumd.
**Step 7.2**
Record: File is actively developed (NAN, virtio, many 2026 hwsim fixes).
PMSR abort itself has been unchanged since 2023 — a long-standing hole,
not churn from last month.
---
## Phase 8: Impact and risk
**Step 8.1: Who**
Record: Users with `CONFIG_MAC80211_HWSIM` who start PMSR
(wmediumd/virtio) and abort. Not general Wi-Fi laptops. Distros often
ship the module; Android Cuttlefish / mac80211 selftests use it.
**Step 8.2: Trigger**
Record: Start PMSR, then abort (socket close / iface down), then a
report **or** wmediumd disconnect so abort’s old early-return fires.
Needs CAP_NET_ADMIN to **start**; report genl op is unrestricted.
Timing-dependent if wmediumd still reports after abort;
**deterministic** dangling pointer after abort regardless.
**Step 8.3: Failure mode**
Record: **Use-after-free** in `cfg80211_pmsr_report` /
`cfg80211_pmsr_complete` (`req->cookie`, `req->nl_portid`, …). Severity:
**HIGH** (oops/KASAN; possible memory corruption). Secondary: stuck
`-EBUSY` on later PMSR.
**Step 8.4: Risk vs benefit**
Record: Benefit **high** for anyone hitting hwsim PMSR abort (crash).
Risk **very low**: ~10-line pointer clear under an existing mutex. Ratio
favors taking it on this tree.
---
## Phase 9: Synthesis
**Step 9.1: Evidence**
For:
- Real UAF with a traced cfg80211 `kfree(req)` after `rdev_abort_pmsr()`
- Small, obviously correct, mutex-protected
- Bug in this tree since v6.4-rc1
- Standalone; no new API
- Author tested abort-then-report under KASAN
- Wireless maintainer applied it
- Original submission had Fixes: + Cc: stable
Against:
- Test/simulator driver; Johannes said hwsim is not very relevant on
deployed systems
- No syzbot/external user report
- Start path needs admin + wmediumd/virtio
- LLM-assisted series (maintainer criticized *other* patches, not this
one)
Unresolved: stable@ lore search (HTTP 403). Does not change the local-
tree technical picture.
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** (clear-on-abort; KASAN boot
described)
2. Real user-visible bug? **PASS** (UAF / oops; also stuck PMSR)
3. Important (crash/security/corruption/deadlock)? **PASS** (UAF → HIGH)
4. Small and contained? **PASS** (+7/−3, one function)
5. No new features/APIs? **PASS**
6. Applies to this tree? **PASS** (code present; clean)
**Step 9.3: Exceptions**
Record: None (not a device ID/quirk/DT/build/doc exception). Qualifies
as a normal memory-safety fix.
**Step 9.4: Decision**
This checkout is **v7.3-rc4**. The buggy hwsim PMSR abort path is here.
The patch is a small UAF fix with no prerequisites. Maintainer
skepticism about hwsim on production APs does not make a use-after-free
in this tree’s driver “not a bug.” It should be taken.
---
## What the commit solves for this tree
`mac80211_hwsim` stores cfg80211’s PMSR request in `data->pmsr_request`.
cfg80211 frees that object when abort finishes. This tree’s abort
callback never dropped the pointer (and skipped all cleanup if wmediumd
had already exited). A later `HWSIM_CMD_REPORT_PMSR` dereferences freed
memory. Clearing the two pointers under `data->mutex` when abort matches
is the whole fix.
## Risk vs benefit
Benefit: prevent a KASAN/UAF oops on PMSR abort and allow a later start.
Risk: negligible; notification becomes best-effort after the pointer is
already gone, which is what cfg80211 requires.
## Concerns
None that block this tree: no missing helpers, no series dependency,
file is already `mac80211_hwsim_main.c`. Johannes’s “deployed systems”
comment is priority, not a correctness NAK.
---
## Verification
- **[Phase 1]** Parsed committed tags: Link msgid
`20260708195911.84365-2`; SOBs Zhao Li + Johannes Berg; no Fixes in
committed text
- **[Phase 1]** mbox of original mail: Fixes `5530c04c87c5`, Cc: stable
- **[Phase 2]** `git show 37a77bd1395e8`: +7/−3 in
`mac80211_hwsim_abort_pmsr` only
- **[Phase 2]** Read current abort (lines 3848–3911) and
`hwsim_pmsr_report_nl` (4213–4277): report uses `data->pmsr_request`
then NULLs it
- **[Phase 2]** Read `cfg80211_pmsr_process_abort()`:
`rdev_abort_pmsr()` then `kfree(req)`
- **[Phase 3]** `git blame` on pre-image: abort from `8ba1da95053e0`;
`git describe --contains` → v6.4-rc1
- **[Phase 3]** `git merge-base --is-ancestor 5530c04c87c59 HEAD` → 0;
same for `8ba1da95053e0`
- **[Phase 3]** `git log --oneline --grep=pmsr --
drivers/net/wireless/virtual/`: series neighbor `aeea930c7a878`
independent
- **[Phase 3]** `git log --oneline -S mac80211_hwsim_abort_pmsr --
drivers/net/wireless/virtual/`: only intro + this fix
- **[Phase 4]** `b4 dig -c 37a77bd1395e8`: patch.msgid.link `…84365-2`
- **[Phase 4]** `b4 dig -a`: v1 of this patch; “v2” is unrelated nl80211
color-change
- **[Phase 4]** `b4 dig -w`: linux-wireless, Johannes, Jaewan Kim,
stable@
- **[Phase 4]** mbox msg from Johannes: wireless-next; hwsim “not all
that relevant in deployed systems”; no NAK of this diff
- **[Phase 4]** WebFetch lore/stable: HTTP 403 — UNVERIFIED whether it
was discussed on stable@ beyond original Cc
- **[Phase 5]** Grep: abort wired in `ieee80211_ops`; nl80211 URELEASE
calls `cfg80211_release_pmsr`
- **[Phase 5]** `HWSIM_CMD_REPORT_PMSR` op has no `GENL_UNS_ADMIN_PERM`;
`NL80211_CMD_PEER_MEASUREMENT_START` has it
- **[Phase 5]** wmediumd URELEASE zeros portid via
`hwsim_register_wmediumd(net, 0)`
- **[Phase 6]** `git describe HEAD` v7.3-rc4-27-gf0100363d8c37; Makefile
7.3.0-rc4
- **[Phase 6]** `git merge-base --is-ancestor 37a77bd1395e8 HEAD` → 0
(present; judged on merit, not as “already selected”)
- **[Phase 6]** Pre-fix abort still has early return without NULL (shown
at `37a77bd1395e8^`)
- **[Phase 7]** Kconfig: test tool, module `mac80211_hwsim`
- **[Phase 8]** `cfg80211_pmsr_complete()` derefs `req->cookie` /
`req->nl_portid` — UAF if abort already freed `req`
- **UNVERIFIED:** How many distro .configs enable `MAC80211_HWSIM` — not
used to drive the verdict; UAF is in-tree regardless
The fix is small, surgical, and matches stable rules for a real use-
after-free in code this tree has had since v6.4.
**YES**
drivers/net/wireless/virtual/mac80211_hwsim.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 484198766efda..89794c724858c 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -3654,9 +3654,6 @@ static void mac80211_hwsim_abort_pmsr(struct ieee80211_hw *hw,
int err = 0;
data = hw->priv;
- _portid = READ_ONCE(data->wmediumd);
- if (!_portid && !hwsim_virtio_enabled)
- return;
mutex_lock(&data->mutex);
@@ -3665,6 +3662,13 @@ static void mac80211_hwsim_abort_pmsr(struct ieee80211_hw *hw,
goto out;
}
+ data->pmsr_request = NULL;
+ data->pmsr_request_wdev = NULL;
+
+ _portid = READ_ONCE(data->wmediumd);
+ if (!_portid && !hwsim_virtio_enabled)
+ goto out;
+
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!skb) {
err = -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Limit mic boost on Positivo N15RPE-S
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (77 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.6] wifi: mac80211_hwsim: clear PMSR request state on abort Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] thunderbolt: xdomain: Notify peers after enumeration Sasha Levin
` (437 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Edson Juliano Drosdeck, Takashi Iwai, Sasha Levin, perex, tiwai,
linux-sound, linux-kernel
From: Edson Juliano Drosdeck <edson.drosdeck@gmail.com>
[ Upstream commit 253010acfc8ad908446347b30a613032d1517bb5 ]
The internal mic boost on the Positivo N15RPE-S is too high.
Fix this by applying the ALC269_FIXUP_LIMIT_INT_MIC_BOOST fixup to the machine
to limit the gain.
Signed-off-by: Edson Juliano Drosdeck <edson.drosdeck@gmail.com>
Link: https://patch.msgid.link/20260805154518.19093-1-edson.drosdeck@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111** (`pending-6.12`). This is a one-line
Realtek HDA PCI quirk for a laptop whose driver and existing mic-boost
fixup are already in this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [ALSA hda/realtek] [Limit] [apply existing
ALC269_FIXUP_LIMIT_INT_MIC_BOOST to Positivo N15RPE-S because internal
mic boost is too high]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Edson Juliano Drosdeck (author)
- Link: https://patch.msgid.link/20260805154518.19093-1-
edson.drosdeck@gmail.com
- Signed-off-by: Takashi Iwai (ALSA maintainer)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, or Cc:
stable
- Ignore pipeline markers (none present on the upstream commit
`253010acfc8ad`)
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: internal microphone boost on Positivo N15RPE-S is too high
- Symptom: excessive gain / noisy internal mic (the fixup comment says
levels 2 and 3 are too noisy)
- Failure mode: hardware-specific unusable/noisy capture, not a kernel
crash
- Root cause: this PCI SSID is not in the quirk table, so the existing
boost limiter is not applied
- Version info: none stated
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit hardware quirk: map
SSID `0x2782:0xa128` to an existing fixup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- Files: `sound/hda/codecs/realtek/alc269.c` (+1 / -0)
- Function/table: `alc269_fixup_tbl[]`
- Scope: single-file, one-line surgical quirk addition
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: PCI SSID `0x2782:0xa128` has no match; codec uses default
auto-config with full internal-mic boost range
- After: that SSID matches `ALC269_FIXUP_LIMIT_INT_MIC_BOOST`, which at
probe overrides amp caps so internal-mic boost is only steps 0–1
- Path: codec probe (`patch_alc269()` → `snd_hda_pick_fixup(...,
alc269_fixup_tbl, ...)`)
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [Hardware workaround] Existing
`alc269_fixup_limit_int_mic_boost()` already limits noisy boost levels 2
and 3. This commit only adds the PCI ID so that function runs on this
laptop.
Verified function in this tree
(`sound/pci/hda/patch_realtek.c:6661-6690`):
- Runs only on `HDA_FIXUP_ACT_PROBE`
- Walks auto-config inputs, keeps only `AUTO_PIN_MIC` with
`INPUT_PIN_ATTR_INT`
- Calls `snd_hda_override_amp_caps()` with `NUM_STEPS=1`
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Quality: obviously correct; identical pattern already used for
Positivo ARN50, Positivo N14AP7, VAIO VJFE-CL, several ThinkPads
- Minimal: one `SND_PCI_QUIRK` line, no API/data-structure change
- Regression risk: very low; only SSID `0x2782:0xa128` is affected. The
chosen fixup is chained to `ALC269_FIXUP_THINKPAD_ACPI`, but that is
the same chain used by the other Positivo/VAIO limit-boost entries
already in this tree.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Insertion point in this tree is after `SND_PCI_QUIRK(0x2782, 0x4900,
"MEDION E15443", ...)` (`98b5ade3a44d8f`, 2024)
- The buggy “missing ID” is not old code; the laptop simply was never
listed
- The fixup itself dates to `3e0d611b2045b` (“ALSA: hda - Limit internal
mic boost for a few Asus machines”, 2013-04-22, contained in
v3.10-rc1) and **is an ancestor of HEAD**
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Expected for a new device quirk. Not a negative
signal.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Related commits already in this tree:
- `d44418f5024f6` ALSA: hda/realtek: Limit mic boost on Positivo ARN50
(same author, same fixup; already backported here)
- `86a433862912f` ALSA: hda/realtek: Limit mic boost on N14AP7 (same
author, same fixup; had Cc: stable)
- Standalone: not patch X/Y. No prerequisite series.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Edson Juliano Drosdeck has 10 commits in
`sound/pci/hda/patch_realtek.c` on this tree, almost all Positivo/VAIO
HDA quirks. Regular hardware-quirk contributor, not a one-off.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record:
- Depends only on `ALC269_FIXUP_LIMIT_INT_MIC_BOOST` and
`alc269_fixup_tbl[]`, both present
- Can apply standalone as a one-line quirk in
`sound/pci/hda/patch_realtek.c`
- Mainline file path `sound/hda/codecs/realtek/alc269.c` is the
post-6.12 HDA codec split; that path does **not** exist here.
Equivalent table is `alc269_fixup_tbl` in `patch_realtek.c`
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 253010acfc8ad` → https://patch.msgid.link/20260805154518.19
093-1-edson.drosdeck@gmail.com
- `b4 dig -a`: only v1; no later revision
- Thread is two messages: the patch and Takashi Iwai “Applied to for-
next branch. Thanks.”
- No NAK, no requested changes, no reviewer-flagged risk
- No explicit Cc: stable in the thread (absence expected)
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To Takashi Iwai (`tiwai@suse.com`); Cc Jaroslav
Kysela (`perex@perex.cz`), Realtek (`kailang@realtek.com`), linux-sound,
linux-kernel. Subsystem maintainer received and applied it.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla link. Description is a hardware report from
the same author who previously submitted verified Positivo quirks. No
independent public bug count found.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone one-patch series. Same author’s ARN50/N14AP7 limit-
boost quirks are the precedent; those are already in this tree.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search returned HTTP 403. No stable-list
discussion verified. No evidence this was rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: Table `alc269_fixup_tbl[]` only. Runtime function used by the
new ID: `alc269_fixup_limit_int_mic_boost()`. Probe picker:
`snd_hda_pick_fixup()` from `patch_alc269()`.
Step 5.2: TRACE CALLERS
Record:
- `patch_alc269()` at `sound/pci/hda/patch_realtek.c:12416` calls
`snd_hda_pick_fixup(codec, alc269_fixup_models, alc269_fixup_tbl,
alc269_fixups)` (line 12583)
- That is the ALC269-family codec probe path
(CONFIG_SND_HDA_CODEC_REALTEK)
- Not IRQ, not syscall hot path; once at device probe
Step 5.3: TRACE CALLEES
Record: `alc269_fixup_limit_int_mic_boost()` →
`snd_hda_codec_get_pincfg()`, `snd_hda_get_input_pin_attr()`,
`snd_hda_override_amp_caps()`. No allocation, no new locks.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace cannot trigger a crash path. The ID is matched when
this laptop’s Realtek HDA codec is probed. Reachable for owners of
Positivo N15RPE-S with SND_HDA_CODEC_REALTEK. Unprivileged users then
get a usable (non-blown-out) internal mic.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same `ALC269_FIXUP_LIMIT_INT_MIC_BOOST` already used for many
IDs in this tree, including:
- `0x1c6c:0x122a` Positivo N14AP7
- `0x2014:0x800a` Positivo ARN50
- `0x2782:0x0214` VAIO VJFE-CL
This is a systematic hardware pattern, not a one-off experiment.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- `git describe HEAD` = `p-6.12-2-gd38d58a4e0359`; `make kernelversion`
= 6.12.111
- `git merge-base --is-ancestor 253010acfc8ad HEAD` → **not in this
tree**
- `0xa128` is absent from `patch_realtek.c` (grep: no matches)
- The missing-ID bug exists here: the laptop would probe without the
limiter
- Fixup and table exist since well before 6.12 (fixup from v3.10)
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Needs a trivial backport, not a clean git-am of the mainline
diff:
1. Path: `sound/hda/codecs/realtek/alc269.c` →
`sound/pci/hda/patch_realtek.c`
2. Context: mainline next line is Lunnen Ground 14 (`0x2782, 0xa212`),
which is **not** in 6.12; insert after `0x2782, 0x4900` and before
`0x7017, 0x2014`
That is the same class of adjustment used for `d44418f5024f6` (ARN50) on
this tree.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No N15RPE-S entry. Nearby same-class quirks (ARN50, N14AP7) are
present. No alternate fix for `0x2782:0xa128`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [sound/pci/hda Realtek codec] [IMPORTANT for laptop audio;
PERIPHERAL in that only this PCI ID is affected]
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Very active: last 20 commits on `patch_realtek.c` are mostly
more `SND_PCI_QUIRK` entries (HP, Lenovo, Samsung, MECHREVO, ASUS).
Mature driver; this is the normal way hardware enablement/workarounds
land.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific / PCI-SSID-specific: only Positivo N15RPE-S
(`0x2782:0xa128`) with Realtek ALC269-family HDA.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Trigger: every boot/probe on that laptop when using the internal mic
at high boost
- Common for owners of that model; zero impact elsewhere
- Not a security trigger; not unprivileged-crash
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: [Noisy / overly boosted internal mic, capture quality unusable
at high gain] [MEDIUM for those users; LOW globally]. Not
panic/UAF/corruption, but it is a real hardware defect the existing
quirk is designed to fix.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: high for N15RPE-S users on 6.12 (mic works as on later
kernels)
- Risk: very low (one ID, existing fixup, same pattern already
backported here)
- Ratio: strongly favors backport
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Explicit audio-codec hardware quirk (`SND_PCI_QUIRK` + existing fixup)
- Real user-visible bug (internal mic boost too high)
- One line, obviously correct, maintainer-applied
- Same author’s identical Positivo ARN50 quirk already in this 6.12 tree
- Fixup and quirk table already present
- No new API, no new driver, no behavioral change except this SSID
AGAINST:
- Not a crash/security/data-corruption bug
- Mainline path differs; needs 1-line context/path adjustment
- No independent public bugzilla/syzbot report
- Affected population is one laptop model
UNRESOLVED:
- Could not query lore.kernel.org/stable (HTTP 403)
- Could not independently verify the author’s hardware test beyond the
commit text and maintainer apply
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — one ID, existing fixup, applied
by Takashi Iwai
2. Fixes a real bug that affects users? PASS — excessive internal mic
boost on this machine
3. Important issue? PASS under the hardware-quirk exception (audio codec
quirk); severity MEDIUM for that model
4. Small and contained? PASS — +1 line
5. No new features or APIs? PASS — ID mapped to existing fixup
6. Can apply to the local tree? PASS — equivalent table exists; needs
trivial path/context backport, same as prior quirks on this tree
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **Hardware quirk / audio codec quirk** (`SND_PCI_QUIRK` in
Realtek HDA). This is an explicit stable exception.
Step 9.4: MAKE YOUR DECISION
This should be backported to this 6.12 tree. It is the standard Realtek
laptop quirk: add a PCI subsystem ID so an existing limiter runs. The
driver, table, and `ALC269_FIXUP_LIMIT_INT_MIC_BOOST` are all here; only
the N15RPE-S ID is missing. Risk is confined to that SSID.
------------------------------------------------
What problem it solves and why it matters
The Positivo N15RPE-S ships with an internal mic whose boost steps 2–3
are too hot. Without this ID, 6.12 users of that laptop keep the default
full boost range. The commit maps `0x2782:0xa128` onto the long-standing
limiter already used for other Positivo machines in this tree.
Stable-rules fit
It is small, obviously correct, does not add APIs, and is the documented
audio-quirk exception. It is not a crash fix, but stable routinely takes
these ID-only Realtek quirks.
Risk vs benefit
Benefit is a working internal mic for that model. Risk is a single-ID
table entry using a fixup that has been in the kernel since v3.10 and is
already applied to sibling Positivo IDs here.
Concerns
The mainline hunk will not `git am` cleanly because of the later HDA
file split and a neighboring Lunnen Ground 14 entry that 6.12 lacks. The
backport is still a one-line insert into `alc269_fixup_tbl` in
`sound/pci/hda/patch_realtek.c`.
Verification:
- [Phase 1] Parsed tags on `253010acfc8ad`: author SOB, maintainer SOB,
msgid Link; no Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: +1 `SND_PCI_QUIRK(0x2782, 0xa128, "Positivo N15RPE-S",
ALC269_FIXUP_LIMIT_INT_MIC_BOOST)`
- [Phase 2] Read `alc269_fixup_limit_int_mic_boost()` at
`patch_realtek.c:6661-6690`; confirmed it clamps internal-mic amp
steps to 0–1
- [Phase 2] Confirmed `[ALC269_FIXUP_LIMIT_INT_MIC_BOOST]` exists at
line 8711 and chains to `ALC269_FIXUP_THINKPAD_ACPI` (same as other
Positivo limit-boost entries)
- [Phase 3] `git merge-base --is-ancestor 3e0d611b2045b HEAD` — fixup
present (v3.10)
- [Phase 3] `git merge-base --is-ancestor 253010acfc8ad HEAD` —
candidate **not** in this tree
- [Phase 3] `git log --grep=N15RPE -- sound/pci/hda/` — empty
- [Phase 3] Grep `0xa128` in `patch_realtek.c` — no match
- [Phase 3] Same-class commits in tree: `d44418f5024f6` (ARN50),
`86a433862912f` (N14AP7)
- [Phase 3] Author has 10 Realtek HDA quirk commits in this tree
- [Phase 4] `b4 dig -c 253010acfc8ad` → msgid
20260805154518.19093-1-edson.drosdeck@gmail.com
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: To tiwai, Cc linux-sound / perex / Realtek
- [Phase 4] LKML/Patchew: Takashi “Applied to for-next”; no NAK
- [Phase 4] UNVERIFIED: lore.kernel.org/stable search HTTP 403
- [Phase 5] `patch_alc269()` line 12583 uses `alc269_fixup_tbl`
- [Phase 6] `git describe HEAD` = p-6.12-2-gd38d58a4e0359; kernelversion
6.12.111
- [Phase 6] Local file is `sound/pci/hda/patch_realtek.c`; `alc269.c`
does not exist; insert after 0x2782/0x4900 before 0x7017/0x2014
- [Phase 8] Failure mode: noisy/excessive internal mic boost on one
laptop; not a crash
**YES**
sound/hda/codecs/realtek/alc269.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index f2b0eb8501a78..5098d3f375316 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -7646,6 +7646,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x2782, 0x1705, "MEDION E15433", ALC269VC_FIXUP_INFINIX_Y4_MAX),
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
SND_PCI_QUIRK(0x2782, 0x4900, "MEDION E15443", ALC233_FIXUP_MEDION_MTL_SPK),
+ SND_PCI_QUIRK(0x2782, 0xa128, "Positivo N15RPE-S", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x2782, 0xa212, "Lunnen Ground 14", ALC269VC_FIXUP_LUNNEN_GROUND_14),
SND_PCI_QUIRK(0x7017, 0x2014, "Star Labs StarFighter", ALC233_FIXUP_STARLABS_STARFIGHTER),
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] thunderbolt: xdomain: Notify peers after enumeration
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (78 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] ALSA: hda/realtek: Limit mic boost on Positivo N15RPE-S Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:17 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] drm/amd/pm: derive stable PPT limits from PPTable Sasha Levin
` (436 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Milo Chen, Mika Westerberg, Sasha Levin, andreas.noever, westeri,
YehezkelShB, linux-usb, linux-kernel
From: Milo Chen <cmh79479@gmail.com>
[ Upstream commit e027dba038f0008df9bc9575f5c3e803e90636c6 ]
Service drivers may register local XDomain properties while discovery is
still in progress. This can cause the properties changed notification to be
sent before the peer is ready to act on it.
If the peer has already read the local property block before the service
was registered, it may keep using the old property generation and miss the
newly registered service. With ThunderboltIP this can leave the network
service half-discovered after a warm reboot and the login request
eventually times out.
Queue another properties changed notification after the XDomain reaches
ENUMERATED so the peer can re-read the final local properties.
Signed-off-by: Milo Chen <cmh79479@gmail.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
candidate is a one-line Thunderbolt XDomain handshake fix: after
discovery reaches `ENUMERATED`, send another properties-changed
notification so a peer can pick up services registered during discovery.
That matches a real ThunderboltIP failure after warm reboot, and the
surrounding helpers already exist here.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: `[thunderbolt: xdomain:] [Notify] [send properties-changed to
peers once XDomain discovery reaches ENUMERATED]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- `Signed-off-by: Milo Chen <cmh79479@gmail.com>` (author)
- `Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>`
(Thunderbolt maintainer; applied the patch)
- No `Fixes:`
- No `Reported-by:` / `Tested-by:` / `Reviewed-by:` / `Acked-by:` /
`Link:` / `Cc: stable`
- Absence of `Fixes:` / `Cc: stable` is expected for this review and
is not a negative signal
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record:
- **Bug:** Service drivers may register local XDomain properties while
discovery is still running. The properties-changed notification can
go out before the peer can act on it.
- **Symptom:** Peer keeps an old property generation and misses the
new service. With ThunderboltIP, the network service stays half-
discovered after a **warm reboot** and the **login request times
out**.
- **Root cause:** Notification is sent too early (during discovery);
nothing is sent once the local host is fully enumerated.
- **Fix:** Queue another properties-changed notification when the
XDomain reaches `ENUMERATED`.
- **Version info:** none in the message.
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: Not a disguised cleanup. The message describes a concrete
functional failure (ThunderboltIP login timeout) and a protocol-timing
fix.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- Record:
- File: `drivers/thunderbolt/xdomain.c` (`+1 / -0`)
- Function: `tb_xdomain_state_work()`
- Scope: single-file, one-line surgical change
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record:
- **Before:** `XDOMAIN_STATE_PROPERTIES` success only sets `xd->state
= XDOMAIN_STATE_ENUMERATED`.
- **After:** same, then `tb_xdomain_queue_properties_changed(xd)`.
- Path: successful remote property fetch at the end of XDomain
discovery (normal path, not an error path).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record:
- **Category:** logic / protocol handshake correctness (missed peer
notification).
- **Mechanism:** `tb_xdomain_queue_properties_changed()` already runs
in `XDOMAIN_STATE_INIT` and after UUID. `tb_register_property_dir()`
(used by `thunderbolt-net`) also notifies via
`update_all_xdomains()`. If that happens while the peer is not
ready, or after the peer already read the old block, the peer can
stick on the old generation. There was no notify after local
discovery finished. The new call reuses the existing notify helper
at ENUMERATED so the peer re-reads the final block.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record:
- **Quality:** Obviously correct relative to the described race. It
reuses `tb_xdomain_queue_properties_changed()`, which already sends
`PROPERTIES_CHANGED_REQUEST` with retries.
- **Minimal:** one call, no API/data-structure change.
- **Regression risk:** Low for the intended case. Extra notifies are
already part of the protocol; the receiver path in
`tb_xdp_handle_request()` treats `PROPERTIES_CHANGED_REQUEST` as
“re-run state work / re-read properties.”
- **Noted risk (code-derived, not field-confirmed):** because
`XDOMAIN_STATE_ENUMERATED` already re-enters `PROPERTIES` when a
peer notify arrives, a successful re-read will now send another
notify. Two Linux hosts both running this change could keep
exchanging property updates. No follow-up revert/fix appears in this
tree after the commit. Treat as theoretical unless proven in use.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Record:
- Surrounding state machine: `8e1de7042596ab` (“thunderbolt: Add
support for XDomain lane bonding”, 2022-05-05), first in
**v5.19-rc1**.
- Notify helper and INIT/UUID notify sites: same commit.
- The added line is this candidate (`e027dba038f000`, Milo Chen,
2026-06-24).
- XDomain discovery protocol itself: `d1ff70241a275` (2017),
**v4.15-rc1**.
**Step 3.2: FOLLOW THE FIXES: TAG**
- Record: No `Fixes:` tag. Not applicable. The missing notify at
ENUMERATED dates to the 5.19 state machine.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
- Record:
- Related: `abc27e5bfed2f` (“Allow service drivers to specify their
own properties”) — extra per-service properties, not required for
this one-line call.
- `308092d080852` (“Restart XDomain discovery handshake after
failure”) — nearby error-path change; not a prerequisite.
- Standalone. Not `patch X/Y`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
- Record: Milo Chen has only this thunderbolt commit here. Applied by
**Mika Westerberg**, Thunderbolt maintainer.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
- Record: Depends only on `tb_xdomain_queue_properties_changed()` and
`XDOMAIN_STATE_ENUMERATED`, both present since 5.19. Applies
standalone.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record:
- `b4 dig -c e027dba038f000…` →
https://patch.msgid.link/20260624060909.2610434-1-cmh79479@gmail.com
- **v1:** `[PATCH] thunderbolt: xdomain: notify peers after
enumeration` (From: Rqirus) —
https://patch.msgid.link/20260624011131.2532004-1-cmh79479@gmail.com
- **v2:** same diff; changelog: “Use full name in From and Signed-off-
by.”
- Mika Westerberg on v2: **“Applied to thunderbolt.git/next,
thanks!”**
- No NAK. No request for `Cc: stable` in the saved thread.
- lore.kernel.org HTTP fetch returned 403; discussion was recovered
via `b4 dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
- Record (`b4 dig -w`): To/Cc Mika Westerberg, Andreas Noever, Michael
Jamet, Yehezkel Bernat, linux-usb, linux-kernel. Subsystem maintainers
were on the original mail. Mika applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: No bugzilla/syzbot/Link. The commit text is the bug report:
ThunderboltIP half-discovered after warm reboot, login timeout.
Severity from the author: networking service fails to complete
discovery.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
- Record: Single-patch series (v1→v2, identical diff). Not part of a
multi-patch set.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
- Record: Web search of lore.kernel.org/stable for this subject returned
no relevant hits. **UNVERIFIED** that nobody asked for it on stable@;
no evidence it was rejected either.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
- Record: `tb_xdomain_state_work()` modified; calls
`tb_xdomain_queue_properties_changed()`; that queues
`tb_xdomain_properties_changed()` →
`tb_xdp_properties_changed_request()`.
**Step 5.2: TRACE CALLERS**
- Record:
- `tb_xdomain_state_work` is delayed work started from
`start_handshake()` / queue helpers; not a syscall.
- `tb_xdomain_queue_properties_changed` call sites: INIT (no UUID
needed), UUID success, and (after this patch) PROPERTIES success.
- `tb_register_property_dir()` is called from
`drivers/net/thunderbolt/main.c` (`tbnet_init`),
`drivers/thunderbolt/stream.c`, `drivers/thunderbolt/dma_test.c`.
**Step 5.3: TRACE CALLEES**
- Record: Notify path allocates/sends an XDomain control packet with
retries (`XDOMAIN_RETRIES`). Failure is logged; it does not unwind
enumeration.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: Reachable when two hosts do XDomain discovery over
Thunderbolt/USB4 (cable/peer already present, including after warm
reboot). Userspace does not need a special syscall; loading
`thunderbolt-net` during boot vs in-progress discovery is the trigger.
Config: `CONFIG_USB4` plus Thunderbolt networking.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
- Record: Same notify is already used at INIT/UUID and when property
dirs are registered. This fills the gap at end-of-discovery. No
sibling drivers needed the same hunk.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
- Record: Yes. `drivers/thunderbolt/xdomain.c` has the PROPERTIES →
ENUMERATED transition. Parent of the candidate only sets `xd->state =
XDOMAIN_STATE_ENUMERATED` with no notify. ThunderboltIP registers
`"network"` via `tb_register_property_dir()` in this tree. Bug class
has been present since the 5.19 state machine; this tree is 7.3-rc4,
so the code is in-scope.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
- Record: Expected **clean apply**. Parent context around the hunk
matches this tree’s pre-patch source. One added line, no helpers
missing.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
- Record: No other commit on this file addresses “notify after
enumeration” or the ThunderboltIP warm-reboot miss. `abc27e5bfed2f` is
a separate feature (per-service properties), not a substitute.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
- Record: `drivers/thunderbolt/` (USB4/Thunderbolt). **IMPORTANT** for
USB4/TBT hosts, **PERIPHERAL** relative to mm/VFS. Affects Thunderbolt
XDomain and ThunderboltIP (`drivers/net/thunderbolt/`), not all
machines.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
- Record: Actively maintained (Mika Westerberg). Recent xdomain work
includes UAF and bounds fixes. Mature protocol with ongoing fixes;
this is not staging.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
- Record: Thunderbolt/USB4 hosts using XDomain, especially ThunderboltIP
between two machines after warm reboot. Driver-specific / config-
specific (`CONFIG_USB4`, thunderbolt-net).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
- Record: Warm reboot (or service driver registering properties during
discovery). Timing-dependent. Unprivileged users do not trigger it via
a random syscall; they hit it by using Thunderbolt networking. Common
for that hardware/use case, rare globally.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
- Record: ThunderboltIP discovery incomplete; login times out; network
over Thunderbolt does not come up. Not a panic, UAF, or corruption.
**Severity: HIGH for ThunderboltIP users, MEDIUM overall** (feature
broken, host stays up).
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
- Record:
- **Benefit:** Restores Thunderbolt networking after a realistic warm-
reboot race. High for those users.
- **Risk:** Very low line count; extra notify is an existing protocol
message. Theoretical Linux↔Linux notify loop is unverified in the
field; no revert in this tree.
- **Ratio:** Benefit outweighs risk.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR backporting:**
- Real user-visible bug: ThunderboltIP half-discovered, login timeout
after warm reboot.
- One-line, reuses an existing helper.
- Maintainer (Mika Westerberg) applied it with no technical objections.
- All needed symbols/state exist in this 7.3-rc4 tree (state machine
since 5.19).
- Applies cleanly; not a new API/feature.
- Standalone; v2 only fixed the author’s From name.
**AGAINST backporting:**
- Not a crash, UAF, or security bug.
- Affects a subset (USB4/TBT XDomain / ThunderboltIP).
- No `Reported-by` besides the author’s scenario.
- Theoretical extra notify traffic between two patched Linux peers
(unverified in production).
**UNRESOLVED:**
- Could not fetch lore over HTTP (403); used `b4` mbox instead.
- Mika’s v1 mail body was not in the saved v2 mbox; v2 changelog says
the only change was the From/SOB name.
- No stable@ thread found.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one existing helper call;
maintainer applied to thunderbolt.git/next.
2. Fixes a real bug that affects users? **PASS** — ThunderboltIP login
timeout after warm reboot.
3. Important issue? **PASS** — service remains unusable (connectivity
failure), not a panic; still a serious functional break for that
hardware.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — helpers and state machine are
present; hunk context matches.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
- Record: None (not a device ID, quirk table, DT, build, or docs-only
change). Qualifies as a normal small bugfix.
**Step 9.4: DECISION**
This tree has the buggy handshake. The patch is a minimal, maintainer-
acked fix for a real ThunderboltIP discovery failure. That is
appropriate to backport here.
---
### What the commit solves for this tree
On 7.3-rc4, XDomain discovery still notifies peers early and service
drivers (notably `thunderbolt-net`) can still register the `"network"`
property directory while handshake is in progress. Without a notify at
`ENUMERATED`, a peer that already read the old block can miss the
service; ThunderboltIP then sits half-discovered and login times out
after warm reboot. One extra `tb_xdomain_queue_properties_changed()` at
the end of discovery closes that window.
### Stable rules
The change is obviously correct, tiny, and does not add APIs. It fixes a
real connectivity bug, not a refactor.
### Risk vs benefit
Benefit is restoring Thunderbolt networking after reboot. Risk is one
extra protocol notify on a path that already sends that message.
Residual ping-pong risk between two Linux peers is unverified and did
not produce a follow-up fix in this tree.
### Concerns
No `Fixes:` tag (expected). Not a crash-class bug. Depends on
Thunderbolt XDomain, which this tree has. No missing prerequisites.
---
Verification:
- [Phase 1] Parsed commit `e027dba038f0008df9bc9575f5c3e803e90636c6`:
subject/body/SOBs only; no Fixes/Reported-by/Cc stable
- [Phase 2] Diff: +1 line in `tb_xdomain_state_work()` after `xd->state
= XDOMAIN_STATE_ENUMERATED`
- [Phase 2] Confirmed existing notifies at INIT (line 1739) and UUID
success (line 1751); `tb_register_property_dir()` calls
`update_all_xdomains()`
- [Phase 2] Confirmed `thunderbolt-net` `tbnet_init()` calls
`tb_register_property_dir("network", tbnet_dir)`
- [Phase 2] Receiver of `PROPERTIES_CHANGED_REQUEST` queues
`state_work`; `ENUMERATED` re-enters `PROPERTIES` (verified in
`xdomain.c`)
- [Phase 3] `git blame`: state machine from `8e1de7042596ab`
(v5.19-rc1); XDomain protocol from `d1ff70241a275` (v4.15-rc1)
- [Phase 3] `git log --author="Milo Chen" -- drivers/thunderbolt/`: only
this commit
- [Phase 3] No later xdomain.c commit addresses this notify
- [Phase 4] `b4 dig -c e027dba038f000…`: lore match
https://patch.msgid.link/20260624060909.2610434-1-cmh79479@gmail.com
- [Phase 4] `b4 dig -a`: v1 and v2; v2 identical diff, From-name fix
only
- [Phase 4] `b4 dig -w`: thunderbolt maintainers + linux-usb
- [Phase 4] mbox: Mika Westerberg “Applied to thunderbolt.git/next,
thanks!”
- [Phase 4] WebFetch lore: 403; used b4 instead
- [Phase 4] Stable-list search: no relevant hits
- [Phase 5] Callers of `tb_register_property_dir`: thunderbolt-net,
stream, dma_test (grep)
- [Phase 5] semcode MCP: not available; used git grep/read
- [Phase 6] `make kernelversion` / Makefile: 7.3.0-rc4; `git describe
HEAD`: v7.3-rc4-27-gf0100363d8c37
- [Phase 6] Parent hunk lacks the notify; this tree has the helpers
- [Phase 6] `git merge-base --is-ancestor e027dba038f000 HEAD`: ancestor
(original commit in this development tree; not used as “already
selected for stable”)
- [Phase 7] MAINTAINERS: THUNDERBOLT DRIVER, Mika Westerberg
- [Phase 8] Failure mode: ThunderboltIP login timeout / half-discovered
service, not oops
- UNVERIFIED: Mika v1 review body (not in v2 mbox); whether Linux↔Linux
notify looping occurs in the field; whether stable@ ever discussed
this patch
**YES**
drivers/thunderbolt/xdomain.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
index d9c2686b5fe41..b35e2f7c318dc 100644
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -1692,6 +1692,7 @@ static void tb_xdomain_state_work(struct work_struct *work)
tb_xdomain_failed(xd);
} else {
xd->state = XDOMAIN_STATE_ENUMERATED;
+ tb_xdomain_queue_properties_changed(xd);
}
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amd/pm: derive stable PPT limits from PPTable
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (79 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] thunderbolt: xdomain: Notify peers after enumeration Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:32 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: universal-pidff: Add support for Turtle Beach VelocityOne Race Sasha Levin
` (435 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Yang Wang, Kenneth Feng, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Yang Wang <kevinyang.wang@amd.com>
[ Upstream commit 25f4a46b0c8acd77c9065b50a1fe48af27d91fdf ]
GetPptLimit reports mutable PMFW runtime state. Using that value for
static capabilities causes two externally visible problems:
- A userspace override changes the default reported through hwmon.
- A firmware reset changes the advertised minimum or maximum range.
Derive platform defaults and supported ranges from the driver PPTable
for Sienna Cichlid, Navi10, Arcturus, and Aldebaran. Reserve PMFW queries
for the effective current limit.
Runtime policy can no longer redefine immutable platform capabilities.
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough from the local 6.12 tree, the sibling SMU13/SMU14
backports, and the series context to decide. The remaining lore lookups
failed with 403, so those are marked unverified.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [drm/amd/pm] [derive] [source immutable PPT default/min/max from
the driver PPTable instead of PMFW GetPptLimit]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Yang Wang <kevinyang.wang@amd.com> (author)
- Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> (AMD PM reviewer)
- Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (amdgpu
maintainer)
- No Fixes:, Reported-by, Tested-by, Link:, or Cc: stable (absence
expected)
- Ignore Sasha Levin SOB if present (pipeline)
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: GetPptLimit returns mutable PMFW runtime state, but the driver
used that one value for current, default, min, and max.
- Symptoms: (1) a userspace power-cap override changes the default shown
in hwmon; (2) a firmware/GPU reset changes the advertised min/max
range.
- Failure mode: hwmon `power1_cap_default` / `power1_cap_max` /
`power1_cap_min` stop being immutable platform capabilities. After
reset, `smu_set_power_limit()` can reject a previously valid TDP
because max was recomputed from the runtime value.
- Root cause: static capabilities were taken from PMFW instead of
PPTable.
- Version info: none in the message. Upstream SHA from drm.git is
`25f4a46b0c8acd77c9065b50a1fe48af27d91fdf` (author 2026-07-30,
committed 2026-08-06).
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit correctness fix.
Navi10/Sienna also start using AC vs DC PPTable entries, matching the
SMU13 pattern already in this tree.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- `arcturus_ppt.c` `arcturus_get_power_limit`: ~+12/-11
- `navi10_ppt.c` `navi10_get_power_limit`: ~+16/-12
- `sienna_cichlid_ppt.c` `sienna_cichlid_get_power_limit`: ~+16/-12
- `aldebaran_ppt.c` `aldebaran_get_power_limit`: ~+6/-2
- Scope: four ASIC PPT backends, one function each. Surgical, not a
cross-subsystem refactor.
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: query GetPptLimit into `power_limit`; on failure fall back to
PPTable; assign that same value to current, default, and (for
Navi/Sienna) the OD min/max base.
- After: default/min/max come from PPTable (Navi/Sienna: AC or DC by
`adev->pm.ac_power`). GetPptLimit is used only for current; on query
failure current falls back to default.
- Arcturus: max becomes the PPTable default; min stays 0 (already true
in this tree from `08e5f8e1a24fb`).
- Aldebaran: max already came from `pptable->PptLimit`; default now does
too, instead of the GetPptLimit result.
- Path: init via `smu_late_init()` → `smu_get_asic_power_limits()`, and
GPU reset via `smu_reset()` which re-runs late_init. Also used when
Sienna/Aldebaran re-query current.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [Logic / correctness] Using a mutable firmware PPT as the
immutable hwmon default/range. Fix: PPTable owns capabilities; PMFW owns
current.
Step 2.4: ASSESS THE FIX QUALITY
Record: Obviously correct and matches `smu_v13_0_0_get_power_limit()` /
`smu_v14_0_2_get_power_limit()` already in this tree. Minimal.
Regression risk is low: Navi/Sienna now pick DC limits on battery, which
is the same rule SMU13 already uses here. Desktop `ac_power` is normally
true, so those cards keep AC limits. No API or locking changes.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: The GetPptLimit-as-everything pattern dates to `1e239fdd31cdf1`
(Evan Quan, 2020-06-08, “maximize code sharing around power limit”).
Min/max pointer args came from `1958946858a62b` (Ma Jun, 2023-10-12).
Present since well before 6.12.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. The real ancestor is the 2020 GetPptLimit
sharing, which is in this tree.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- `08e5f8e1a24fb` already in this tree: Arcturus min=0 (Cc: stable).
This patch keeps that.
- `b3498e00aff57` “fix smu13 power limit default/cap calculation” (Yang
Wang, Cc: stable, in v6.12.94): same bug on SMU13.
- `b3adc697752b9` follow-up SMU13 range fix (Cc: stable, Closes gitlab
5419).
- `a322d276f3d10` SMU14 range fix (Cc: stable).
- This candidate is the remaining SMU11/Aldebaran analog; not already
applied (`git merge-base --is-ancestor 25f4a46b0c8acd HEAD` failed).
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Yang Wang is a regular amd/pm contributor in this tree
(SMU13/SMU14 power-limit fixes, pptable UAF, metrics). Kenneth Feng
reviewed those as well.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Standalone. No new helpers. `SocketPowerLimitDc`,
`GET_PPTABLE_MEMBER`, and `adev->pm.ac_power` already exist here. Later
drm-next-7.3 series (refactor by controller, OD percentage,
save/restore, restore after reset) is a large follow-on and is not
required for this hunk.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 25f4a46b0c8acd77c9065b50a1fe48af27d91fdf`: lore.kernel.org
returned server error; no match.
- lore.kernel.org WebFetch: 403.
- drm.git commit page confirms SHA, author, reviewer, committer.
- amd-gfx July 2026: related 4-patch “refactor PPT limit runtime policy”
(Kenneth Feng reviewed). “derive stable PPT limits from PPTable” is
listed first among Yang Wang’s five commits in the amd-drm-next-7.3
pull (mail-archive).
- UNVERIFIED: full review thread / NAKs / explicit Cc: stable for this
exact patch (lore 403).
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: Kenneth Feng Reviewed-by; Alex Deucher signed off. Recipients
from `b4 dig -w` unverified.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by on this commit. Sibling SMU13 fix closed
https://gitlab.freedesktop.org/drm/amd/-/work_items/5227 (WebFetch 403;
title/body unverified). Follow-up closed work item 5419.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: First of five PPT commits in amd-drm-next-7.3. Later four are a
large policy refactor. This patch is self-contained.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: UNVERIFIED for this SHA (lore 403). The same class of fix for
SMU13/SMU14 already landed in this 6.12 tree with Cc: stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `arcturus_get_power_limit`, `navi10_get_power_limit`,
`sienna_cichlid_get_power_limit`, `aldebaran_get_power_limit`.
Step 5.2: TRACE CALLERS
Record: Registered as `.get_power_limit` in each ppt_funcs table.
Invoked via `smu_get_asic_power_limits()` from:
- `smu_late_init()` (boot and `smu_reset()`), filling
`smu->{current,default,max,min}_power_limit`
- `smu_get_power_limit()` for CURRENT on Sienna-family (11.0.7/11/12/13)
and Aldebaran (13.0.2)
Hwmon `power1_cap{,_default,_max,_min}` goes
`amdgpu_hwmon_show_power_cap_*` → `amdgpu_dpm_get_power_limit` →
`smu_get_power_limit`. Sets are range-checked against cached
`max_power_limit`/`min_power_limit` in `smu_set_power_limit()`.
Step 5.3: TRACE CALLEES
Record: `smu_v11_0_get_current_power_limit()` /
`smu_cmn_send_smc_msg(SMU_MSG_GetPptLimit)` for current only; PPTable
fields for defaults.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace-reachable via hwmon sysfs (typically root). GPU reset
/ late_init also refresh the caches. Reachable on Navi10 (RX 5700),
Sienna (RX 6800/6900, 6000M), Arcturus (MI100), Aldebaran (MI200).
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: SMU13 (`smu_v13_0_0`, `smu_v13_0_7`) and SMU14 (`smu_v14_0_2`)
already use PPTable + AC/DC for default/min/max in this tree. These four
backends were the leftover GetPptLimit-for-everything copies.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Local tree is **pending-6.12 / 6.12.111**
(`p-6.12-3-g88406e77611c6`). The four `*_get_power_limit` functions
match the patch “before” side. Bug introduced ~2020 (`1e239fdd31cdf1`),
long before 6.12.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply expected. Navi10 context below the hunk differs
(`MAX_PCIE_CONF` vs `NUM_LINK_LEVELS`) but that is outside this
function. Arcturus min=0 already present.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: SMU13/SMU14 analogs are here; these four ASICs are not. No
earlier version of this exact change.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [drm/amd/pm SWSMU] [IMPORTANT] — common AMD dGPU/instinct power
management, not core mm/net, but widely used hardware.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Actively maintained; recent 6.12.y already took SMU13/SMU14
power-limit correctness fixes from the same author.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific: Navi10/Navi14, Sienna Cichlid family, Arcturus,
Aldebaran. Anyone using hwmon power cap (LACT, CoreCtrl, scripts) or
hitting GPU reset.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Always at `smu_late_init` if PMFW current ≠ PPTable default (boot
power source / firmware policy).
- GPU reset (`smu_reset` → late_init) refreshes default/max/min from
GetPptLimit, so a runtime policy or leftover firmware value rewrites
advertised range.
- In this 6.12 tree, DEFAULT/MAX/MIN hwmon reads use the cache, so a
live userspace write to `power1_cap` does not immediately rewrite
`power1_cap_default` unless late_init/reset re-runs. The commit’s
first symptom is therefore mainly boot/reset, not every write. Still a
real bug.
- Trigger is privileged sysfs or reset, not an unprivileged crash
primitive.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Incorrect hwmon capabilities; after reset,
`smu_set_power_limit()` can reject a previously legal TDP because max
was derived from the runtime PPT. No oops/UAF/corruption. Severity:
MEDIUM (functional / ABI), same class already accepted for this tree on
SMU13.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record: Benefit medium-high for affected GPUs (correct caps, no trapped
range after reset). Risk low (~40 net lines, four isolated functions,
established pattern). Ratio favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real bug: mutable PMFW state used as immutable hwmon default/min/max.
- After GPU reset, cached max/min can shrink and block restoring the
platform TDP.
- Same class already backported to this 6.12 tree for SMU13/SMU14
(`b3498e00aff57`, `b3adc697752b9`, `a322d276f3d10`), all Cc: stable.
- Small, obviously correct, no new APIs.
- Buggy code is in this tree; patch applies cleanly.
- Reviewed by Kenneth Feng, signed off by Alex Deucher.
AGAINST:
- Not a crash, security hole, or data corruption.
- First of a later 5-commit PPT series; later patches are large
refactors (do not take those).
- Navi/Sienna AC/DC selection is extra vs the old always-AC fallback
(same as already-stable SMU13).
- No Fixes:/Reported-by on this commit; lore thread unverified.
UNRESOLVED:
- Full amd-gfx review text / NAKs (lore 403, b4 failed).
- GitLab 5227 details (403).
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — matches SMU13/14 in this tree;
AMD reviewer + maintainer.
2. Fixes a real bug that affects users? PASS — wrong hwmon caps; reset
can trap the power range.
3. Important issue? PASS — not a panic, but the same issue was already
treated as stable-worthy here for newer ASICs; user-visible PM/sysfs
breakage on common GPUs.
4. Small and contained? PASS — four functions, ~70 lines.
5. No new features or APIs? PASS — corrects existing hwmon values; AC/DC
uses existing PPTable fields.
6. Can apply to the local tree? PASS — buggy code present; clean apply
expected.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None of the automatic exceptions (device ID / quirk / DT / build
/ docs). Qualifies as a normal small correctness fix.
Step 9.4: MAKE YOUR DECISION
This should be backported to this 6.12 tree. It is the leftover
SMU11/Aldebaran half of a power-cap reporting bug whose SMU13/SMU14 half
is already in 6.12.y. Do not pull the later PPT refactor series with it.
Verification:
- [Phase 1] Parsed tags: author Yang Wang, Reviewed-by Kenneth Feng, SOB
Alex Deucher; no Fixes/Reported-by/Cc stable
- [Phase 1] drm.git SHA 25f4a46b0c8acd77c9065b50a1fe48af27d91fdf
confirmed via search snippet
- [Phase 2] Diff: four `*_get_power_limit` functions; PPTable for
default/min/max, GetPptLimit only for current
- [Phase 3] git describe HEAD: p-6.12-3-g88406e77611c6; make
kernelversion 6.12.111
- [Phase 3] git merge-base --is-ancestor 25f4a46b0c8acd HEAD: not an
ancestor (not in this tree)
- [Phase 3] git blame: GetPptLimit pattern from 1e239fdd31cdf1 (2020);
still present in all four files
- [Phase 3] Related stable commits in this tree: b3498e00aff57
(v6.12.94), b3adc697752b9, a322d276f3d10, 08e5f8e1a24fb
- [Phase 4] b4 dig -c 25f4a46b0c8acd: lore server error, no match
- [Phase 4] lore WebFetch 403; gitlab 5227 403
- [Phase 4] amd-gfx July 2026: 4-patch PPT refactor series by same
author; drm-next-7.3 pull lists this commit first of five
- [Phase 5] Callers: smu_late_init, smu_reset, smu_get_power_limit,
hwmon power1_cap*; range check in smu_set_power_limit
- [Phase 5] SMU13/SMU14 in this tree already implement the post-fix
pattern
- [Phase 6] Read all four local functions: match the patch “before” side
- [Phase 6] GET_PPTABLE_MEMBER and SocketPowerLimitDc exist for Sienna
and Beige Goby
- [Phase 8] Failure mode: wrong hwmon caps / possible -EINVAL on set
after reset; not oops
- UNVERIFIED: original lore discussion, NAKs, gitlab 5227 body, whether
SocketPowerLimitDc is zero on any Navi10 mobile SKU
This is a small, already-reviewed correction of hwmon PPT
default/min/max on GPUs that still use GetPptLimit for those values. The
same bug was already backported on SMU13/SMU14 in this 6.12 tree, the
code is present, and the follow-on refactor series is not required.
**YES**
.../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 25 ++++++++-------
.../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 32 +++++++++++--------
.../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 28 +++++++++-------
.../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 8 +++--
4 files changed, 53 insertions(+), 40 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 4fff78da81ff8..2b2d3c3aa20ba 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1329,24 +1329,25 @@ static int arcturus_get_power_limit(struct smu_context *smu,
uint32_t *min_power_limit)
{
PPTable_t *pptable = smu->smu_table.driver_pptable;
- uint32_t power_limit;
+ uint32_t current_limit, default_limit;
- if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
- /* the last hope to figure out the ppt limit */
- if (!pptable) {
- dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
- return -EINVAL;
- }
- power_limit =
- pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ if (!pptable) {
+ dev_err(smu->adev->dev,
+ "Cannot get PPT limit due to pptable missing!");
+ return -EINVAL;
}
+ default_limit = pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+
+ if (smu_v11_0_get_current_power_limit(smu, ¤t_limit))
+ current_limit = default_limit;
+
if (current_power_limit)
- *current_power_limit = power_limit;
+ *current_power_limit = current_limit;
if (default_power_limit)
- *default_power_limit = power_limit;
+ *default_power_limit = default_limit;
if (max_power_limit)
- *max_power_limit = power_limit;
+ *max_power_limit = default_limit;
/*
* No lower bound is imposed on the limit. Any unreasonable limit set
* will result in frequent throttling.
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index a2fcf678182b4..4737ceb2a5434 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2393,22 +2393,26 @@ static int navi10_get_power_limit(struct smu_context *smu,
(struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
PPTable_t *pptable = smu->smu_table.driver_pptable;
- uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
+ uint32_t current_limit, default_limit;
+ uint32_t od_percent_upper = 0, od_percent_lower = 0;
- if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
- /* the last hope to figure out the ppt limit */
- if (!pptable) {
- dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
- return -EINVAL;
- }
- power_limit =
- pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ if (!pptable) {
+ dev_err(smu->adev->dev,
+ "Cannot get PPT limit due to pptable missing!");
+ return -EINVAL;
}
+ default_limit = smu->adev->pm.ac_power ?
+ pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+ pptable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+
+ if (smu_v11_0_get_current_power_limit(smu, ¤t_limit))
+ current_limit = default_limit;
+
if (current_power_limit)
- *current_power_limit = power_limit;
+ *current_power_limit = current_limit;
if (default_power_limit)
- *default_power_limit = power_limit;
+ *default_power_limit = default_limit;
if (powerplay_table) {
if (smu->od_enabled &&
@@ -2422,15 +2426,15 @@ static int navi10_get_power_limit(struct smu_context *smu,
}
dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
- od_percent_upper, od_percent_lower, power_limit);
+ od_percent_upper, od_percent_lower, default_limit);
if (max_power_limit) {
- *max_power_limit = power_limit * (100 + od_percent_upper);
+ *max_power_limit = default_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
- *min_power_limit = power_limit * (100 - od_percent_lower);
+ *min_power_limit = default_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 31c2c0386b1f9..d553c6fbab47c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -632,20 +632,24 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
struct smu_11_0_7_powerplay_table *powerplay_table =
(struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
struct smu_11_0_7_overdrive_table *od_settings = smu->od_settings;
- uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
- uint16_t *table_member;
+ uint32_t current_limit, default_limit;
+ uint32_t od_percent_upper = 0, od_percent_lower = 0;
+ u16 *power_limit_ac, *power_limit_dc;
- GET_PPTABLE_MEMBER(SocketPowerLimitAc, &table_member);
+ GET_PPTABLE_MEMBER(SocketPowerLimitAc, &power_limit_ac);
+ GET_PPTABLE_MEMBER(SocketPowerLimitDc, &power_limit_dc);
- if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
- power_limit =
- table_member[PPT_THROTTLER_PPT0];
- }
+ default_limit = smu->adev->pm.ac_power ?
+ power_limit_ac[PPT_THROTTLER_PPT0] :
+ power_limit_dc[PPT_THROTTLER_PPT0];
+
+ if (smu_v11_0_get_current_power_limit(smu, ¤t_limit))
+ current_limit = default_limit;
if (current_power_limit)
- *current_power_limit = power_limit;
+ *current_power_limit = current_limit;
if (default_power_limit)
- *default_power_limit = power_limit;
+ *default_power_limit = default_limit;
if (powerplay_table) {
if (smu->od_enabled &&
@@ -659,15 +663,15 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
}
dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
- od_percent_upper, od_percent_lower, power_limit);
+ od_percent_upper, od_percent_lower, default_limit);
if (max_power_limit) {
- *max_power_limit = power_limit * (100 + od_percent_upper);
+ *max_power_limit = default_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
- *min_power_limit = power_limit * (100 - od_percent_lower);
+ *min_power_limit = default_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}
return 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
index 18d5d07045098..9e67e57d70b75 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -1281,8 +1281,12 @@ static int aldebaran_get_power_limit(struct smu_context *smu,
if (current_power_limit)
*current_power_limit = power_limit;
- if (default_power_limit)
- *default_power_limit = power_limit;
+ if (default_power_limit) {
+ if (pptable)
+ *default_power_limit = pptable->PptLimit;
+ else
+ *default_power_limit = power_limit;
+ }
if (max_power_limit) {
if (pptable)
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18] HID: universal-pidff: Add support for Turtle Beach VelocityOne Race
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (80 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] drm/amd/pm: derive stable PPT limits from PPTable Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] nvme: bound ns descriptor header and body to identify buffer Sasha Levin
` (434 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Tomasz Pakuła, Jiri Kosina, Sasha Levin, jikos, bentiss,
oleg, linux-input, linux-kernel
From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
[ Upstream commit 53f7f7955a684e820bdd6bd6792c45c4b434f637 ]
Add usb VID and device PID to hid-ids.h
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.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**
- Record: `[HID / universal-pidff] [Add] USB VID/PID so Turtle Beach
VelocityOne Race binds to the existing hid-universal-pidff driver`
**Step 1.2 — Tags**
- Record:
- `Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>`
(author; co-author of this driver)
- `Signed-off-by: Jiri Kosina <jkosina@suse.com>` (HID maintainer)
- `[Upstream commit 53f7f7955a684e820bdd6bd6792c45c4b434f637]` and
`Signed-off-by: Sasha Levin` ignored as pipeline markers
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, `Link:`, or `Cc: stable` (absence of the last two is expected)
**Step 1.3 — Body**
- Record: Body is one sentence: “Add usb VID and device PID to hid-
ids.h”. No crash, leak, or corruption described. The claimed intent is
hardware enablement for one USB HID device. No version range given.
Root cause as stated: the IDs were missing from the existing driver’s
table.
**Step 1.4 — Hidden bug fix?**
- Record: Not a disguised leak/race/UAF. It is a USB ID addition to an
existing driver (stable exception category 1).
---
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
- Record:
- `drivers/hid/hid-ids.h`: +3 (two `#define`s plus a blank line)
- `drivers/hid/hid-universal-pidff.c`: +1 in
`universal_pidff_devices[]`
- Net +4 lines, two files, one table plus ID macros
- Classification: single-purpose, surgical device-ID add
**Step 2.2 — Code flow**
- Record:
- Before: `0x10f5:0x7077` is unmatched by this driver and falls
through to generic HID.
- After: HID core matches `HID_USB_DEVICE(USB_VENDOR_ID_TURTLE_BEACH,
USB_DEVICE_ID_TB_VELOCITYONE_RACE)` and calls
`universal_pidff_probe()`.
- Path: device enumeration / probe, not an error path. No
`driver_data` quirks.
**Step 2.3 — Bug mechanism**
- Record: `[Hardware enablement / USB device ID]` — the driver already
implements PID force-feedback wrapping; this only lists one more
VID/PID. Not UAF, leak, race, overflow, or init-bug.
**Step 2.4 — Fix quality**
- Record: Obviously correct as an ID table add. Insertion sits
alphabetically between TURBOX and TWINHAN. Vendor `0x10f5` already
identifies Turtle Beach elsewhere (`drivers/input/joystick/xpad.c`
uses `0x10f5` with other PIDs `0x7005`/`0x7008`/`0x7073`). PID
`0x7077` does not collide with those. No public API change. Regression
risk is low: only this VID:PID binds; probe returns 0 even if the PID
usage page is absent.
---
## Phase 3: Git history
**Step 3.1 — Blame**
- Record: New lines; they did not exist before this commit. Surrounding
`hid-ids.h` TURBOX/TWINHAN macros date to 2008–2017. The device table
terminator was last touched by `5b9cae8c6472e` (clang-format, 2025).
The driver itself was added in `f06bf8d94fffb` (“HID: Add hid-
universal-pidff driver and supported device ids”, 2025-02-03; `git
describe` of that commit is `v6.13-4738-gf06bf8d94fffb`).
**Step 3.2 — Fixes: tag**
- Record: No `Fixes:` tag. Not applicable.
**Step 3.3 — File history**
- Record: Recent related commits on this driver: Asetek ID adds
(`c385f61108d40`), spelling/format nits, and `01d9874e84d3a` (stop
device on FF init failure). No prerequisite refactor is required for
this ID. Standalone; not “patch X/Y”. No later follow-up on these
files after this commit.
**Step 3.4 — Author**
- Record: Tomasz Pakuła is a listed `MODULE_AUTHOR` of `hid-universal-
pidff.c` and a frequent hid-pidff contributor (overflow, NPD,
playback, Asetek IDs). This is the subsystem’s own device-table
maintainer, not a drive-by.
**Step 3.5 — Dependencies**
- Record: Needs `hid-universal-pidff.c`, `USB_VENDOR_ID_*` macros, and
`hid_pidff_init_with_quirks`. All are in this tree. `git merge-base
--is-ancestor f06bf8d94fffb HEAD` succeeds; `git merge-base --is-
ancestor f06bf8d94fffb v6.18` also succeeds. Can apply standalone.
---
## Phase 4: Mailing list / external research
**Step 4.1 — Original discussion**
- Record: `b4 dig -c 53f7f7955a684e820bdd6bd6792c45c4b434f637` → https:/
/patch.msgid.link/20260922131758.1242755-1-
tomasz.pakula.oficjalny@gmail.com
- `b4 dig -a`: single v1 series only; no v2/v3.
- LKML: https://lkml.iu.edu/2609.2/17309.html (submission),
https://lkml.iu.edu/2609.2/21230.html (Jiri Kosina: “Applied,
thanks.”)
- No NAK, no requested changes, no stable nomination in review.
lore.kernel.org fetch returned 403; discussion confirmed via `b4 dig`
+ LKML/Patchew mirrors.
**Step 4.2 — Recipients (`b4 dig -w`)**
- Record: `jikos@kernel.org` (HID maintainer), `oleg@makarenk.ooo` (co-
author), `linux-input@vger.kernel.org`, `linux-
kernel@vger.kernel.org`. Right lists and maintainer were on Cc; Kosina
applied it.
**Step 4.3 — Bug report**
- Record: No `Reported-by` / syzbot / bugzilla. Phoronix (secondary, not
a kernel bug tracker) notes basic HID input already worked and this
listing improves FF for the VelocityOne Race. That is consistent with
an ID add, not a crash fix.
**Step 4.4 — Series context**
- Record: Standalone one-patch series. Same pattern as earlier Asetek ID
adds in this driver.
**Step 4.5 — Stable list**
- Record: `WebFetch` of `https://lore.kernel.org/stable/?q=VelocityOne`
returned 403. Web search did not show a stable-list thread about this
patch. UNVERIFIED that nobody discussed it on stable@; no evidence of
a NAK there either.
---
## Phase 5: Code semantic analysis
**Step 5.1 — Functions**
- Record: No function body changed. Data only:
`universal_pidff_devices[]` plus two macros. Probe path that becomes
reachable: `universal_pidff_probe` → `universal_pidff_input_mapping` /
`universal_pidff_input_configured`.
**Step 5.2 — Callers**
- Record: `universal_pidff_probe` is only the `.probe` of `struct
hid_driver universal_pidff`, registered via `module_hid_driver`.
Invoked by HID/USB enumeration when VID:PID matches. Not IRQ, not a
syscall hot path.
**Step 5.3 — Callees**
- Record: `hid_parse`, `hid_hw_start`, `hid_pidff_init_with_quirks`,
`hid_hw_stop`. Existing, already used by every other ID in the table.
**Step 5.4 — Reachability**
- Record: Reachable when a user plugs in `10f5:7077` and
`CONFIG_HID_UNIVERSAL_PIDFF` is enabled (`depends on USB_HID &&
HID_PID`). Userspace cannot trigger it without that hardware.
**Step 5.5 — Similar patterns**
- Record: Same table already lists Moza, Cammus, VRS, FFBeast, Lite
Star/PXN, Asetek. This is the established way this driver gains
devices. Turtle Beach VID `0x10f5` is already used in `xpad.c` for
other products; PID `0x7077` is unique.
---
## Phase 6: Local tree (this checkout)
**Step 6.1 — Does the code exist here?**
- Record: Local tree is **6.18.57** (`make kernelversion`; `git describe
HEAD` = `v6.18.57-155-gcdf239ca885b2`). `hid-universal-pidff.c`
exists. Driver intro `f06bf8d94fffb` is an ancestor of both `HEAD` and
`v6.18`. Parent of this candidate still has the Asetek rows and the
empty terminator; the ID macros were absent (`git grep
USB_VENDOR_ID_TURTLE` on the parent was empty). The hardware and
driver this listing targets are in this tree.
**Step 6.2 — Backport difficulty**
- Record: Clean apply. Parent context matches the provided diff (TURBOX
block, then TWINHAN; Asetek entries then `{}`). No refactor gap.
**Step 6.3 — Related fixes already here?**
- Record: No other VelocityOne Race HID listing. No alternate fix for
`10f5:7077` in HID. `xpad.c` does not claim PID `0x7077`.
---
## Phase 7: Subsystem context
**Step 7.1**
- Record: `[HID USB force-feedback helper] [IMPORTANT for owners of
listed wheels; PERIPHERAL vs core kernel]`. Not mm/fs/net core.
Optional `CONFIG_HID_UNIVERSAL_PIDFF`.
**Step 7.2**
- Record: Actively maintained in 2025–2026 (quirks, Asetek IDs, pidff
correctness fixes). Mature enough that ID adds are the normal
extension mechanism.
---
## Phase 8: Impact and risk
**Step 8.1 — Who is affected**
- Record: Driver-specific / config-specific: users who own a Turtle
Beach VelocityOne Race and enable this HID driver. Everyone else is
unchanged.
**Step 8.2 — Trigger**
- Record: Plug in that USB wheel. Not a race. Unprivileged user can plug
hardware; no syscall exploit surface beyond normal HID.
**Step 8.3 — Failure mode without the patch**
- Record: Device stays on hid-generic: basic input, missing this
driver’s PID FF init and button-range mapping. Not
oops/deadlock/corruption. Severity for those users: functional
hardware gap (FF), **MEDIUM** as a bug, but it is the documented
device-ID exception.
**Step 8.4 — Risk vs benefit**
- Record: Benefit: FF/PID support for this wheel on 6.18.y without a
full kernel upgrade. Risk: very low (4 lines, match is VID+PID, no
quirk, probe already tolerates missing PID page). Ratio: favorable for
a device-ID add.
---
## Phase 9: Synthesis
**Step 9.1 — Evidence**
For:
- USB ID add to a driver that already exists in this 6.18 tree (stable
exception 1).
- +4 lines, no new APIs, no new driver, no new sysfs/module params.
- HID maintainer applied v1 with no objections.
- Author maintains this driver.
- VID `0x10f5` is already Turtle Beach in-tree; PID does not clash with
xpad entries.
- Applies cleanly here.
Against:
- Not a crash/security/corruption fix.
- Short commit message; no `Reported-by`.
- Niche ~$650 sim-racing hardware.
- Improves FF rather than repairing a generic HID oops.
Unresolved:
- lore.kernel.org HTTP 403; stable@ thread not confirmed.
- No in-tree test that this exact PID speaks USB PID FF (same as other
IDs in this table).
**Step 9.2 — Stable rules**
1. Obviously correct and tested? **PASS** — mechanical ID add;
maintainer applied it. No in-tree Tested-by, but the change is the
same class as prior IDs in this file.
2. Real issue affecting users? **PASS** — without the ID, this wheel
does not get the existing PID FF path.
3. Important (crash/security/deadlock) **or** listed exception? **PASS**
— USB device ID on an existing driver.
4. Small and contained? **PASS** — 4 lines, two files.
5. No new features/APIs? **PASS** — no new driver, ioctl, or userspace
ABI; only an ID in an existing table.
6. Applies to this tree? **PASS** — driver and insertion point are
present on 6.18.57.
**Step 9.3 — Exception**
- Record: **NEW DEVICE ID** (USB VID/PID) on existing `hid-universal-
pidff`.
**Step 9.4 — Decision**
This is exactly the device-ID class stable trees take. The driver is in
6.18; the patch is tiny and isolated to `10f5:7077`. Benefit is real for
owners of that wheel; risk to everyone else is negligible.
---
### What the commit does for this tree
It lists Turtle Beach VelocityOne Race (`USB 10f5:7077`) in `hid-
universal-pidff` so 6.18 systems can use the PID force-feedback path
already in this kernel, instead of generic HID only.
### Stable-rules fit
Meets the device-ID exception: existing driver, IDs only, clean apply,
no new API.
### Risk vs benefit
Very low risk, localized hardware enablement. No locking or error-path
change.
### Concerns
None that block backport. No extra quirks or follow-up commits required
in this tree. Stable-list discussion could not be fetched (403).
---
Verification:
- [Phase 1] Parsed tags: author SOB + Jiri Kosina SOB; no
Fixes/Reported-by/Cc:stable
- [Phase 1] Body is a one-line ID add, not a crash write-up
- [Phase 2] Diff: +3 `hid-ids.h`, +1 table row; no function logic change
- [Phase 2] No `driver_data` quirk on the new entry
- [Phase 3] `git blame` on new macros → this commit; surrounding IDs
from 2008–2017
- [Phase 3] Driver intro `f06bf8d94fffb` (`v6.13-4738-gf06bf8d94fffb`);
ancestor of HEAD and of `v6.18`
- [Phase 3] `git log --oneline --author="Tomasz Pakuła" --
drivers/hid/`: driver co-maintainer, many pidff commits
- [Phase 3] No later commits on these files after this ID add
- [Phase 4] `b4 dig -c 53f7f7955a684e820bdd6bd6792c45c4b434f637`: lore
msgid `20260922131758.1242755-1-tomasz.pakula.oficjalny@gmail.com`
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: jikos@kernel.org, linux-input, co-author Oleg
- [Phase 4] LKML: Kosina “Applied, thanks.”
(https://lkml.iu.edu/2609.2/21230.html)
- [Phase 4] lore.kernel.org WebFetch: 403; used LKML/Patchew/`b4`
instead
- [Phase 5] Probe only via `module_hid_driver`; callees
`hid_parse`/`hid_hw_start`/`hid_pidff_init_with_quirks` exist here
- [Phase 5] `0x10f5` in `xpad.c` for other PIDs; `0x7077` not used there
- [Phase 6] `make kernelversion` → 6.18.57; `git describe HEAD` →
`v6.18.57-155-gcdf239ca885b2`
- [Phase 6] Parent of candidate: no `USB_VENDOR_ID_TURTLE`; Asetek rows
present; apply context matches
- [Phase 8] Failure mode: missing FF/mapping for one USB wheel, not oops
- UNVERIFIED: stable@ archive (HTTP 403); no in-kernel confirmation the
device implements USB PID (same as other table IDs)
**YES**
drivers/hid/hid-ids.h | 3 +++
drivers/hid/hid-universal-pidff.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ca5c62f29aebe..69b1b0f98c99d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1415,6 +1415,9 @@
#define USB_DEVICE_ID_ASUS_MD_5110 0x5110
#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100
+#define USB_VENDOR_ID_TURTLE_BEACH 0x10f5
+#define USB_DEVICE_ID_TB_VELOCITYONE_RACE 0x7077
+
#define USB_VENDOR_ID_TWINHAN 0x6253
#define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100
diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
index 60180467a0bfd..f1854cfe42d0d 100644
--- a/drivers/hid/hid-universal-pidff.c
+++ b/drivers/hid/hid-universal-pidff.c
@@ -187,6 +187,7 @@ static const struct hid_device_id universal_pidff_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_FORTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_LA_PRIMA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_TONY_KANAAN) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TURTLE_BEACH, USB_DEVICE_ID_TB_VELOCITYONE_RACE)},
{}
};
MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] nvme: bound ns descriptor header and body to identify buffer
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (81 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: universal-pidff: Add support for Turtle Beach VelocityOne Race Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] udf: validate extent partition references in udf_current_aext() Sasha Levin
` (433 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Hari Mishal, Christoph Hellwig, Greg Kroah-Hartman, Keith Busch,
Sasha Levin, axboe, sagi, linux-nvme, linux-kernel
From: Hari Mishal <harimishal1@gmail.com>
[ Upstream commit 3c568b35a0d309acb40746552bec2af24cd550ef ]
nvme_identify_ns_descs() allocates a buffer and gives it to the
controller, which populates it and then iterates the buffer with
variable byte increments that vary by type and body size. But, there is
no bounds check inside the iteration itself except the loop bound
itself. Fix this by checking and stopping iteration if the next header
or its declared body would go past the buffer itself.
Assisted-by: gkh_clanker_t1000
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[nvme]** **[bound]** bound namespace descriptor header and
body to the Identify buffer so iteration cannot walk off the end.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Assisted-by:** gkh_clanker_t1000 (LLM-assisted; not a substitute for
review)
- **Reviewed-by:** Christoph Hellwig \<hch@lst.de\> (NVMe maintainer)
- **Signed-off-by:** Hari Mishal \<harimishal1@gmail.com\> (author)
- **Signed-off-by:** Greg Kroah-Hartman \<gregkh@linuxfoundation.org\>
(submitted the series)
- **Signed-off-by:** Keith Busch \<kbusch@kernel.org\> (NVMe maintainer;
applied)
- **No Fixes:** tag (expected for this review pipeline)
- **No Cc: stable** (expected)
- **No Reported-by / Tested-by / Link / syzbot**
- Ignore pipeline markers: none in the supplied text beyond the usual
SOBs
Notable: reviewed and applied by the two primary NVMe maintainers.
Submitted as **[PATCH 1/2]** with an unrelated sibling (FDP clamp).
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `nvme_identify_ns_descs()` allocates a 4096-byte Identify
buffer, lets the controller fill it, then walks variable-length
namespace ID descriptors. The only guard was `pos <
NVME_IDENTIFY_DATA_SIZE`.
- **Symptom/failure mode:** out-of-bounds header/body access when a
descriptor header sits near the end of the buffer, or `nidl` claims a
body that extends past 4096 bytes. That is a heap OOB read (possible
crash, KASAN report, or adjacent-heap leak via `memcpy` in
`nvme_process_ns_desc()`).
- **Version info:** none in the message. The walker has existed since
2017.
- **Root cause:** device-controlled stride (`sizeof(header) + nidl`)
with no check that the next header or declared body still fits in the
allocation.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a disguised cleanup.** It is an explicit bounds-check fix.
The verb “bound” here means “do not read past the buffer.”
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/nvme/host/core.c` — **+4 / −0**
- **Function:** `nvme_identify_ns_descs()`
- **Scope:** single-file surgical fix (two `if` + `break` pairs)
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record: **Before:** loop at `pos`, form `cur = data + pos`, read
`cur->nidl` immediately, then call `nvme_process_ns_desc()` which
`memcpy`s the body. **After:** (1) if the 4-byte header would pass the
buffer, stop; (2) if `nidl == 0`, stop (unchanged); (3) if header+body
would pass the buffer, stop; then process. Still an Identify/scan path,
not an error-recovery rewrite. Stopping with `break` matches existing
`nidl == 0` / `len < 0` handling (no new error code for a truncated
trailing descriptor).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Memory safety / out-of-bounds]** Device-controlled OOB read.
Mechanism, verified against `struct nvme_ns_id_desc` (`nidt`, `nidl`,
reserved — 4 bytes) and `nvme_process_ns_desc()`:
- If `pos` is 4093–4095, reading the header itself is OOB.
- If the header fits but `nidl` does not leave enough remaining bytes,
known-type `memcpy` (EUI64/NGUID/UUID/CSI) reads past the
`kzalloc(4096)` buffer after the length-equals-expected check.
The fix stops before those accesses. Header check is first, so
`cur->nidl` is only read when the header is in-bounds.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: **Obviously correct and minimal.** Check order is right. `nidl`
is `__u8` (max 255); `pos` is non-negative and `< 4096`; `pos + 4 +
nidl` cannot overflow a 32-bit `int`. On spec-compliant lists that fit
in 4096 bytes the new branches never fire. **Regression risk: very
low.** Truncating a malformed last descriptor is safer than reading past
the buffer. If CSI is truncated on a multi-CSS controller, the existing
`!csi_seen` path can still return `-EINVAL` — that is the conservative
failure.
No API, locking, or data-structure change.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: Loop introduced by **`3b22ba2682b432`** (“nvme: get list of
namespace descriptors”, Johannes Thumshirn, 2017-06-15) — first
contained in **v4.13-rc1**. The two bounds checks are
**`3c568b35a0d309`** (this commit, 2026-07-14). The walker has been in-
tree for many years.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Buggy pattern comes from `3b22ba2682b432`,
which is an ancestor of this checkout.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Same-author sibling **`bc7f75eba5001`** — `nvmet: passthru: fix OOB
reads when parsing ns id descriptor list` (same descriptor-list OOB
class on the target passthru path). Independent file.
- Series sibling **`29261f8bb4166`** — `nvme: clamp FDP nruhsd...` is a
different function (`nvme_query_fdp_info`). **This 1/2 does not depend
on 2/2.**
- Later `core.c` changes (kmalloc_obj, unsigned nsid print,
scan/SRCU/FDP) do not rewrite this loop. **Standalone.**
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Hari Mishal is not an NVMe maintainer; three NVMe commits, all
device-controlled bounds issues. Weight comes from **Christoph Hellwig
Reviewed-by** and **Keith Busch** applying it to nvme-7.3.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: **None.** Adds checks in an existing loop.
`nvme_process_ns_desc()`, `NVME_IDENTIFY_DATA_SIZE` (4096), and `struct
nvme_ns_id_desc` already exist here. Applies standalone.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig:** https://patch.msgid.link/2026070931-stopping-
cost-239a@gregkh
- **v1 only** (`b4 dig -a`); applied version is that v1
- Thread (mbox): Christoph: “Looks good: Reviewed-by”; Keith: “Thanks,
series applied to nvme-7.3.”
- **No NAK, no stability concerns, no request for Cc: stable**
WebFetch of lore.kernel.org returned **403**; discussion recovered via
`b4 dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc included **linux-nvme**, **Keith Busch, Jens
Axboe, Christoph Hellwig, Sagi Grimberg** (all NVM EXPRESS DRIVER
maintainers). Appropriate audience.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: **No user/syzbot/bugzilla report.** Found by analysis (Greg’s
clanker + author). Still a real, reachable OOB given a malformed
Identify NS descriptor list.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: **[PATCH 1/2]** / **[PATCH 2/2]** share an author and file but
not code. 1/2 is self-contained. Target passthru fix is a related class,
not a prerequisite.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable WebFetch **403**. **UNVERIFIED** whether
stable@ already discussed this hash. Absence of Cc: stable is expected
here and is not a negative.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: **`nvme_identify_ns_descs()`** modified;
**`nvme_process_ns_desc()`** callee (memcpy of descriptor bodies).
**Step 5.2: TRACE CALLERS**
Record:
- Only caller: `nvme_scan_ns()` in `drivers/nvme/host/core.c`
- `nvme_scan_ns()` ← `nvme_scan_ns_async()` /
`nvme_scan_ns_sequential()`
- Those ← `nvme_scan_work()` on `ctrl->scan_work`
Context: **process-context workqueue**, NVMe namespace scan on probe,
reset, and NS-changed AEN. Common path for NVMe hosts, not IRQ/hot-
cache.
**Step 5.3: TRACE CALLEES**
Record: `kzalloc` / `nvme_submit_sync_cmd` / `nvme_process_ns_desc` /
`kfree`. The OOB is in the parse loop and in `nvme_process_ns_desc()`
memcpy, not in the admin command itself.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable on any NVMe 1.3+ controller (or multi-CSS) that does
not have `NVME_QUIRK_NO_NS_DESC_LIST`. Userspace does not call this
syscall-direct; a **malicious or buggy controller** (local PCIe or NVMe-
oF target) controls the buffer. That is a standard untrusted-device
memory-safety bug.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same class already bounded in `drivers/nvme/target/passthru.c`
(`pos + sizeof(*cur)` and CSI body). Host-side
`nvme_identify_ns_descs()` was the gap this commit closes.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: **`git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`**,
**`make kernelversion` = 7.3.0-rc4**
- Function and loop exist at `drivers/nvme/host/core.c`
(`nvme_identify_ns_descs`)
- Bug introduced **v4.13** (`3b22ba2682b432`), long before this branch
- The two checks are present on HEAD (this commit is an ancestor). That
is historical fact, **not** used as “already selected for stable”
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** to this `nvme_identify_ns_descs()` shape.
Context is the same 4.13-era loop; no extra helpers required. **Expected
backport difficulty: clean apply** on trees that still have this
function.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier host-side equivalent. Passthru OOB fix is a different
file. No conflicting alternate host fix.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: **NVMe host core** (`drivers/nvme/host/core.c`). **IMPORTANT** —
common block/storage path, not mm/VFS core, but widely deployed
(servers, laptops, NVMe-oF).
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Actively maintained (Keith Busch, Christoph Hellwig, et al.).
This is a small correctness fix in old parse code, not a follow-on to a
brand-new feature in 7.3.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: **Driver-specific, but broad:** NVMe hosts scanning namespaces
(almost all NVMe users on 1.3+). Triggered by device Identify data, not
a rare Kconfig.
**Step 8.2: TRIGGER CONDITIONS**
Record: Namespace scan (probe/reset/NS-changed). **Not** every I/O.
Needs a **malformed descriptor list** (buggy firmware or untrusted
target). Unprivileged local users typically cannot inject Identify
payloads without device control; NVMe-oF to an untrusted target can.
Timing-independent; deterministic given bad data.
**Step 8.3: FAILURE MODE SEVERITY**
Record: **Heap out-of-bounds read** → KASAN/oops, possible info leak, or
silent heap corruption adjacent to the Identify buffer. **Severity:
HIGH.** Not a guaranteed panic on production kernels, but it is a real
memory-safety bug in a storage driver.
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit: high** — stops device-controlled OOB on a common NVMe scan
path; 4 lines; maintainers acked.
- **Risk: very low** — two range checks; no lock/API/behavior change for
valid lists.
- **Ratio: strongly favors backport.**
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real OOB read from controller-controlled Identify NS descriptor list
- Path is namespace scan on ordinary NVMe hosts
- 4-line, obviously correct bounds checks; header checked before `nidl`
- Same bug class already recognized on the passthru parser
- Reviewed-by Christoph Hellwig; applied by Keith Busch
- Code has existed since v4.13; no missing prerequisites in this tree
- No new feature/API
**AGAINST:**
- No Fixes:/Cc: stable/syzbot/user report (not a negative per the rules)
- LLM-assisted origin (offset by maintainer review)
- Trigger needs a bogus/malicious controller, not typical I/O
- Series labeled 1/2 (sibling is independent)
**UNRESOLVED:**
- lore.kernel.org HTTP 403; thread recovered via b4 mbox
- Whether stable@ already discussed this commit: **UNVERIFIED**
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — two range checks; Reviewed-
by maintainer; applied to nvme-7.3
2. Fixes a real bug that affects users? **PASS** — OOB parse of device
Identify data
3. Important (crash/security/corruption/deadlock)? **PASS** — HIGH
memory-safety (OOB read; crash/leak potential)
4. Small and contained? **PASS** — +4 lines, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — same function/context; no
extra deps
**Step 9.3: EXCEPTION CATEGORIES**
Record: **None** (not an ID/quirk/DT/build/doc exception). It qualifies
as a normal small memory-safety fix.
**Step 9.4: DECISION**
This is a surgical host-side bounds check for a long-standing, device-
controlled OOB in NVMe namespace scanning. It meets stable rules for
this checkout (7.3-rc4; buggy walker present since v4.13). Benefit is
high; regression risk is very low.
---
### What the commit solves (for this tree)
`nvme_identify_ns_descs()` walks a 4096-byte Identify Namespace ID
Descriptor List with a device-chosen stride. Without checking that the
next 4-byte header and `nidl` body fit, a truncated or oversized last
descriptor causes an out-of-bounds header read and/or `memcpy` in
`nvme_process_ns_desc()`. That hits every NVMe scan of a 1.3+ (or multi-
CSS) controller that returns a bad list. The patch stops the loop before
those accesses. Compliant devices are unchanged.
### Risk vs benefit
Four lines of range checks, no locking or ABI change. Worst case on a
truncated list is skipping remaining descriptors (already the `nidl ==
0` policy). Benefit is preventing a heap OOB in a widely used storage
driver.
### Concerns
None that block backport: 1/2 is independent of the FDP 2/2 patch; no
extra commits required; apply is clean against this
`nvme_identify_ns_descs()`.
---
### Verification
- **[Phase 1]** Parsed tags: Reviewed-by Christoph Hellwig; SOB Hari
Mishal, Greg Kroah-Hartman, Keith Busch; Assisted-by
gkh_clanker_t1000; no Fixes/Reported-by/Cc:stable/syzbot
- **[Phase 2]** Diff: +4 lines in `nvme_identify_ns_descs()`; two `pos +
sizeof(*cur)` / `+ cur->nidl` checks vs `NVME_IDENTIFY_DATA_SIZE`
(4096). Confirmed `struct nvme_ns_id_desc` is 4 bytes; `nidl` is
`__u8`
- **[Phase 2]** `nvme_process_ns_desc()` memcpy of EUI64/NGUID/UUID/CSI
only after `nidl` matches expected length — body check is what keeps
those copies in-buffer
- **[Phase 2]** Integer overflow: max `pos+hdr+nidl` ≈ 4354, no 32-bit
overflow
- **[Phase 3]** `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4
- **[Phase 3]** Commit `3c568b35a0d309`; `git merge-base --is-ancestor`
→ ancestor of HEAD
- **[Phase 3]** Blame: loop `3b22ba2682b432` (2017, v4.13-rc1); checks
from this commit
- **[Phase 3]** Pre-image `git show 3c568b35a0d30^:...` matches the
supplied diff (no header/body checks)
- **[Phase 3]** Sibling `29261f8bb4166` is `nvme_query_fdp_info()` only
— not a prereq. Related `bc7f75eba5001` is target passthru
- **[Phase 4]** `b4 dig -c 3c568b35a0d309`: lore/msgid
2026070931-stopping-cost-239a@gregkh; v1 only; CC linux-nvme + all
NVMe maintainers
- **[Phase 4]** mbox: Hellwig Reviewed-by; Busch “series applied to
nvme-7.3”; no NAK
- **[Phase 4]** WebFetch lore.kernel.org / patch.msgid.link / lore
stable search: **403** — discussion taken from b4 mbox instead
- **[Phase 5]** Only caller `nvme_scan_ns()` → `nvme_scan_work()`
(probe/reset/NS-changed scan)
- **[Phase 5]** Similar bounds already in
`drivers/nvme/target/passthru.c`
- **[Phase 6]** Buggy walker exists in this tree’s history since v4.13;
current file has the checks; apply would be clean
- **[Phase 6]** MAINTAINERS: NVM EXPRESS DRIVER — Busch, Axboe, Hellwig,
Grimberg
- **[Phase 8]** Failure mode: heap OOB read on malformed Identify NS
descriptor list; severity HIGH
- **UNVERIFIED:** whether stable@ already discussed this commit (lore
stable HTTP 403)
**YES**
drivers/nvme/host/core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index d5fb6612fa229..5ed62e070f715 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1564,8 +1564,12 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl,
for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) {
struct nvme_ns_id_desc *cur = data + pos;
+ if (pos + sizeof(*cur) > NVME_IDENTIFY_DATA_SIZE)
+ break;
if (cur->nidl == 0)
break;
+ if (pos + sizeof(*cur) + cur->nidl > NVME_IDENTIFY_DATA_SIZE)
+ break;
len = nvme_process_ns_desc(ctrl, &info->ids, cur, &csi_seen);
if (len < 0)
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] udf: validate extent partition references in udf_current_aext()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (82 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] nvme: bound ns descriptor header and body to identify buffer Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: handle empty QUERY_ALLOCATED_RANGES output Sasha Levin
` (432 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable; +Cc: Kyle Zeng, Jan Kara, Sasha Levin, jack, linux-kernel
From: Kyle Zeng <kylebot@openai.com>
[ Upstream commit 120ec50984b8645232c2c004310dd94ceff5520e ]
Long allocation descriptors carry an on-disk
extLocation.partitionReferenceNum. udf_current_aext() copies that value
into a kernel_lb_addr and returns it to several consumers.
If the partition reference is outside s_partitions, callers can later
index s_partmaps out of bounds. The truncate/free path can pass such an
extent to udf_free_blocks(), where the invalid partition reference
causes a slab out-of-bounds read.
Validate eloc->partitionReferenceNum in udf_current_aext() before
returning a decoded extent. This rejects invalid file extents and
indirect allocation descriptor extents in the common parser, so callers
do not need to duplicate the partition-map bounds check.
Assisted-by: Codex:gpt-5.5
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Link: https://patch.msgid.link/20260612225846.97678-1-kylebot@openai.com
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is **v7.3-rc4** (`7.3.0-rc4`). This is a real UDF
slab out-of-bounds on crafted long allocation descriptors; the
vulnerable parser and `udf_free_blocks()` indexing both exist here, and
the 7-line check is the right place to reject them.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[udf] [validate] reject out-of-range on-disk extent partition
references in udf_current_aext()`
- Subsystem: `udf` (UDF filesystem)
- Verb: `validate` — safety-check language; this is a bounds-check bug
fix, not a feature
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Assisted-by: Codex:gpt-5.5` — LLM-assisted; not a quality veto by
itself
- `Signed-off-by: Kyle Zeng <kylebot@openai.com>` — author
- `Link:
https://patch.msgid.link/20260612225846.97678-1-kylebot@openai.com`
- `Signed-off-by: Jan Kara <jack@suse.cz>` — UDF maintainer (listed in
MAINTAINERS)
- No `Fixes:` tag (expected for this review queue)
- No `Cc: stable@vger.kernel.org` (expected)
- No `Reported-by:` / `Tested-by:` / `Reviewed-by:` / `Acked-by:`
- Ignore pipeline SOBs; none were present beyond author + maintainer
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Long ADs copy on-disk `extLocation.partitionReferenceNum`
into `kernel_lb_addr`. That value can be `>= s_partitions`.
- **Symptom:** Callers later index `s_partmaps[]` out of bounds. The
truncate/free path passes the extent to `udf_free_blocks()`, which
does a **slab out-of-bounds read**.
- **Root cause:** Common extent decoder does not bounds-check the
partition reference.
- **Fix:** Check `eloc->partitionReferenceNum >= s_partitions` in
`udf_current_aext()` and return `-EFSCORRUPTED`.
- **Version info in message:** none. Git shows the long-AD copy dates to
`28de7948a89676` (contained in v2.6.23-rc1).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. The message names a slab OOB and a concrete consumer
(`udf_free_blocks()`). This is an explicit memory-safety fix.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `fs/udf/inode.c` — **+7 / -0**
- Function: `udf_current_aext()` only
- Scope: single-file surgical fix
Committed form (Jan Kara dropped a misplaced `sbi` local from the mailed
v2):
```2316:2321:fs/udf/inode.c
if (eloc->partitionReferenceNum >=
UDF_SB(inode->i_sb)->s_partitions) {
udf_debug("invalid partition reference %u (partitions
%u)\n",
eloc->partitionReferenceNum,
UDF_SB(inode->i_sb)->s_partitions);
return -EFSCORRUPTED;
}
```
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** After decoding a short or long AD, return `1` with `eloc`
filled. Long ADs take `partitionReferenceNum` from disk
(`lelb_to_cpu(lad->extLocation)`). Short ADs copy the inode’s already-
checked location.
- **After:** Same decode, then reject `partitionReferenceNum >=
s_partitions` with `-EFSCORRUPTED`.
- Path: every extent walk through `udf_current_aext()` /
`udf_next_aext()`, including truncate, bmap, directory iteration.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Memory safety / out-of-bounds** (category d).
Verified in this tree: `udf_free_blocks()` still indexes with no
partition check:
```664:669:fs/udf/balloc.c
void udf_free_blocks(struct super_block *sb, struct inode *inode,
struct kernel_lb_addr *bloc, uint32_t offset,
uint32_t count)
{
uint16_t partition = bloc->partitionReferenceNum;
struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
```
`extent_trunc()` in `fs/udf/truncate.c` passes `eloc` from
`udf_current_aext()` into `udf_free_blocks()`. `udf_get_pblock()`
already bounds-checks, so reads are safer; the crash is the
free/truncate path.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: same pattern as `udf_read_inode()`
(`iloc->partitionReferenceNum >= sbi->s_partitions`) and
`udf_get_pblock()`.
- Minimal: one check before the success return.
- Regression risk: **low**. Callers already treat `ret <= 0` as failure
(`ee703a7068f95` / `b405c1e58b739`). Truncate does `while (... > 0)`
then `if (ret < 0) return ret`. `-EFSCORRUPTED` is already used across
`fs/udf/`.
- Short-AD false positives: unlikely; `udf_read_inode()` already
validates `i_location.partitionReferenceNum` (`1d82a56bc5bf8`).
- Mailed v2 put `sbi` in `udf_write_aext()` (wrong function); LKP failed
to compile. Jan applied the check with `UDF_SB()` inline. The commit
under review is that corrected form.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Long-AD copy: `28de7948a89676` (Cyrill Gorcunov, 2007), contained in
**v2.6.23-rc1**
- Function skeleton: `^1da177e4c3f41` (2.6.12-rc2)
- Error-return API: `ee703a7068f95` (2024), contained in **v6.12-rc2**
- The new check: `120ec50984b86` (this commit), contained in
**v7.3-rc1**
The buggy decode has been in UDF for a long time.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Introducer is the long-standing long-AD decode,
not a recent regression.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `1d82a56bc5bf8` — partition check in `udf_read_inode()` (v4.11-rc1);
inode location only, not file extents
- `ee703a7068f95` / `b405c1e58b739` — `udf_current_aext`/`udf_next_aext`
return `-errno`; **present in this tree** (prerequisite for a clean
`-EFSCORRUPTED` return)
- `5f0419457f89d` — related truncate OOB in `udf_free_blocks()` (wrong
end-block vs partition length); **present**; still does not check
partition index
- Standalone patch (v2 of a single patch), not `X/Y`
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Only this UDF commit from Kyle Zeng in this tree. Weight comes
from **Jan Kara** applying it, not from the author being the maintainer.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs `udf_current_aext()` to return `-errno` (`ee703a7068f95`).
That **is** in this tree. No missing helpers or struct fields. Can apply
standalone here.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 120ec50984b86` →
https://patch.msgid.link/20260612225846.97678-1-kylebot@openai.com
- `b4 dig -a`: **v2** is the matching series (`[PATCH v2] udf: validate
extent partition references...`)
- v1 (LKML): `[PATCH] udf: validate partition reference before freeing
blocks` — check inside `udf_free_blocks()` instead
- Thread (`/tmp/udf-thread.mbox`): LKP compile errors from `sbi`
declared in `udf_write_aext` and used in `udf_current_aext`
- Jan Kara (18 Jun 2026): “Thanks! I've added the patch to my tree (just
deleting the spurious sbi variable addition).”
- No NAK. No reviewer `Cc: stable`. Maintainer accepted.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): Kyle Zeng, `linux-kernel@vger.kernel.org`, Jan
Kara, `outbounddisclosures@openai.com`. Jan is the UDF maintainer.
`linux-fsdevel` was not on the original To/Cc; Jan still took the patch.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla `Reported-by`. The message describes a slab
OOB on truncate/free of a crafted long AD. A sibling UDF truncate OOB
(`5f0419457f89d`) documents `ftruncate(2)` after a user-mount of
removable UDF (UDisks/polkit) as a local availability issue. Same
trigger class; that report is for a different bounds bug, not this exact
partition-index hole.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: v1 was a `udf_free_blocks()` defense; v2 moved the check to the
common parser so all consumers are covered. Only v2 was merged.
`udf_free_blocks()` in this tree still has no partition-index check, so
this parser check is the defense for that OOB.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: Web search of lore.kernel.org/stable for this subject did not
find a dedicated stable discussion. Absence of stable-list traffic is
not a negative signal here.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `udf_current_aext()`
**Step 5.2: TRACE CALLERS**
Record (verified with grep):
- `udf_next_aext()` — `ret = udf_current_aext(...); if (ret <= 0) return
ret;`
- `udf_truncate_extents()` / tail of truncate loop — `while ((ret =
udf_current_aext(...)) > 0)`, then `if (ret < 0) return ret`
- `__udf_add_aext` setup in `inode.c:2053` — `if (err <= 0) goto
err_out`
`udf_next_aext()` is used from `inode_bmap()`, `extent_trunc` callers,
`directory.c`, `balloc.c`, `super.c`. Impact surface is **all UDF extent
walks**.
**Step 5.3: TRACE CALLEES**
Record: `udf_get_fileshortad` / `udf_get_filelongad`, `lelb_to_cpu`,
`UDF_SB()`. No new locks or allocations.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace-reachable after a UDF mount: `ftruncate` / file delete
/ write that frees extents. `inode_bmap()` is also on read, but
`udf_get_pblock()` already rejects a bad partition. The OOB is
truncate/free. Mount often needs `CAP_SYS_ADMIN`; desktop udisks can
still allow unprivileged mounts of removable UDF (documented on the
sibling truncate OOB).
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same check already in `udf_read_inode()` and `udf_get_pblock()`.
`udf_free_blocks()`, `udf_prealloc_blocks()`, and `udf_new_block()`
still index `s_partmaps[partition]` without that check. Fixing the
decoder covers those consumers.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.**
- `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`
- `make kernelversion` → `7.3.0-rc4`
- Long-AD decode and `udf_free_blocks()` OOB index are in this checkout
- Bug introduced ~v2.6.23, long before this branch
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** on this tree. `udf_current_aext()` already
returns `int` / `-errno`. Context around the switch matches the hunk.
`git merge-base --is-ancestor ee703a7068f95 HEAD` is true.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: `5f0419457f89d` is here (partition *length* on free, not
partition *index*). `1d82a56bc5bf8` only covers inode location. Nothing
else closes this hole except this check.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `fs/udf/` — **IMPORTANT** (real filesystem, not core VFS; not
staging). Data-path OOB on mountable media.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained by Jan Kara; recent 7.3 UDF work includes
integrity, leaks, deadlock, and other OOB/corruption checks. Mature code
with ongoing fuzz/LLM-found hardening.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Filesystem-specific / config-specific** (`CONFIG_UDF_FS`).
Anyone who mounts UDF (optical, ISO, some USB). Not universal.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Crafted/corrupted image with long ADs and `partitionReferenceNum
>= s_partitions`, then truncate/free. Not every boot. Reachable from
`ftruncate` after mount. Unprivileged trigger if the image can be
mounted without `CAP_SYS_ADMIN` (udisks/removable media).
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Slab out-of-bounds read in `udf_free_blocks()` →
KASAN/oops/panic. **HIGH** (crash / local availability; not shown to be
a write primitive). Sibling UDF truncate OOB was described as a local
availability panic.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** High for UDF users — stops a kernel OOB on corrupted
media
- **Risk:** Very low — 7 lines, existing error API, maintainer-applied
- **Ratio:** Strongly favors applying the fix on this tree
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real slab OOB in `udf_free_blocks()` when a long AD carries a bad
partition index
- That index path is still unchecked in this tree
- Truncate/free is a normal file operation after mount
- 7-line decoder check; same pattern as existing UDF partition checks
- Maintainer applied it (after fixing the mailed unused/`sbi` mistake)
- Callers already propagate `-errno`
- Prerequisite error-return refactor is in this tree
- Bug is old (long ADs since ~2.6.23)
AGAINST:
- No `Reported-by` / syzbot for this exact hole
- LLM-assisted; mailed v2 did not compile until Jan edited it
- UDF is not a default desktop root filesystem
- No `Cc: stable` (not a negative under these rules)
UNRESOLVED:
- Could not fetch lore.kernel.org HTML (HTTP 403); thread recovered via
`b4 dig -m`
- No dedicated stable-list thread found
- No in-tree reproducer; mechanism is verified from code, not from a
crash log in the commit
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — bounds check matches
existing UDF checks; maintainer applied the compile-fixed version
2. Fixes a real bug that affects users? **PASS** — OOB on
crafted/corrupted UDF truncate/free
3. Important issue? **PASS** — slab OOB / crash, HIGH
4. Small and contained? **PASS** — +7 lines, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — `udf_current_aext()` and
`-errno` callers exist here
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not an ID/quirk/DT/docs exception. It is a normal memory-safety
filesystem fix.
**Step 9.4: MAKE YOUR DECISION**
This tree’s UDF decoder still hands untrusted long-AD partition
references to `udf_free_blocks()`, which indexes `s_partmaps[]` with no
partition bound. The check is small, already matches local error
handling, and was accepted by the UDF maintainer. It should be in this
tree.
------------------------------------------------
What the commit solves and why it matters here
------------------------------------------------
Long allocation descriptors store `partitionReferenceNum` on disk.
`udf_current_aext()` used to copy that into `eloc` and return success.
Truncate then calls `extent_trunc()` → `udf_free_blocks()`, which does
`s_partmaps[partition]` with no `s_partitions` check. A crafted UDF
image can produce a slab OOB read and a kernel oops. Validating the
reference in the common parser rejects that extent once for every
consumer.
------------------------------------------------
Stable rules / risk vs benefit
------------------------------------------------
The change is obviously correct, tiny, and does not add APIs. Benefit is
preventing a UDF crash on corrupted media; risk is a rejected extent
returning `-EFSCORRUPTED` on a path that already handles `-errno`. No
missing prerequisites in this checkout.
------------------------------------------------
Concerns
------------------------------------------------
The mailed v2 was broken (`sbi` in the wrong function); the committed
diff is the maintainer-corrected version, which is what this evaluation
uses. Older kernels without `ee703a7068f95` would need extra caller
work; **this tree already has that refactor**, so it is not a blocker
here.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed tags: Assisted-by Codex, SOB Kyle Zeng, Link
patch.msgid.link, SOB Jan Kara; no Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: +7 in `udf_current_aext()`; `udf_free_blocks()` still
does `s_partmaps[partition]` with no index check
(`fs/udf/balloc.c:668-669`); `extent_trunc()` calls
`udf_free_blocks()` (`fs/udf/truncate.c:37-54`, `271`)
- [Phase 3] `git blame`: long-AD copy `28de7948a89676` (v2.6.23-rc1);
check is `120ec50984b86`; error API `ee703a7068f95` (v6.12-rc2)
- [Phase 3] No Fixes: tag; `git merge-base --is-ancestor ee703a7068f95
HEAD` true; `1d82a56bc5bf8` and `5f0419457f89d` are ancestors and do
not close this hole
- [Phase 4] `b4 dig -c 120ec50984b86`: lore URL found; `-a`: v2 only;
`-w`: Jan Kara CC’d; `-m`: LKP unused/`sbi` errors; Jan: applied after
deleting spurious `sbi`
- [Phase 4] lore.kernel.org WebFetch returned 403; bodies taken from
mbox + openwall/LKML mirrors
- [Phase 4] Stable lore search: no dedicated discussion found
- [Phase 5] Callers: `udf_next_aext`, truncate loop, `inode.c:2053`;
`inode_bmap` propagates `err <= 0`
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4; buggy decode and OOB index present
- [Phase 7] MAINTAINERS: UDF → Jan Kara; `fs/udf/` actively patched in
7.3
- [Phase 8] Failure mode: slab OOB read on truncate/free of crafted long
AD — HIGH
- UNVERIFIED: live KASAN reproducer for this exact image; unprivileged-
mount path for *this* hole (documented only for the sibling truncate
OOB)
**YES**
fs/udf/inode.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 271e3f0d1fb10..05d4e95ba3c61 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -2312,6 +2312,13 @@ int udf_current_aext(struct inode *inode, struct extent_position *epos,
return -EINVAL;
}
+ if (eloc->partitionReferenceNum >= UDF_SB(inode->i_sb)->s_partitions) {
+ udf_debug("invalid partition reference %u (partitions %u)\n",
+ eloc->partitionReferenceNum,
+ UDF_SB(inode->i_sb)->s_partitions);
+ return -EFSCORRUPTED;
+ }
+
return 1;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] ksmbd: handle empty QUERY_ALLOCATED_RANGES output
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (83 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] udf: validate extent partition references in udf_current_aext() Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] btrfs: fix memory barrier order in reloc_root_is_dead() Sasha Levin
` (431 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable; +Cc: Namjae Jeon, Sasha Levin, linux-cifs, linux-kernel
From: Namjae Jeon <linkinjeon@kernel.org>
[ Upstream commit 7f07791522a251e2be087d11ae9cd51eb3408f1d ]
FSCTL_QUERY_ALLOCATED_RANGES can be issued with a valid input buffer but
without room for an output range. Do not reject the request before
looking at the file layout. If the query would produce a range, return
STATUS_BUFFER_TOO_SMALL. If it produces no ranges, return success with an
empty output.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111** (`pending-6.12`). The buggy `in_count ==
0` path is present here; the upstream fix is not. This is a small, spec-
driven ksmbd protocol fix that applies cleanly.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[ksmbd] [handle] empty QUERY_ALLOCATED_RANGES output** —
“handle” here means correct SMB2 status/output when the client supplies
a valid input buffer but no room for an output range.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record: Tags on upstream `7f07791522a251e2be087d11ae9cd51eb3408f1d`:
- Signed-off-by: Namjae Jeon `<linkinjeon@kernel.org>` (ksmbd
maintainer; also committer)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
or Cc: stable
- The candidate copy’s `[Upstream commit …]` and `Signed-off-by: Sasha
Levin` were ignored as pipeline markers
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `FSCTL_QUERY_ALLOCATED_RANGES` is rejected when the output
buffer cannot hold one `FILE_ALLOCATED_RANGE_BUFFER` (16 bytes),
before the file layout is inspected.
- **Symptom:** Client gets a hard `STATUS_INVALID_PARAMETER` instead of
`STATUS_BUFFER_TOO_SMALL` (ranges exist) or success with empty output
(no ranges).
- **Root cause:** Early `if (in_count == 0) return -EINVAL` in
`fsctl_query_allocated_ranges()`.
- **No version range** in the message. Function dates to 2021
(`e2f34481b24db2`).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. It is an explicit protocol-correctness
fix: wrong NTSTATUS for a documented FSCTL.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `fs/smb/server/smb2pdu.c` — **+12 / −4** (16 lines)
- Function: `fsctl_query_allocated_ranges()` only
- Scope: **single-file surgical fix**
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `in_count == 0` (i.e. `out_buf_len < sizeof(struct
file_allocated_range_buffer)`) returns `-EINVAL` immediately, mapped
in `smb2_ioctl()` to `STATUS_INVALID_PARAMETER`. File is never looked
at.
- **After:** Validate offset/length and look up the file. If `in_count
== 0`, probe with a **stack** dummy range and `in_count=1`. If that
probe fills a range, return `-ENOSPC` (`STATUS_BUFFER_TOO_SMALL` at
line 8701–8702). If it fills nothing, return 0 with `*out_count = 0`.
Non-zero `in_count` is unchanged.
- Path: normal FSCTL handling, not an init/error-only cleanup.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Logic / protocol correctness**, matching [MS-FSA]
FSCTL_QUERY_ALLOCATED_RANGES:
- `OutputBufferSize < sizeof(FILE_ALLOCATED_RANGE_BUFFER)` **MUST** fail
with `STATUS_BUFFER_TOO_SMALL`
- No allocated ranges → `STATUS_SUCCESS`, `BytesReturned = 0`
- Input `Length == 0` → success with empty output
Using a stack dummy is required: calling `ksmbd_vfs_fqar_lseek()` with
`qar_rsp` and `in_count=1` when the real output buffer is shorter than
16 bytes would write past the ioctl response buffer.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct against MS-FSA and the existing `-ENOSPC` →
`STATUS_BUFFER_TOO_SMALL` mapping. Minimal. Regression risk is low: fd
get/put stay balanced; dummy is on-stack; `*out_count` is forced to 0 on
the empty-output path. Slight error-code change for “bad fid **and**
tiny output buffer” (`-EINVAL` → `-ENOENT`) is more correct.
Verified `git apply --check` on this tree: **hunks apply cleanly**
(offset −891 lines only).
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: The `if (in_count == 0) return -EINVAL` lines were introduced in
**`e2f34481b24db2`** (“cifsd: add server-side procedures for SMB3”,
2021-05-10). Present for the entire ksmbd lifetime in this tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Introducing commit **is** an ancestor of HEAD
(`git merge-base --is-ancestor e2f34481b24db2 HEAD` succeeded).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Related later mainline work (not in this tree):
- `350684e049851` — dense-file SEEK_DATA handling (`vfs.c`)
- `25e414db70333` — holes / `-E2BIG` overflow (`vfs.c` + `smb2pdu.c`,
larger)
- `3c707d4b3f926` — READ_DATA permission on this FSCTL
Those are **independent** bugs. This patch only changes the zero-output-
buffer gate and does not need them.
Recent 6.12 ksmbd work on the same file includes other buffer-size
protocol fixes already in this tree (`fix partial file information
responses`, `return buffer overflow for partial filesystem info`, `fix
partial normalized name responses`). Same class of bug.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Namjae Jeon is listed in MAINTAINERS as **KERNEL SMB3 SERVER
(KSMBD)** maintainer. This landed in his 7.3-rc1 ksmbd pull (protocol-
compat / smbtorture).
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. Calls existing `ksmbd_vfs_fqar_lseek()`. In this
tree that helper still has `if (!in_count) return 0`, which is why the
probe must pass `in_count=1`. No new helpers or struct fields. **Applies
standalone.**
`git merge-base --is-ancestor 7f07791522a251e2be087d11ae9cd51eb3408f1d
HEAD` → not in this tree.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 7f07791522a251e2be087d11ae9cd51eb3408f1d` failed:
lore.kernel.org returned an error
- WebFetch of lore search URLs returned **403**
- **UNVERIFIED:** v1/v2 revisions, NAKs, reviewer-requested Cc: stable
- Verified via LKML: commit is in **[GIT PULL] ksmbd server update for
7.3-rc1** (Namjae Jeon, 2026-08-23), grouped with protocol-
compatibility fixes “validated with smbtorture” and “allocated-range
queries”
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: **UNVERIFIED** (b4 -w failed with lore). Commit is authored
**and** committed by the ksmbd maintainer.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla tag. Behavior is specified in [MS-FSA]
2.1.5.10.22: too-small output **MUST** be `STATUS_BUFFER_TOO_SMALL`;
empty result is success. Samba/Windows discussions distinguish that
status from `STATUS_BUFFER_OVERFLOW` (partial fill) and from
`STATUS_INVALID_PARAMETER` (hard fail).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Sequential maintainer commits around 2026-07-09; next ones
change `vfs.c` for dense files/holes. Not a numbered `N/M` series. This
hunk is self-contained.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** (lore 403). Absence of Cc: stable is expected for
this pipeline.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `fsctl_query_allocated_ranges()`; helper
`ksmbd_vfs_fqar_lseek()`; dispatcher `smb2_ioctl()`.
**Step 5.2: TRACE CALLERS**
Record:
- Sole caller: `smb2_ioctl()` `case FSCTL_QUERY_ALLOCATED_RANGES`
(`fs/smb/server/smb2pdu.c`)
- `smb2_ioctl` is `SMB2_IOCTL_HE` in `fs/smb/server/smb2ops.c`
- Reachable from authenticated SMB2 clients over the network (not
interrupt context)
**Step 5.3: TRACE CALLEES**
Record: `ksmbd_lookup_fd_fast` / `ksmbd_fd_put`; `ksmbd_vfs_fqar_lseek`
→ `vfs_llseek(SEEK_DATA/SEEK_HOLE)`. Probe uses a stack buffer, not the
response buffer.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace/network client → SMB2 IOCTL →
FSCTL_QUERY_ALLOCATED_RANGES. **Yes, user-triggerable.** `in_count == 0`
when `smb2_calc_max_out_buf_len()` yields `out_buf_len < 16`
(`MaxOutputResponse` 0..15). Linux CIFS often asks for ≥16 bytes
(`smb2ops.c`); Windows/smbtorture can send a smaller max output. That is
a real client pattern for this FSCTL.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same file already special-cases `-E2BIG` →
`STATUS_BUFFER_OVERFLOW` and `-ENOSPC` → `STATUS_BUFFER_TOO_SMALL`. This
patch is the missing `in_count==0` case of that protocol. Other ksmbd
“too-small output buffer” fixes are already in this 6.12 tree.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `fs/smb/server/smb2pdu.c` lines 8196–8198:
```8196:8211:fs/smb/server/smb2pdu.c
*out_count = 0;
if (in_count == 0)
return -EINVAL;
...
ret = ksmbd_vfs_fqar_lseek(fp, start, length,
qar_rsp, in_count, out_count);
```
Local version: **6.12.111**. Bug introduced **v5.15-era ksmbd (2021)**.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** (`git apply --check` succeeded). Surrounding
function matches the upstream pre-image besides line numbers.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No other commit in this tree greps to this subject/behavior.
Dense-file / holes / extra permission commits are **not** ancestors of
HEAD. Not required for this gate-fix.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM**
Record: **ksmbd** (`fs/smb/server/`). **IMPORTANT** (in-kernel SMB3
server: NAS, OpenWrt, appliances). Not core mm/VFS for all boots;
network-facing for every ksmbd user. `CONFIG_SMB_SERVER` default n.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained; many ksmbd protocol fixes already on this
branch.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: **Driver/config-specific:** ksmbd (`CONFIG_SMB_SERVER`) serving
`FSCTL_QUERY_ALLOCATED_RANGES` (sparse-file tools, backup, smbtorture,
some Windows APIs).
**Step 8.2: TRIGGER CONDITIONS**
Record: Valid QUERY_ALLOCATED_RANGES input **and** `MaxOutputResponse <
16`. Not every IOCTL; not unprivileged local syscalls except via an SMB
session. Timing-independent.
**Step 8.3: FAILURE MODE SEVERITY**
Record: Wrong NTSTATUS → client treats a sizing/empty query as a **hard
parameter error** instead of retry (`BUFFER_TOO_SMALL`) or empty
success. Can fail sparse-file / backup / torture paths. **MEDIUM**
(functional interoperability, not oops/UAF/corruption).
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit:** Medium — restores documented SMB status for a long-
standing ksmbd FSCTL; clients can retry or accept empty results.
- **Risk:** Very low — 16 lines, existing error mapping, stack dummy,
clean apply, no API/locking change.
- **Ratio:** Favorable.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real MS-FSA MUST violation: tiny output buffer returns
`STATUS_INVALID_PARAMETER` instead of `STATUS_BUFFER_TOO_SMALL` /
empty success
- User-visible: SMB clients abort instead of retrying or treating the
file as having no ranges
- Present in this 6.12 tree since ksmbd was added
- 16-line surgical change; applies cleanly; no prerequisites
- Maintainer-authored; in 7.3 ksmbd pull as smbtorture protocol-compat
- Dummy buffer avoids a would-be response-buffer overflow
- Same class as buffer-size ksmbd fixes already on this branch
**AGAINST:**
- Not a crash, UAF, security hole, deadlock, or data corruption
- No syzbot/CVE/Reported-by
- Trigger is a small `MaxOutputResponse`, not the Linux CIFS client’s
usual 16+-byte buffer
- Sibling dense-file/holes fixes remain separate (they do not block this
one)
**UNRESOLVED:** lore/b4 review thread (403/server error); no explicit
stable mailing-list discussion.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — matches MS-FSA; maintainer
commit; smbtorture-oriented 7.3 pull. Direct lore Tested-by
unverified.
2. Fixes a real bug that affects users? **PASS** — wrong NTSTATUS on a
reachable FSCTL.
3. Important issue? **PASS** (MEDIUM-HIGH for a network file server) —
hard client failure vs retryable/empty result; not a panic.
4. Small and contained? **PASS** — one function, +12/−4.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — buggy code present; `git
apply --check` clean.
**Step 9.3: EXCEPTION CATEGORIES**
Record: None (not a device ID / quirk / DT / build / docs patch).
Qualifies as a normal contained bugfix.
**Step 9.4: DECISION**
Backport to **this** 6.12 tree. The bug exists here, the fix is
standalone and low-risk, and returning the wrong SMB status on
QUERY_ALLOCATED_RANGES is a real interoperability failure for ksmbd
users.
---
### What the commit solves for stable users
On 6.12 ksmbd, a legal `FSCTL_QUERY_ALLOCATED_RANGES` with
`MaxOutputResponse` smaller than one range is failed as
`STATUS_INVALID_PARAMETER` before the file is examined.
Windows/smbtorture expect `STATUS_BUFFER_TOO_SMALL` if ranges exist, or
success with zero output if they do not. That mismatch can abort sparse-
file queries instead of allowing a retry.
### Stable rules / risk
The change is obviously correct, small, and already wired to this tree’s
`-ENOSPC` mapping. It does not need the later dense-file or holes vfs
work. Risk is a slightly different (more accurate) status on a rare
combined bad-fid + tiny-buffer case.
### Verification
- **[Phase 1]** Parsed upstream
`7f07791522a251e2be087d11ae9cd51eb3408f1d`: maintainer SOB only; no
Fixes/Reported-by/Cc stable
- **[Phase 2]** Diff: +12/−4 in `fsctl_query_allocated_ranges()`; dummy
stack probe; `-ENOSPC` when probe fills a range
- **[Phase 2]** Confirmed `smb2_ioctl()` maps `-ENOSPC` →
`STATUS_BUFFER_TOO_SMALL` (lines 8701–8702)
- **[Phase 3]** `git blame`: `in_count == 0` from `e2f34481b24db2`
(2021); ancestor of HEAD
- **[Phase 3]** `git merge-base --is-ancestor 7f077915… HEAD` → not in
this tree
- **[Phase 3]** `git apply --check` of the upstream diff → clean (offset
−891)
- **[Phase 3]** Sibling dense/holes/perms commits exist as objects,
**not** ancestors of HEAD; vfs probe still works with 6.12
`ksmbd_vfs_fqar_lseek`
- **[Phase 4]** `b4 dig` lore error; lore WebFetch 403; LKML 7.3-rc1
ksmbd pull lists this subject
- **[Phase 4]** MS-FSA: too-small output MUST be
`STATUS_BUFFER_TOO_SMALL`
- **[Phase 5]** Only caller is `smb2_ioctl`
FSCTL_QUERY_ALLOCATED_RANGES; dispatched as `SMB2_IOCTL_HE`
- **[Phase 6]** `git describe HEAD` → `p-6.12-3-gc504cf0baa3d8`; `make
kernelversion` → 6.12.111; buggy early `-EINVAL` still present
- **[Phase 7]** MAINTAINERS: Namjae Jeon is ksmbd maintainer
- **[Phase 8]** Failure mode: wrong NTSTATUS / client abort, not oops
- **UNVERIFIED:** lore reviewer comments, Tested-by, explicit stable
nomination
**YES**
fs/smb/server/smb2pdu.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 0fbbb47f94644..c18590d8ee2b9 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -8302,8 +8302,6 @@ static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
int ret = 0;
*out_count = 0;
- if (in_count == 0)
- return -EINVAL;
start = le64_to_cpu(qar_req->file_offset);
length = le64_to_cpu(qar_req->length);
@@ -8315,8 +8313,18 @@ static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
if (!fp)
return -ENOENT;
- ret = ksmbd_vfs_fqar_lseek(fp, start, length,
- qar_rsp, in_count, out_count);
+ if (!in_count) {
+ struct file_allocated_range_buffer range;
+
+ ret = ksmbd_vfs_fqar_lseek(fp, start, length, &range, 1,
+ out_count);
+ if (!ret && *out_count)
+ ret = -ENOSPC;
+ *out_count = 0;
+ } else {
+ ret = ksmbd_vfs_fqar_lseek(fp, start, length,
+ qar_rsp, in_count, out_count);
+ }
if (ret && ret != -E2BIG)
*out_count = 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] btrfs: fix memory barrier order in reloc_root_is_dead()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (84 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: handle empty QUERY_ALLOCATED_RANGES output Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] md: add cond_resched() to md_do_sync()'s skip path Sasha Levin
` (430 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Filipe Manana, Boris Burkov, David Sterba, Sasha Levin,
linux-btrfs, linux-kernel
From: Filipe Manana <fdmanana@suse.com>
[ Upstream commit 6f1c97695a6e230ee15c9e052e1933bdccfd5fa3 ]
When we set a root's reloc_root to NULL, we do it like this:
static void clear_reloc_root(struct btrfs_root *root)
{
root->reloc_root = NULL;
/*
* Need barrier to ensure clear_bit() only happens after
* root->reloc_root = NULL. Pairs with have_reloc_root().
*/
smp_wmb();
clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
}
So that a NULL reloc_root is always seen before seeing that the bit
BTRFS_ROOT_DEAD_RELOC_TREE was cleared.
But on the read side we have:
static bool reloc_root_is_dead(const struct btrfs_root *root)
{
smp_rmb();
if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
return true;
return false;
}
And then callers of reloc_root_is_dead() access root->reloc_root.
Because the read memory barrier is placed before testing the bit, the CPU
is completely free to speculatively reorder those two loads. It can read
root->reloc_root before it actually checks the dead tree bit.
Sashiko reported this as an existing problem in another patch review, see
the link in the Link tag below.
Fix this by moving the read memory barrier to happen after testing the bit
and update the comment to reflect current reality.
Link: https://sashiko.dev/#/patchset/cf84f1a217c719e25b6b69e4298dd7afd36c9427.1781194426.git.fdmanana%40suse.com
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This tree is **Linux 6.18.53** (`pending-6.18`). The candidate is
mainline `6f1c97695a6e2` (`v7.3-rc1`) and is **not** in this checkout.
The misplaced `smp_rmb()` in `reloc_root_is_dead()` is still present,
and the write-side half of the same series is already here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[btrfs]` `[fix]` — correct read-side memory-barrier order in
`reloc_root_is_dead()` so the `BTRFS_ROOT_DEAD_RELOC_TREE` bit is
observed before callers load `root->reloc_root`.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Link:** https://sashiko.dev/#/patchset/cf84f1a217c719e25b6b69e4298dd
7afd36c9427.1781194426.git.fdmanana%40suse.com (Sashiko review of a
related UAF patch, where this read-side bug was flagged)
- **Reviewed-by:** Boris Burkov `<boris@bur.io>`
- **Signed-off-by:** Filipe Manana `<fdmanana@suse.com>` (author), David
Sterba `<dsterba@suse.com>` (btrfs maintainer)
- No **Fixes:**, **Reported-by:**, **Tested-by:**, **Cc: stable**,
**Acked-by:**
- Ignore pipeline SOBs. Absence of Fixes/Cc-stable is expected.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Writer does `root->reloc_root = NULL; smp_wmb();
clear_bit(DEAD)`. Reader did `smp_rmb(); test_bit(DEAD)` and then
callers loaded `root->reloc_root`.
- **Mechanism:** An `smp_rmb()` *before* the bit load does not order
that load against the later `reloc_root` load. CPU/compiler may load
`reloc_root` first.
- **Symptom:** Stale non-NULL `reloc_root` after the writer has NULLed
it and cleared the dead bit, then `btrfs_drop_snapshot()` — use-after-
free.
- **Root cause:** Classic MP (message-passing) pairing error:
`smp_rmb()` must sit *between* the two loads, not before both.
- **Version info:** Buggy helper dates to `6282675e6708ec` (v5.5-rc7,
2020).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. Explicit barrier/UAF-class correctness fix, found by
Sashiko on a related reloc-root series.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `fs/btrfs/relocation.c` (+6 / −5)
- **Function:** `reloc_root_is_dead()`
- **Scope:** Single-function, surgical
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `smp_rmb(); if (test_bit(DEAD)) return true; return
false;`
- **After:** `if (test_bit(DEAD)) return true; smp_rmb(); return false;`
- **Affected path:** Any caller that, on a false result, then reads
`root->reloc_root` (`have_reloc_root()`, `btrfs_init_reloc_root()`,
`btrfs_should_ignore_reloc_root()`).
- Early return when the bit is set skips the rmb; those callers do not
load `reloc_root`. That is correct.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** Synchronization / race (memory-barrier pairing); failure
mode is UAF
- **Mechanism:** Writer: store `reloc_root=NULL`, `smp_wmb()`,
`clear_bit(DEAD)`. Required reader: load DEAD, `smp_rmb()`, load
`reloc_root`. Current reader puts `smp_rmb()` *before* the bit load,
so it does not pair. Compiler can hoist `root->reloc_root` above
`test_bit()` after inlining (x86 included); weak memory models can
also reorder the loads in hardware.
Verified against LKMM recipes (`tools/memory-
model/Documentation/recipes.txt`, MP + `smp_wmb`/`smp_rmb`): the read
barrier is between the two loads.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Minimal and matches documented pairing. No API/data-structure
change. Regression risk is low: if the bit is set we return without rmb
(callers do not touch `reloc_root`); if clear, rmb orders the subsequent
load. David Sterba initially doubted the move; Filipe explained the
pairing; David still merged with SOB.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Buggy `smp_rmb()` + `test_bit()`: `6282675e6708ec` (“btrfs:
relocation: fix reloc_root lifespan and access”), Qu Wenruo,
2020-01-08, first in **v5.5-rc7**. That commit itself was `CC: stable
# 5.4+` to fix KASAN UAFs on balance+snapshot.
- Write-side `clear_reloc_root()`: `fda1b6636ff184` in this tree
(Upstream `83201804efa4a`).
- Original commit text even said “the pairing read side is before
test_bit” — that comment is what this patch corrects.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Introducer is `6282675e6708ec`, present in this
tree (`git merge-base --is-ancestor` exit 0). Independently identified
in 2021 by Baptiste Lepers (`[PATCH] btrfs: relocation: fix misplaced
barrier in reloc_root_is_dead`, 2021-05-26) with `Fixes: 6282675e6708e`;
that patch was never merged.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same-day 2-patch series `[PATCH 0/2] btrfs: fix incorrect
barrier usage in relocation`:
- **1/2** `b78fe9563e2d5` / this tree `63d6b1f04cd91` — write-side
`clear_reloc_root()` in `merge_reloc_roots()`. **Already in this
tree.**
- **2/2** this commit — read-side rmb. **Not in this tree.**
Prerequisite UAF helper `clear_reloc_root` (`fda1b6636ff184`) is also
already here. No later mainline rewrite of `reloc_root_is_dead()` after
`6f1c97695a6e2`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Filipe Manana is a core btrfs author (many reloc-root UAF/leak
fixes). David Sterba (listed btrfs maintainer) signed off. Boris Burkov
reviewed the series.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: This hunk only reorders `smp_rmb()` vs `test_bit()` in
`reloc_root_is_dead()`. It does not call `clear_reloc_root()`.
Standalone. `git show 6f1c97695a6e2 | git apply --check` succeeded (hunk
offset −94 lines only).
The kbuild error on the series was `clear_reloc_root` undeclared when
**1/2** was applied without the UAF series; that does not apply to
**this** patch, and this 6.18.53 tree already has both the helper and
1/2.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **Lore/thread:** cover `cover.1781263239.git.fdmanana@suse.com`; 2/2
msgid `62602395bf1488aa81645ea59e22405d6c06d3f7.1781263239.git.fdmanan
a@suse.com`
- **Series:** v1 only (2026-06-12), two patches
- **b4 dig -c 6f1c97695a6e2** initially matched the related UAF v5
thread (same Link/Sashiko URL / similar patch-id). Direct msgid fetch
recovered the real 0/2 series (9 messages).
- **Reviewer feedback:**
- Boris Burkov: `Reviewed-by` on the cover (both patches)
- David Sterba (2026-06-18): argued rmb-before-`test_bit` was
intentional “to have up-to-date value”; said post-test rmb “is
wrong, or at least not entirely correct”; suggested dropping
barriers
- Filipe: pairing is load-bit / rmb / load-`reloc_root` against store-
NULL / wmb / clear-bit; dropping barriers would regress the 2020
KASAN races
- David still merged (SOB on the commit)
- **kbuild:** false positive (1/2 vs missing helper on for-next vs
Linus)
- **Stable nomination in thread:** none
- **NAKs:** no NAK; maintainer doubt was answered and the patch landed
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: To/Cc `linux-btrfs@vger.kernel.org`. Boris reviewed. David (M:
in MAINTAINERS) engaged and merged.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot for this exact rmb placement. Sashiko flagged it while
reviewing the insert_dirty_subvol UAF series. Original 2020 KASAN
reports (Zygo Blaxell) are why the barriers exist. 2021 Baptiste patch:
same diagnosis; appears unreplied (odd `To:`), never applied.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Companion 1/2 already AUTOSEL’d and present in this 6.18 tree.
This 2/2 is the unfinished read-side half. UAF series that introduced
`clear_reloc_root` is also already here.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: Openwall/AUTOSEL traffic is for 1/2 and the UAF helper, not this
subject. No stable-list rejection of 2/2 was found. lore.kernel.org
search URLs returned 403; discussion was recovered via `b4 mbox`
instead.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `reloc_root_is_dead()` only.
**Step 5.2: TRACE CALLERS**
Record (this tree, `fs/btrfs/`):
- `have_reloc_root()` → `btrfs_update_reloc_root()`,
`btrfs_reloc_pre_snapshot()`, `btrfs_reloc_post_snapshot()`
- `btrfs_init_reloc_root()` (direct) ← `fs/btrfs/transaction.c` when a
shareable root is recorded in a transaction
- `btrfs_should_ignore_reloc_root()` ← `fs/btrfs/backref.c` during reloc
backref walk
Contexts: relocation/balance, snapshot creation during balance,
transaction join for subvolumes. Not interrupt. Reachable from
`BTRFS_IOC_BALANCE` / snapshot ioctls.
**Step 5.3: TRACE CALLEES**
Record: `test_bit()`, `smp_rmb()`. Callers then read `root->reloc_root`
and may dereference `commit_root`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Writer `clean_dirty_subvols()` / `clear_reloc_root()`: save
pointer, NULL `reloc_root`, wmb, clear DEAD, `btrfs_drop_snapshot()`.
Concurrent reader: new transaction / snapshot / backref walk calling
`reloc_root_is_dead()` then loading `reloc_root`. Original 2020 analysis
called this the C–D window after `btrfs_commit_transaction()`.
Userspace-reachable on btrfs balance+snapshot. Unprivileged users
typically cannot ioctl-balance; a hit still crashes/corrals the
filesystem.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same class of misplaced rmb in `btrfs_record_root_in_trans`
(2021 Baptiste, later 2026 “btrfs: fix root-in-trans fast-path
ordering”). Write-side pairing in this file is already correct
(`clear_reloc_root`, `btrfs_update_reloc_root` `set_bit`+wmb).
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `fs/btrfs/relocation.c` lines 246–257:
```246:257:fs/btrfs/relocation.c
static bool reloc_root_is_dead(const struct btrfs_root *root)
{
/*
- Pair with set_bit/clear_bit in clean_dirty_subvols and
- btrfs_update_reloc_root. We need to see the updated bit before
- trying to access reloc_root
*/
smp_rmb();
if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
return true;
return false;
}
```
Introduced v5.5; still wrong here. Write side already uses `smp_wmb()`
in `clear_reloc_root()` (1460–1468). `git merge-base --is-ancestor
6f1c97695a6e2 HEAD` → not an ancestor.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** (`git apply --check` succeeded, offset only). No
helper dependency. Surrounding `have_reloc_root()` / callers match
mainline.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: 1/2 and `clear_reloc_root` UAF fix are here. This read-side
reorder is not. No substitute fix.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **fs/btrfs** — **IMPORTANT** (filesystem integrity; reloc UAF
can oops or corrupt during balance).
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Active. Multiple 2026 reloc-root UAF/leak/barrier fixes already
landed in this 6.18.y tree.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Btrfs users who run balance/relocation, especially concurrent
with snapshots/subvolume updates. Not universal, but a standard admin
path.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Overlap of `clear_reloc_root()`/`clean_dirty_subvols()` with a
reader of `have_reloc_root()` / `btrfs_init_reloc_root()` /
`btrfs_should_ignore_reloc_root()`. Timing-dependent; same shape as the
2020 KASAN balance+snapshot reports. Typically privileged ioctls; impact
is whole-fs.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Stale `reloc_root` used after `btrfs_drop_snapshot()` → **UAF /
oops**, possible further refcount damage. **Severity: HIGH.**
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit: HIGH** — completes barrier pairing; write side already
backported here, so this tree currently has an unpaired wmb.
- **Risk: LOW** — 11 lines, one static helper, no locking/API change.
- **Ratio:** Strongly favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real MP barrier bug; UAF if `reloc_root` is loaded before `test_bit`
during dead-bit clear
- Buggy code verified in this 6.18.53 tree since v5.5
- Write-side companion already in this tree → read side is the missing
half
- LKMM pairing is unambiguous (`smp_rmb` between the two loads)
- Small, applies cleanly, reviewed (Boris), merged by maintainer (David)
- Same race family as the 2020 KASAN reloc-root lifespan fix
- Sashiko + independent 2021 diagnosis
**AGAINST:**
- No dedicated syzbot/user crash for this rmb placement
- David initially disputed the move (later merged)
- Original 2020 text claimed a transaction as a higher-level barrier
(barriers still added for the C–D window; this patch is that window)
- 2021 patch sat unmerged (likely overlooked, not NAK’d)
**UNRESOLVED:** Could not fetch lore.kernel.org HTML (403). Thread
recovered via `b4 mbox`. No evidence this 2/2 was rejected for stable.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — matches LKMM MP pairing;
reviewed; in mainline as of v7.3-rc1
2. Fixes a real bug that affects users? **PASS** — unpaired barrier on a
path built to stop reloc-root UAF
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
HIGH, UAF/oops during balance
4. Small and contained? **PASS** — +6/−5, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — clean apply; prerequisites
already present
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: N/A — ordinary correctness fix.
**Step 9.4: MAKE YOUR DECISION**
This 6.18.53 tree still has `smp_rmb()` before `test_bit()` in
`reloc_root_is_dead()`, so the write-side `smp_wmb()` already present in
`clear_reloc_root()` does not pair. Moving the rmb after the bit test is
the standard, small fix for a UAF-class race on btrfs relocation. It
should be backported here.
===============================================================
Verification
===============================================================
- **[Phase 1]** Parsed subject/tags/body from `git show 6f1c97695a6e2`
on origin/master
- **[Phase 2]** Diff is +6/−5 in `reloc_root_is_dead()` only; compared
to current `fs/btrfs/relocation.c:246-257`
- **[Phase 2]** Confirmed write side `clear_reloc_root()` at 1460–1468:
NULL → `smp_wmb()` → `clear_bit`
- **[Phase 2]** LKMM recipes.txt MP example: load y, `smp_rmb()`, load x
- **[Phase 3]** `git blame -L 246,257`: `6282675e6708ec` (v5.5-rc7);
`git describe --contains 6282675e6708ec` → `v5.5-rc7~22^2~2`
- **[Phase 3]** `git merge-base --is-ancestor 6282675e6708ec HEAD` →
yes; `6f1c97695a6e2` → no
- **[Phase 3]** `git merge-base --is-ancestor 63d6b1f04cd91 HEAD` → 1/2
present; `fda1b6636ff18` → `clear_reloc_root` present
- **[Phase 3]** `git show 6f1c97695a6e2 | git apply --check` → hunk
succeeded at offset −94
- **[Phase 3]** `git describe --contains 6f1c97695a6e2` →
`v7.3-rc1~117^2~66`
- **[Phase 4]** `b4 mbox` of msgid `50682caa6bbf…` → cover + 1/2 + 2/2 +
Boris Reviewed-by + David concern + Filipe reply + kbuild false
positive
- **[Phase 4]** 2021 Baptiste patch verified via openwall/lkml.iu (never
in `git log origin/master --author='Baptiste Lepers' -- fs/btrfs`)
- **[Phase 4]** lore.kernel.org WebFetch 403; used b4 instead
- **[Phase 5]** `git grep` callers: `have_reloc_root`,
`btrfs_init_reloc_root`, `btrfs_should_ignore_reloc_root` →
transaction.c, relocation.c, backref.c
- **[Phase 6]** `git describe HEAD` / `make kernelversion` →
`p-6.18-1-g03b85e06ca9bf`, **6.18.53**
- **[Phase 6]** `git grep -A20 reloc_root_is_dead origin/master` →
mainline already has test_bit then rmb
- **[Phase 7]** MAINTAINERS: David Sterba is btrfs maintainer; he SOB’d
the commit
- **[Phase 8]** Failure mode from original `6282675e6708ec` KASAN stacks
(balance+snapshot) plus C–D window vs `drop_snapshot` after
`clear_bit`
- **UNVERIFIED:** Direct sashiko.dev review text (JS page had no static
content); inferred from Link tag + cover letter + Filipe changelog
The patch is a small, obviously correct pairing fix for a reloc-root UAF
race, the buggy code is in this 6.18.53 tree, and the write-side half is
already here.
**YES**
fs/btrfs/relocation.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index eab9686b1bcdf..fcb0ab937de5c 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -245,14 +245,15 @@ static struct btrfs_backref_node *walk_down_backref(
static bool reloc_root_is_dead(const struct btrfs_root *root)
{
+ if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
+ return true;
/*
- * Pair with set_bit/clear_bit in clean_dirty_subvols and
- * btrfs_update_reloc_root. We need to see the updated bit before
- * trying to access reloc_root
+ * Pairs with set_bit/clear_bit in clear_reloc_root() and
+ * btrfs_update_reloc_root(). We need to see the updated bit before
+ * trying to access root->reloc_root in our callers.
*/
smp_rmb();
- if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
- return true;
+
return false;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] md: add cond_resched() to md_do_sync()'s skip path
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (85 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] btrfs: fix memory barrier order in reloc_root_is_dead() Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] drm/msm/adreno: Add support for A704 GPU Sasha Levin
` (429 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Yunye Zhao, Yu Kuai, Sasha Levin, song, linux-raid, linux-kernel
From: Yunye Zhao <yunye.zhao@linux.alibaba.com>
[ Upstream commit 162eb5ba791f6260fdaabae75fa2df20134f67d8 ]
When sync_request() reports a skipped region (*skipped == 1),
md_do_sync()'s main loop advances the cursor and takes an early
continue:
j += sectors;
...
if (last_check + window > io_sectors || j == max_sectors)
continue;
If the personality returns a small span per call (raid10 recovery
returns only 128 sectors), syncing a large, mostly clean array iterates
this branch an enormous number of times without ever yielding the CPU.
On a non-preemptive kernel the resync thread then trips the soft-lockup
watchdog:
watchdog: BUG: soft lockup - CPU#149 stuck for 313s! [mdX_resync]
md_bitmap_start_sync+0x6f/0xe0
raid10_sync_request+0x2c9/0x1530 [raid10]
md_do_sync+0x810/0x1030
md_thread+0xa7/0x150
Add a cond_resched(). This does not reduce the wasted iterations; the
excessive iteration count is a raid10 problem addressed separately.
Signed-off-by: Yunye Zhao <yunye.zhao@linux.alibaba.com>
Link: https://patch.msgid.link/20260723135535.101995-3-yunye.zhao@linux.alibaba.com
Signed-off-by: Yu Kuai <yukuai@fygo.io>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The checked-out tree is **6.18.53** (`pending-6.18`). The skip path in
`md_do_sync()` is present, has no yield, and matches this patch. That is
a real soft-lockup fix.
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
- Record: `[md] [add] add cond_resched() to md_do_sync()'s skip path`
- Subsystem: MD RAID core. Verb “add” here is a yield on an existing
loop, not a feature.
**Step 1.2 — Tags**
- Record:
- `Signed-off-by: Yunye Zhao <yunye.zhao@linux.alibaba.com>` (author)
- `Link: https://patch.msgid.link/20260723135535.101995-3-
yunye.zhao@linux.alibaba.com`
- `Signed-off-by: Yu Kuai <yukuai@fygo.io>` (md maintainer; applied)
- No `Fixes:` / `Reported-by:` / `Tested-by:` in the committed text
- Original v2 submission **did** include `Cc: stable@vger.kernel.org`;
Yu Kuai dropped it when applying (“Remove the cc stable as there is
no fixtag”). That is process, not a technical NAK.
- Pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit …]`
ignored as instructed.
**Step 1.3 — Body**
- Record:
- **Bug:** when `sync_request()` returns `*skipped == 1` with a small
span (RAID10 recovery: 128 sectors), `md_do_sync()` takes `continue`
and never reaches the existing `cond_resched()`.
- **Symptom:** `watchdog: BUG: soft lockup - CPU#149 stuck for 313s!
[mdX_resync]` with `md_bitmap_start_sync` → `raid10_sync_request` →
`md_do_sync` → `md_thread`.
- **Trigger:** large, mostly-clean RAID10 recovery (author:
2^40-sector device → ~2^33 iterations).
- **Root cause of CPU burn:** RAID10 recovery discards the bitmap’s
large clean span and returns 128; that is patch 3/3. This commit
only yields.
- Author tested on 6.6.102 and mainline.
**Step 1.4 — Hidden bug fix?**
- Record: Not hidden. Explicit soft-lockup fix. Series cover letter
calls it a “safety net, any personality/layout.”
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
- Record: `drivers/md/md.c` only; ~3 insertions / 1 deletion in
`md_do_sync()`. Surgical, single-function.
**Step 2.2 — Flow**
- Record: **Before:** skip/early-continue path never yields. **After:**
`cond_resched()` then `continue`. Normal I/O path still uses the later
`cond_resched()` at the speed-limit check.
**Step 2.3 — Bug mechanism**
- Record: **Hang / soft-lockup** (non-preemptive). Skip path bypasses
the yield that already exists later in the same loop.
Verified in this tree:
```9751:9753:drivers/md/md.c
if (last_check + window > io_sectors || j ==
max_sectors)
continue;
```
```9779:9779:drivers/md/md.c
cond_resched();
```
Skip `continue` never reaches line 9779. `window` is `32 * (PAGE_SIZE /
512)` (256 sectors). If `skipped`, `io_sectors` does not increase, so
`last_check + window > io_sectors` stays true.
RAID10 recovery still does `max_sync = RESYNC_PAGES << (PAGE_SHIFT-9)`
(128 sectors). On a clean bitmap, `biolist == NULL` → `giveup` clamps to
`max_sync` and, because `max_sector` is a parameter (not reset at
`skipped:`), the call returns 128 to `md_do_sync()`.
**Step 2.4 — Fix quality**
- Record: Obviously correct. Same primitive already used in this
function. Process context (`md_thread`). No new API/locks. Regression
risk very low. Might slightly slow tight skip loops; that is the goal.
## Phase 3: Git history
**Step 3.1 — Blame**
- Record: Skip `continue` dates to early MD (`57afd89f98a99` / 2.6 era).
Long-standing. RAID10 128-sector recovery cap is equally old
(`RESYNC_BLOCK_SIZE` 64KiB).
**Step 3.2 — Fixes: tag**
- Record: None. Not a regression from a single later commit; interaction
of skip-continue and RAID10 recovery skip size.
**Step 3.3 — Related commits**
- Record: Patch 2/3 of “md/raid10: fix recovery corruption and soft
lockup on large arrays”.
- 1/3 `md/raid10: fix still_degraded being inverted` — **already in
this tree** (`0efabe6229dc6`). Independent.
- 3/3 `md/raid10: skip clean regions in bulk` — **not** in this tree.
Independent; this yield still needed for far/offset layouts and
other personalities.
- No `cond_resched` on this skip path in `HEAD`.
**Step 3.4 — Author**
- Record: Yunye Zhao (Alibaba). Applied by Yu Kuai (md maintainer).
**Step 3.5 — Dependencies**
- Record: Standalone. Uses existing `cond_resched()`. 6.18
`md_do_sync()` already has `update:`, `MD_RESYNC_ACTIVE`, and 4-arg
`sync_request()` — same context as the patch. Clean apply.
## Phase 4: Mailing list
**Step 4.1 — Discussion**
- Record: https://lore.kernel.org/linux-
raid/20260723135535.101995-3-yunye.zhao@linux.alibaba.com/ (also
openwall mirrors).
- v1: single `cond_resched` patch. Yu Kuai initially thought it was a
dead loop.
- v2: 3 patches; this one retitled; v1 “io_sectors never increases”
claim corrected.
- Yu Kuai on v1 follow-up: “This patch is still valuable, even a 5s
lockup is not acceptable.”
- Applied to md-7.3. No NAK on the yield itself.
**Step 4.2 — Recipients**
- Record: Song Liu, Yu Kuai; Cc Li Nan, Xiao Ni, linux-raid, linux-
kernel.
**Step 4.3 — Bug report**
- Record: Author stack trace; 2^40-sector array; ~8.6e9 iterations;
313s. Cover letter: before patch 3, 37.2s 100% CPU on 8T-per-disk
sparse recovery; `softlockup_panic=1`.
**Step 4.4 — Series**
- Record: 2/3 is the md-core safety net. Does not depend on 1/3 or 3/3.
**Step 4.5 — stable@**
- Record: No useful stable-list thread found (lore.kernel.org/stable
403). Maintainer dropped `Cc: stable` only for missing `Fixes:`.
## Phase 5: Semantics
**Step 5.1 — Functions**
- Record: `md_do_sync()`.
**Step 5.2 — Callers**
- Record: Registered as the MD resync thread
(`md_register_thread(md_do_sync, …)`). Kernel thread, not IRQ.
Userspace triggers via array recovery/resync/check (`mdadm`).
**Step 5.3 — Callees**
- Record: `pers->sync_request()`, bitmap start/end, `cond_resched()`,
speed-limit waits.
**Step 5.4 — Reachability**
- Record: Yes. Disk replace / rebuild / `--syncaction` on RAID10 with
internal bitmap. Production path.
**Step 5.5 — Similar patterns**
- Record: Same file already yields on the I/O path. RAID1/5/10 use
`cond_resched()` in other loops. Skip path was the hole.
## Phase 6: This tree (6.18.53)
**Step 6.1 — Buggy code present?**
- Record: **Yes.** `drivers/md/md.c` ~9752 skip `continue` with no
yield. RAID10 `giveup` still advances by `max_sync` (128). `git
describe HEAD`: `p-6.18-1-g03b85e06ca9bf`. `make kernelversion`:
`6.18.53`.
**Step 6.2 — Backport difficulty**
- Record: **Clean apply.** Local hunk matches the submitted diff
(`MD_RESYNC_ACTIVE`, `update:`).
**Step 6.3 — Already fixed?**
- Record: No. 1/3 is in tree; 2/3 and 3/3 are not. Older `71e8e4f288e74`
(bitmap size vs array size) is a different lockup.
## Phase 7: Subsystem
**Step 7.1**
- Record: `drivers/md` — **IMPORTANT** (enterprise RAID, dm-raid). Not
staging.
**Step 7.2**
- Record: Active; recent RAID10/md fixes on this branch.
## Phase 8: Impact and risk
**Step 8.1 — Who**
- Record: MD/RAID users, especially RAID10 recovery of large mostly-
clean arrays. Distro/enterprise kernels often `PREEMPT_NONE` /
`PREEMPT_VOLUNTARY`.
**Step 8.2 — Trigger**
- Record: Recovery/resync of a large sparse array. Not unprivileged
syscall; rebuild is a privileged/admin path. Common after disk
replace. Timing-independent tight loop.
**Step 8.3 — Failure mode**
- Record: Soft lockup (313s in the report). With `softlockup_panic=1`,
panic. **CRITICAL**.
**Step 8.4 — Risk vs benefit**
- Record: Benefit high (stops watchdog/panic). Risk very low (3 lines,
existing helper). Ratio strongly in favor. Remaining CPU spin is patch
3; this still prevents the BUG.
## Phase 9: Synthesis
**For backporting**
- Real, reproduced soft lockup with stack trace.
- Hole is in this tree; patch matches.
- Tiny, obviously correct; maintainer applied it and called it valuable.
- Independent of 3/3; still needed after 1/3.
- Classic stable pattern: `cond_resched()` to stop a lockup.
**Against**
- Does not cut the 128-sector crawl (author is explicit).
- No `Fixes:` (maintainer dropped `Cc: stable` for that).
- Pre-existing `md_new_event()` spam on `last_check == 0` (not
introduced here).
**Unresolved:** none that change the verdict. Could not fetch
lore.kernel.org/stable (403); discussion from the patch mbox is enough.
**Stable rules**
1. Obviously correct and tested — **PASS** (mainline + QEMU tests;
maintainer applied).
2. Real user-visible bug — **PASS** (soft lockup on RAID10 recovery).
3. Important (crash/hang) — **PASS** (soft lockup / possible panic).
4. Small and contained — **PASS** (~3 lines, one function).
5. No new features/APIs — **PASS**.
6. Applies to this tree — **PASS** (clean).
**Exception category:** none required; it is a hang fix.
This matters on 6.18 because RAID rebuild of large arrays is normal
operations, and a 5–313s lockup (or panic) is exactly what stable is
for. The yield is the same one the I/O path already uses.
## Verification
- [Phase 1] Tags: author SOB, Yu Kuai SOB, msgid link; v2 had `Cc:
stable`, dropped on apply for missing Fixes.
- [Phase 2] Diff: 3 lines in `md_do_sync()` skip `continue`; 6.18 code
at 9752–9753 / 9779 matches.
- [Phase 2] RAID10: `max_sync = RESYNC_PAGES << (PAGE_SHIFT-9)` = 128;
`biolist == NULL` → `giveup`.
- [Phase 3] `git describe HEAD` / `make kernelversion`: 6.18.53, branch
`pending-6.18`.
- [Phase 3] 1/3 already ancestor (`0efabe6229dc6`); this commit is not
in HEAD.
- [Phase 4] `b4 mbox` 21-message thread; Yu Kuai: yield still valuable;
applied to md-7.3.
- [Phase 5] Caller: `md_register_thread(md_do_sync)` resync thread.
- [Phase 6] Skip path present; context matches; expected clean apply.
- [Phase 8] Failure: soft lockup 313s; severity CRITICAL.
- UNVERIFIED: lore.kernel.org/stable search (HTTP 403). Does not change
the verdict.
**YES**
drivers/md/md.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ce3bd127e3bb3..44f44219ed7fe 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9751,8 +9751,10 @@ void md_do_sync(struct md_thread *thread)
*/
md_new_event();
- if (last_check + window > io_sectors || j == max_sectors)
+ if (last_check + window > io_sectors || j == max_sectors) {
+ cond_resched();
continue;
+ }
last_check = io_sectors;
repeat:
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] drm/msm/adreno: Add support for A704 GPU
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (86 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] md: add cond_resched() to md_do_sync()'s skip path Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] ata: pata_ep93xx: fix PIO fallback when DMA init fails Sasha Levin
` (428 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Aditya Sherawat, Konrad Dybcio, Dmitry Baryshkov, Akhil P Oommen,
Rob Clark, Sasha Levin, lumag, airlied, simona, linux-arm-msm,
dri-devel, freedreno, linux-kernel
From: Aditya Sherawat <asherawa@qti.qualcomm.com>
[ Upstream commit 1f69339da06255a7f8560b4768fff83992c03deb ]
Adreno A704 GPU found in Shikra is an IP reuse of A702 GPU with very
minimal changes. The only KMD facing difference is the chipid and the
zap firmware which is specified via devicetree.
Just add the new chipid to enable support for A704 GPU in Shikra.
Signed-off-by: Aditya Sherawat <asherawa@qti.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
Patchwork: https://patchwork.freedesktop.org/patch/738931/
Message-ID: <20260710-shikra-gpu-v6-1-b388ec5dce77@oss.qualcomm.com>
Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is **Linux 7.3.0-rc4**
(`v7.3-rc4-27-gf0100363d8c37`). The commit is a one-line Adreno chip-id
add on the existing A702 catalog entry; that is the textbook device-ID
exception, so the rest of the write-up is the forensic checklist behind
a YES for this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[drm/msm/adreno] [Add] [register Adreno A704 chipid on the
existing A702 catalog entry]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected; this is new hardware ID enablement, not a
regression fix)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** Konrad Dybcio `<konrad.dybcio@oss.qualcomm.com>`
(listed reviewer of the msm/adreno driver); Dmitry Baryshkov
`<dmitry.baryshkov@oss.qualcomm.com>` (msm display maintainer)
- **Acked-by:** none
- **Link:** none in the commit body; **Patchwork:**
https://patchwork.freedesktop.org/patch/738931/; **Message-ID:**
`<20260710-shikra-gpu-v6-1-b388ec5dce77@oss.qualcomm.com>` (explicit
**v6 1/7** of the Shikra GPU series)
- **Cc: stable:** none (expected)
- **Signed-off-by:** Aditya Sherawat (author); Akhil P Oommen
(msm/adreno reviewer/maintainer, listed in MAINTAINERS); Rob Clark
(DRM msm maintainer, committer)
- Pipeline markers such as `Upstream commit` / `Signed-off-by: Sasha
Levin` were ignored per instructions; none were present on the git
object itself
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug/problem:** Adreno A704 on Qualcomm **Shikra** is an IP reuse of
A702. The kernel-facing difference is the chipid (`0x07000400` vs
`0x07000200`); zap firmware is supplied via DT, not a new catalog
firmware name.
- **Symptom:** without the chipid, `adreno_info()` does not match,
`adreno_has_gpu()` warns `Unknown GPU revision` and returns false, and
the GPU does not bind.
- **Version info:** none in the message. Git: commit is
`1f69339da06255a7f8560b4768fff83992c03deb`, first contained in
**v7.3-rc1**.
- **Root cause as stated:** missing catalog chipid; A704 is not a new
GPU family.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a hidden bug fix.** The subject is honest new-hardware
enablement. It still qualifies under the **new device-ID** stable
exception (one ID on an already-supported driver), not as a
crash/UAF/leak fix.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/gpu/drm/msm/adreno/a6xx_catalog.c` — **1 insertion,
1 deletion** (2 lines changed, 1 file)
- **Function/object:** `static const struct adreno_info a7xx_gpus[]` —
first entry (A702)
- **Scope:** single-file surgical ID add
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** that catalog entry matches only `chip_ids = {0x07000200,
0}`.
- **After:** `{0x07000200, 0x07000400, 0}`.
- **Path:** GPU probe / `adreno_has_gpu()` → `find_chipid()` (DT
compatible `qcom,adreno-07000400` or `qcom,chipid`) → `adreno_info()`
walks `chip_ids[]`. A704 now returns the existing A702 `adreno_info`
(same firmware `a702_sqe.fw`, same `a6xx_gmuwrapper_funcs`, same
quirks). Systems without that chipid are unchanged.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Hardware / device-ID enablement]** not UAF/leak/race.
Mechanism: catalog match table omitted `0x07000400`, so A704 never
bound. Fix: append the ID to the existing A702 row. Same pattern as
existing multi-id rows (e.g. A630 `0x06030001, 0x06030002`).
Verified detail: `adreno_is_a702()` compares `gpu->info->chip_ids[0] ==
0x07000200`. A702 remains first, so A704 still takes the A702 code paths
— consistent with “IP reuse”.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: **Obviously correct and minimal.** No API, locking, or struct-
layout change. Regression risk is **very low**: unknown chipids still
miss; only `0x07000400` newly matches, and it reuses the already-shipped
A702 programming. Zap firmware override remains DT `firmware-name`
(`adreno_gpu.c`).
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Current line is this commit (`1f69339da06255`).
- Surrounding A702 entry comes from catalog split **`2e819c420e5b8`**
(Rob Clark, 2024-06-18) and A702 support **`18397519cb622`**
(“drm/msm/adreno: Add A702 support”), first contained in **v6.9-rc1**.
- A702 code has been in-tree for many releases; this is not last-month-
only infrastructure.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** N/A. There is no “introduced the bug” SHA;
the gap is a new chipid on existing IP.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Immediate neighbors in `a6xx_catalog.c`: A810 support, A722 support,
GBIF rename, A730 hwcg fix — unrelated GPU SKUs.
- **Series:** Message-ID is **v6 1/7** “drm/msm: Add support for Shikra
GPU (A704)”. Rest of series: dt-binding `qcom,adreno-07000400`, SMMU
binding, Shikra GPU/SMMU/cooling DT, EVK enable.
- Binding commit **`9479a45e5f59c`** is in this tree
(`qcom,adreno-07000400` in `gpu.yaml`).
- This catalog patch is **standalone** as a match-table add; it does not
call new helpers.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Aditya Sherawat has this one msm/adreno commit in the path-
limited log. Submitted via **Akhil P Oommen** (MAINTAINERS reviewer for
Adreno) and merged by **Rob Clark**. Weight is from reviewer/maintainer
trailers, not author volume.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Needs the A702 `a7xx_gpus[]` row and `ADRENO_CHIP_IDS()` — both
present here.
- Does **not** need the rest of the 7-patch DT series to be correct or
safe.
- Cover letter listed many Shikra SoC prerequisites; those apply to
**board GPU bring-up**, not to appending a chipid.
- **Can apply standalone: yes.**
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 1f69339da06255`: **[PATCH v6 1/7] drm/msm/adreno: Add
support for A704 GPU** — https://patch.msgid.link/20260710-shikra-
gpu-v6-1-b388ec5dce77@oss.qualcomm.com
- `b4 dig -a`: v1 (2026-06-09, 2 patches, bindings-first) through **v6
(2026-07-10, 7 patches)**. Applied version is latest (v6).
- Cover letter (v5 mbox, same change-id): A704 is A702 reuse; Mesa
already merged
(gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41762). DT bits
added from v3.
- Reviews on this patch: R-b Konrad, R-b Dmitry. **No NAK** on the
chipid patch. Dmitry’s only v5 comment was parsing of the **GPU
cooling DT** commit (patch 6), unrelated to the chipid.
- **No reviewer Cc: stable** on this patch.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc included Rob Clark, Konrad Dybcio, Dmitry
Baryshkov, Akhil P Oommen, linux-arm-msm, dri-devel, freedreno, DT list.
Right maintainers and lists.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: **No syzbot/bugzilla/user crash.** Intent is enablement of
Shikra A704, not a fuzzer bug. Cover letter is the “report”.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 7-patch Shikra GPU series. This commit is **1/7** and is the
only KMD catalog change. Later patches are bindings/DT. Not a “2/3 logic
fix that is incomplete alone”.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: `https://lore.kernel.org/stable/?q=A704+adreno` → **[No results
found]**. No stable request and no documented rejection.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: No function body edited. Data: `a7xx_gpus[]`. Consumers:
`adreno_info()`, `adreno_has_gpu()`, `adreno_bind()`.
**Step 5.2: TRACE CALLERS**
Record:
- `adreno_info()`: used from `adreno_has_gpu()` and `adreno_bind()`.
- `adreno_has_gpu()` / bind: OF GPU device probe (drm/msm), not a
syscall-hot path.
- Context: platform probe, process context.
**Step 5.3: TRACE CALLEES**
Record: After match, `info->funcs->init` is existing
`&a6xx_gmuwrapper_funcs`. No new callees.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: userspace cannot invent a chipid; DT/firmware describes the GPU.
Reachable on Shikra (or any board with `qcom,adreno-07000400`). **Not**
a universal mm/fs path. Without a GPU node the new ID is inert.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Multiple `ADRENO_CHIP_IDS(id1, id2)` rows already exist (A630
and others). This is the standard alias-SKU pattern.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Tree: **7.3.0-rc4** (mainline -rc, `HEAD` `f0100363d8c37`).
- `a6xx_catalog.c` A702 row exists; **this commit is already an ancestor
of HEAD** (`git merge-base --is-ancestor 1f69339da06255 HEAD` → yes).
Current source already has `ADRENO_CHIP_IDS(0x07000200, 0x07000400)`.
- A702 support: **v6.9-rc1**; catalog file since **`2e819c420e5b8`**.
- Missing-id problem is real for any 7.3-based kernel that lacked this
SHA; this checkout already contains the ID.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** onto the A702 row in this tree (already
applied). No conflicting hunk. `a6xx_gmuwrapper_funcs` is present
(`491fadb2b818e`).
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Binding `9479a45e5f59c` is here. Shikra `shikra.dtsi` has GPUCC
but **no `gpu@` / `qcom,adreno-07000400` node** in this checkout — DT
enablement from later series patches is incomplete here, which does
**not** make the chipid harmful.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **drm/msm/adreno** (Qualcomm GPU). **IMPORTANT** for MSM/Adreno
devices, not core mm/vfs. Peripheral relative to the whole kernel;
important for Shikra and any other A704 SKU.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: **Active** — recent catalog churn (A810, A722, A840, X2-85).
Maintained by Rob Clark / Akhil / Konrad. Mature A702 path since v6.9;
this ID rides that path.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **driver/platform-specific** — Adreno A704 / Shikra. No effect
on other GPUs. `CONFIG_DRM_MSM` users only.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Probe of a GPU node whose parsed chipid is `0x07000400`. Common
on that SoC, never on others. Unprivileged users do not trigger a new
attack surface; they only get a working GPU after bind.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Without the ID: GPU not recognized, no bind, no display/compute
on that SoC — **not** panic/UAF. **Severity: MEDIUM for those devices**
(hardware dead), **LOW for everyone else**. Device-ID exception treats
that as backport-worthy enablement.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** A704/Shikra GPU can bind using the already-supported A702
path; Mesa support already exists per cover letter.
- **Risk:** very low (1-token ID, existing row, no hot-path/locking).
- **Ratio:** high benefit for that hardware, negligible risk.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Classic **new device ID** on an existing driver (A702 since v6.9).
- One-line, obviously correct; A704 is documented IP reuse of A702.
- Matching already supports multiple `chip_ids`; A702 stays
`chip_ids[0]` so `adreno_is_a702()` still works.
- Reviewed by Konrad Dybcio and Dmitry Baryshkov; signed off by Akhil P
Oommen; merged by Rob Clark.
- Inert on machines without chipid `0x07000400`.
- Local tree has the A702 catalog row, macros, and probe path; patch
applies (and is already in 7.3-rc1+).
**AGAINST:**
- Not a crash/security/corruption fix; it is new SKU enablement.
- Part of a 7-patch Shikra GPU series (DT still incomplete in this dts).
- No syzbot/user crash, no Cc: stable, no stable@ discussion.
- Author is not a high-volume subsystem regular (mitigated by maintainer
R-b/SOB).
**UNRESOLVED:**
- lore HTML for the v6 thread was 403 via WebFetch; discussion was
recovered via `b4 dig` + mbox (v5 thread saved; v6 is the applied
revision with the same chipid hunk).
- Whether every Shikra EVK DT patch is in 7.3-rc4: GPU node not found in
`shikra*.dts*`; does not change chipid safety.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one ID, two msm maintainers
R-b, merged by drm/msm maintainer; Mesa noted as already merged.
2. Fixes a real bug that affects users? **PASS** (via device-ID
exception) — without the ID, A704 never matches and the GPU does not
probe.
3. Important issue (crash, security, corruption, deadlock)? **PASS**
under the **new device-ID exception**, not as a critical memory-
safety fix. Severity for A704 owners is missing GPU, not oops.
4. Small and contained? **PASS** — 1 file, +1/-1.
5. No new features or APIs? **PASS** — no new uAPI/driver; only a chipid
alias on existing A702 code.
6. Can apply to the local tree? **PASS** — A702 row and
`ADRENO_CHIP_IDS` exist; commit is already in this 7.3-rc4 history.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **NEW DEVICE ID on an existing driver** (Adreno catalog chipid ≡
PCI/USB ID add). DT exception would apply to later series patches, not
this one.
**Step 9.4: MAKE YOUR DECISION**
This tree is **7.3.0-rc4**. The A702 driver and catalog entry are
present. The patch is a one-line chipid add, which stable policy
explicitly allows. It does not need the rest of the Shikra DT series to
be correct. Benefit is enabling A704; risk is negligible. That is a YES
for this tree.
---
**What the commit solves for users of this tree:** A704 reports chipid
`0x07000400`. Without it, drm/msm logs unknown revision and skips the
GPU. With it, the existing A702 path runs (SQE firmware, GMU wrapper,
quirks). Zap firmware stays DT-overridable.
**Stable rules:** small, reviewed, no new API; qualifies as a device-ID
add, not as a sanitizer/crash fix.
**Risk vs benefit:** very low risk, real hardware enablement for
Shikra/A704.
**Concerns:** series 1/7; DT GPU node may still be missing on Shikra in
this checkout — that does not make the ID unsafe. No crash-fix urgency.
Verification:
- [Phase 1] Subject/tags: no Fixes/Reported-by/Cc:stable; R-b Konrad +
Dmitry; SOB Akhil + Rob Clark; Message-ID v6-1/7
- [Phase 1] Body: A704 = A702 reuse; difference is chipid + DT zap
- [Phase 2] `git show 1f69339da06255`: `a6xx_catalog.c` +1/-1,
`ADRENO_CHIP_IDS(0x07000200, 0x07000400)`
- [Phase 2] `adreno_is_a702()` uses `chip_ids[0] == 0x07000200` — A702
remains first
- [Phase 2] `adreno_info()` matches any `chip_ids[k]`
(`adreno_device.c:59-61`)
- [Phase 3] `git describe --match 'v*' --contains 18397519cb622` → A702
in **v6.9-rc1**
- [Phase 3] `git describe --match 'v*' --contains 1f69339da06255` → A704
in **v7.3-rc1**
- [Phase 3] blame: A702 row from `2e819c420e5b8`; this line from
`1f69339da06255`
- [Phase 3] no Fixes: tag; standalone vs DT series
- [Phase 4] `b4 dig -c`: lore/msgid v6 1/7; `-a`: v1–v6; `-w`: msm
maintainers + lists
- [Phase 4] mbox `/tmp/a704-thread.mbox`: v5 0–7/7 subjects; R-b on
chipid; Dmitry comment only on cooling DT
- [Phase 4] lore.kernel.org/stable `A704 adreno`: no hits
- [Phase 4] WebFetch lore/patchwork: 403/Anubis; discussion taken from
b4/mbox instead
- [Phase 5] probe path `find_chipid` → `adreno_info` →
`info->funcs->init`; grep callers verified
- [Phase 5] similar multi-id: A630 `0x06030001, 0x06030002`
- [Phase 6] `git describe HEAD` → **v7.3-rc4-27-gf0100363d8c37**; `make
kernelversion` → **7.3.0-rc4**
- [Phase 6] `git merge-base --is-ancestor 1f69339da06255 HEAD` → yes
(already in this tree)
- [Phase 6] `gpu.yaml` contains `qcom,adreno-07000400` via
`9479a45e5f59c`
- [Phase 6] no `gpu@` / adreno compatible in
`arch/arm64/boot/dts/qcom/shikra*`
- [Phase 7] MAINTAINERS: Rob Clark / Konrad / Akhil for
`drivers/gpu/drm/msm/adreno/`
- [Phase 8] failure mode: unknown GPU, no bind; not oops; device-ID
exception
- UNVERIFIED: full v6 lore HTML (403); whether Shikra EVK GPU DT landed
under a different subject
**YES**
drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index b43850966a5f6..bbfee7fef6dc0 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -1417,7 +1417,7 @@ DECLARE_ADRENO_REGLIST_LIST(a750_ifpc_reglist);
static const struct adreno_info a7xx_gpus[] = {
{
- .chip_ids = ADRENO_CHIP_IDS(0x07000200),
+ .chip_ids = ADRENO_CHIP_IDS(0x07000200, 0x07000400),
.family = ADRENO_6XX_GEN1, /* NOT a mistake! */
.fw = {
[ADRENO_FW_SQE] = "a702_sqe.fw",
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ata: pata_ep93xx: fix PIO fallback when DMA init fails
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (87 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] drm/msm/adreno: Add support for A704 GPU Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] iommu/amd: Fix missing CMD_COMPLETE_PPR response for invalid PPR requests Sasha Levin
` (427 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Rosen Penev, Damien Le Moal, Sasha Levin, cassel, linux-ide,
linux-kernel
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit c303c3619a1d5cf7d4b457106062d16724724a80 ]
ep93xx_pata_dma_init() returns an error when dma_request_chan() fails,
which causes ep93xx_pata_probe() to abort entirely. The probe function
already has a PIO fallback path (it checks both channel pointers before
enabling UDMA), so the DMA init should not fail the probe on non-fatal
errors.
Propagate -EPROBE_DEFER, such that we allow the DMA controller driver
to load, in case we got probed before the DMA controller driver.
For all other failures (e.g. -ENODEV when the DMA controller is missing
in the device tree), fall back to PIO.
Assisted-by: Opencode:Big-Pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
Record: `[ata / pata_ep93xx] [fix] restore PIO fallback when DMA init
fails so probe does not abort`
**Step 1.2 — Tags**
Record:
- `Assisted-by: Opencode:Big-Pickle`
- `Signed-off-by: Rosen Penev <rosenp@gmail.com>` (author)
- `Signed-off-by: Damien Le Moal <dlemoal@kernel.org>` (libata
maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, `Link:`, or `Cc: stable` (absence of Fixes/Cc:stable is expected
here)
- Notable: no user/syzbot report; maintainer SOB is present
**Step 1.3 — Body**
Record:
- **Bug:** `ep93xx_pata_dma_init()` treats any `dma_request_chan()`
failure as fatal. `ep93xx_pata_probe()` then returns that error and
never registers the ATA host.
- **Symptom:** PATA/IDE controller never appears; storage is
unavailable. PIO fallback in probe (channel-pointer check before UDMA)
is dead for this path.
- **Root cause:** after the OF DMA conversion, non-defer errors (e.g.
`-ENODEV`) abort probe instead of continuing without DMA.
- **Intended fix:** propagate `-EPROBE_DEFER`; for other failures, warn
and return 0 so the existing PIO path runs.
- **Version info in message:** none.
**Step 1.4 — Hidden bug fix?**
Record: Not hidden. The subject and body describe a real probe
regression. The diff also NULLs error pointers and stops
`fail_release_rx` from falling through into a second release.
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
Record:
- File: `drivers/ata/pata_ep93xx.c` (+21/−9, 30 lines)
- Function: `ep93xx_pata_dma_init()`
- Scope: single-file surgical error-path change
**Step 2.2 — Code flow**
Record (pre-image from `c303c3619a1d5^`):
- **rx `dma_request_chan` fail:** `dev_err_probe()` and return the
error. Probe aborts. `dma_rx_channel` left as `ERR_PTR`.
- **tx `dma_request_chan` fail:** `dev_err_probe()`, `goto
fail_release_rx`. That released rx, then **fell through** into
`fail_release_dma` → `ep93xx_pata_release_dma()` with rx still non-
NULL and tx still an error pointer.
- **`dmaengine_slave_config` fail:** `dev_err_probe()`, release both,
**return `ret`** → probe aborts.
- **After:** non-defer failures NULL the pointers, warn, return 0.
`-EPROBE_DEFER` still fails probe so the DMA driver can load.
`fail_release_rx` no longer falls through.
**Step 2.3 — Bug mechanism**
Record:
- **Primary:** logic/error-path — optional DMA failure became a hard
probe failure (regression of designed PIO fallback).
- **Secondary:** error-path resource handling — old tx-fail path could
`dma_release_channel()` twice on rx and pass `ERR_PTR` into
`dma_release_channel()` (`chan->client_count` dereference in
`drivers/dma/dmaengine.c`).
**Step 2.4 — Fix quality**
Record: Obviously correct and minimal. Matches pre-v6.12 void `dma_init`
(fail DMA, keep probing). Regression risk is low: happy path unchanged;
`-EPROBE_DEFER` still delays probe; libata only sets `udma_mask` when
both channels are non-NULL, so BMDMA ops are not used in PIO mode. No
API/data-structure change.
## Phase 3: Git history
**Step 3.1 — Blame**
Record: The failing `dma_request_chan()` + `return int` behavior was
introduced by `9963113e3a924` (“ata: pata_ep93xx: add device tree
support”, 2024-09-12), contained in **v6.12-rc1**. Before that,
`ep93xx_pata_dma_init()` was `void` and returned after releasing
channels, leaving pointers NULL. Driver itself dates to `2fff27512600`
(2012).
**Step 3.2 — Fixes: tag**
Record: No `Fixes:` tag. The commit that introduced the bug is
`9963113e3a924`. `git merge-base --is-ancestor 9963113e3a924 HEAD`
succeeds in this tree.
**Step 3.3 — File history**
Record: Between the DT conversion and this fix: pinctrl/DT cleanup,
`remove()` callback switch, COMPILE_TEST/type tweaks. No other DMA-init
semantics change. Not patch X/Y. Standalone.
**Step 3.4 — Author**
Record: Rosen Penev is a regular ATA contributor. Damien Le Moal (libata
maintainer) applied it to `for-7.3`.
**Step 3.5 — Dependencies**
Record: Needs the v6.12 `dma_request_chan()` conversion
(`9963113e3a924`). That is in this tree. No extra helper/API required.
Applies standalone on this code.
## Phase 4: Mailing list / external
**Step 4.1 — Original discussion**
Record:
- Lore/msgid:
https://patch.msgid.link/20260720020229.1972888-1-rosenp@gmail.com
(v2, committed)
- v1: https://patch.msgid.link/20260601190749.20045-1-rosenp@gmail.com
- v1→v2: commit-message only (`v2: fix EPROBE_DEFER description`). Code
unchanged.
- Niklas Cassel on v1: “This patch looks correct to me”, asked not to
call `-EPROBE_DEFER` “fatal”.
- Damien on v2: “Applied to for-7.3. Thanks!”
- No NAK, no stable nomination, no reviewer risk flags.
**Step 4.2 — Recipients (`b4 dig -w`)**
Record: `linux-ide@vger.kernel.org`, Damien Le Moal, Niklas Cassel,
`linux-kernel`. Right maintainers.
**Step 4.3 — Bug report**
Record: No `Reported-by` / bugzilla / syzbot. Bug is from code
inspection of the DT conversion.
**Step 4.4 — Series**
Record: Single standalone patch, two revisions, message-only v2.
**Step 4.5 — stable@**
Record: No stable-list discussion found (lore HTML search was unusable;
v2 mbox/thread had no stable Cc). UNVERIFIED beyond the v1/v2 linux-ide
thread.
## Phase 5: Semantic / call chain
**Step 5.1 — Functions**
Record: `ep93xx_pata_dma_init()` only (callees: `dma_request_chan`,
`dmaengine_slave_config`, `dma_release_channel`,
`ep93xx_pata_release_dma`).
**Step 5.2 — Callers**
Record: Only `ep93xx_pata_probe()` (`err =
ep93xx_pata_dma_init(drv_data); if (err) return err;`). Platform probe /
device enumeration. Not IRQ/hot path.
**Step 5.3 — Callees**
Record: `dma_request_chan()` → `of_dma_request_slave_channel()`. Missing
`dmas` returns `-ENODEV` (“Silently fail if there is not even the dmas
property”). Missing controller while `dmas` is present returns
`-EPROBE_DEFER`.
**Step 5.4 — Reachability**
Record: Reachable when `CONFIG_PATA_EP93XX` is enabled and the
`cirrus,ep9312-pata` platform device probes. Userspace does not trigger
it directly; boot/device probe does. On this tree the SoC dtsi node is
`status = "disabled"` and no in-tree board enables `&ide`.
Binding/example still has no `dmas`, so **any** DT that enables the node
as documented hits `-ENODEV` and, before the fix, never binds.
**Step 5.5 — Similar patterns**
Record: Pre-6.12 driver already implemented this fallback. Probe still
has `if (drv_data->dma_rx_channel && drv_data->dma_tx_channel)` before
setting `udma_mask`.
## Phase 6: This tree (v7.3-rc4)
**Step 6.1 — Buggy code here?**
Record: Yes. Local tree: `git describe HEAD` =
**v7.3-rc4-27-gf0100363d8c37**, `make kernelversion` = **7.3.0-rc4**.
`9963113e3a924` is an ancestor. Pre-fix `ep93xx_pata_dma_init()` in
`c303c3619a1d5^` returns errors from `dma_request_chan()`. The candidate
itself is also an ancestor of HEAD (already in 7.3); that does not
change whether the bug class exists in this lineage.
**Step 6.2 — Backport difficulty**
Record: Clean apply on this tree’s `pata_ep93xx.c` (post-DT
`dma_request_chan` shape). No conflicting local changes after the fix.
**Step 6.3 — Related fixes already here**
Record: This is the fix. No later follow-up on the file. `5c8121262484d`
(“pata_ep93xx: fix deferred probing”) only touches `platform_get_irq()`,
not DMA init.
## Phase 7: Subsystem context
**Step 7.1**
Record: Subsystem `drivers/ata` (libata PATA). Criticality
**PERIPHERAL/IMPORTANT**: storage driver, but only Cirrus EP93xx
(`CONFIG_PATA_EP93XX` depends on `ARCH_EP93XX || COMPILE_TEST`).
**Step 7.2**
Record: File is mature (2012) with a burst of DT work in 6.12; otherwise
low churn.
## Phase 8: Impact and risk
**Step 8.1 — Who is affected**
Record: EP93xx PATA users on DT kernels (6.12+). Not universal. In-tree
boards do not enable the IDE node today; anyone enabling it per the
binding (no `dmas`; `additionalProperties: false`) is affected.
**Step 8.2 — Trigger**
Record: Device probe. Common if the node is enabled: official
dtsi/binding have no DMA properties, so `dma_request_chan("rx")` returns
`-ENODEV` every boot. Unprivileged userspace cannot trigger it. Not a
race.
**Step 8.3 — Failure mode**
Record:
- Main: probe fails → no ATA host → disk missing (boot/rootfs failure if
PATA is the disk). Severity **HIGH** for those boards, not a kernel
oops.
- Secondary (rx OK, tx fail): `dma_release_channel(ERR_PTR)` / double-
release. Severity **HIGH** if hit; needs a DT with a working `rx` name
and failing `tx`. Not the in-tree DT shape.
**Step 8.4 — Risk/benefit**
Record: Benefit medium-high for EP93xx DT PATA (driver actually binds).
Risk very low (error path only, ~20 lines, maintainer-acked). Ratio
favors backport.
## Phase 9: Synthesis
**Step 9.1 — Evidence**
FOR:
- Real v6.12 regression: DMA init errors abort probe; original design
and probe still expect PIO fallback.
- In-tree binding/example/dtsi do not describe DMA, so `-ENODEV` is the
realistic `dma_request_chan()` result if the node is enabled.
- Also closes a bad tx-fail cleanup (ERR_PTR / double-release).
- Small, obviously correct; Niklas: “looks correct”; Damien applied it.
- Prerequisites (`dma_request_chan` conversion) are in this tree.
AGAINST:
- Niche SoC; IDE node disabled in all in-tree boards — limited default
user base.
- No crash/syzbot/user report.
- Not a new feature, but also not a universal core-kernel bug.
UNRESOLVED:
- Whether any production EP93xx DT out of tree enables this node
(unverified).
- No stable@ thread found beyond linux-ide.
**Step 9.2 — Stable rules**
1. Obviously correct and tested? **PASS** — logic matches pre-6.12; v1
reviewed; maintainer applied. No separate hardware Tested-by.
2. Real bug affecting users? **PASS** — probe failure / non-working PATA
when DMA is absent.
3. Important (crash/security/corruption/deadlock/etc.)? **PASS** —
storage controller fails to register (boot-breaking if PATA is the
disk). Not an oops, but functionally serious. Secondary error-path
UAF-class DMA release if tx fails after rx.
4. Small and contained? **PASS** — one function, +21/−9.
5. No new features/APIs? **PASS**.
6. Can apply to this tree? **PASS** — same `dma_request_chan` code; DT
conversion is present.
**Step 9.3 — Exception category**
Record: None (not an ID/quirk/DT/build/doc exception). Ordinary driver
bugfix.
**Step 9.4 — Decision**
This tree is **7.3-rc4**. The v6.12 DT conversion is here, so the bug
exists in this lineage. The patch restores the driver’s intended PIO
fallback, keeps `-EPROBE_DEFER`, and is a small, reviewed error-path
fix. It meets stable criteria for this checkout.
What it solves for stable users: after the 6.12 OF DMA switch, missing
DMA (the documented DT) made `pata_ep93xx` fail probe instead of running
PIO. That can leave the disk missing. Risk is low; no extra commits are
required here.
Verification:
- [Phase 1] Parsed tags: author + Damien SOB only; no Fixes/Reported-
by/Cc:stable
- [Phase 2] Diff: `ep93xx_pata_dma_init()` error paths; return 0 except
`-EPROBE_DEFER`; NULL ERR_PTRs; split `fail_release_rx` from
`fail_release_dma`
- [Phase 2] Parent file: `git show
c303c3619a1d5^:drivers/ata/pata_ep93xx.c` confirms probe abort + fall-
through release
- [Phase 2] `dma_release_channel()` dereferences `chan->client_count` —
ERR_PTR would oops
- [Phase 3] Blame: buggy `dma_request_chan` from `9963113e3a924`
(v6.12-rc1); `git merge-base --is-ancestor 9963113e3a924 HEAD` true
- [Phase 3] Pre-DT `dma_init` was void and already fell back to PIO
- [Phase 4] `b4 dig -c c303c3619a1d5`: v1 2026-06-01, v2 2026-07-19
(message-only)
- [Phase 4] Niklas Cassel: “looks correct”; Damien: “Applied to for-7.3”
- [Phase 5] Only caller: `ep93xx_pata_probe()`;
`of_dma_request_slave_channel` returns `-ENODEV` without `dmas`
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37;
kernelversion 7.3.0-rc4
- [Phase 6] Binding `cirrus,ep9312-pata.yaml`: no dmas,
`additionalProperties: false`; dtsi `ide@800a0000` has no dmas, status
disabled; no `&ide` enable in in-tree boards
- [Phase 8] Failure: probe fail / no disk; not an oops on the common
`-ENODEV` path
- UNVERIFIED: out-of-tree boards enabling this node; stable@ mailing
list beyond linux-ide
**YES**
drivers/ata/pata_ep93xx.c | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index b2b9e0058333e..3f61712af5bbe 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -652,14 +652,22 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
* start of new transfer.
*/
drv_data->dma_rx_channel = dma_request_chan(dev, "rx");
- if (IS_ERR(drv_data->dma_rx_channel))
- return dev_err_probe(dev, PTR_ERR(drv_data->dma_rx_channel),
- "rx DMA setup failed\n");
+ if (IS_ERR(drv_data->dma_rx_channel)) {
+ ret = PTR_ERR(drv_data->dma_rx_channel);
+ drv_data->dma_rx_channel = NULL;
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ dev_warn(dev, "rx DMA unavailable, using PIO\n");
+ return 0;
+ }
drv_data->dma_tx_channel = dma_request_chan(&pdev->dev, "tx");
if (IS_ERR(drv_data->dma_tx_channel)) {
- ret = dev_err_probe(dev, PTR_ERR(drv_data->dma_tx_channel),
- "tx DMA setup failed\n");
+ ret = PTR_ERR(drv_data->dma_tx_channel);
+ drv_data->dma_tx_channel = NULL;
+ if (ret == -EPROBE_DEFER)
+ goto fail_release_rx;
+ dev_warn(dev, "tx DMA unavailable, using PIO\n");
goto fail_release_rx;
}
@@ -670,7 +678,7 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ret = dmaengine_slave_config(drv_data->dma_rx_channel, &conf);
if (ret) {
- dev_err_probe(dev, ret, "failed to configure rx dma channel");
+ dev_warn(dev, "failed to configure rx dma channel, using PIO\n");
goto fail_release_dma;
}
@@ -681,7 +689,7 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ret = dmaengine_slave_config(drv_data->dma_tx_channel, &conf);
if (ret) {
- dev_err_probe(dev, ret, "failed to configure tx dma channel");
+ dev_warn(dev, "failed to configure tx dma channel, using PIO\n");
goto fail_release_dma;
}
@@ -689,10 +697,14 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
fail_release_rx:
dma_release_channel(drv_data->dma_rx_channel);
+ drv_data->dma_rx_channel = NULL;
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ return 0;
+
fail_release_dma:
ep93xx_pata_release_dma(drv_data);
-
- return ret;
+ return 0;
}
static void ep93xx_pata_dma_start(struct ata_queued_cmd *qc)
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] iommu/amd: Fix missing CMD_COMPLETE_PPR response for invalid PPR requests
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (88 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] ata: pata_ep93xx: fix PIO fallback when DMA init fails Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] wifi: mt76: set the EOSP bit in the QoS header of the last released frame Sasha Levin
` (426 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Vasant Hegde, Gaultier Delbarre, Wei Huang, Ankit Soni,
Joerg Roedel, Sasha Levin, joro, will, iommu, linux-kernel
From: Vasant Hegde <vasant.hegde@amd.com>
[ Upstream commit bc1f5ec826bfa510e7138e2be5aad23907850874 ]
The AMD IOMMU spec, requires the host to respond with a CMD_COMPLETE_PPR
command when an EVENT_TYPE_INV_PPR_REQ event is received with the RX bit
cleared. This response was missing in the current implementation, leaving
invalid PPR requests unacknowledged.
Introduce amd_iommu_report_ppr_err() to handle EVENT_TYPE_INV_PPR_REQ
events. The new function logs the invalid PPR request and when the RX
bit is cleared, sends CMD_COMPLETE_PPR response.
Reported-by: Gaultier Delbarre <Gaultier.Delbarre@amd.com>
Co-developed-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Ankit Soni <Ankit.Soni@amd.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: the INV_PPR_REQ path is in this 6.12 tree, the
completion helper already exists, and the fix is a small spec-compliance
change to stop PRI stalls.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[iommu/amd] [Fix] missing CMD_COMPLETE_PPR response for
invalid PPR requests.** The subject is an explicit bug fix in the AMD
IOMMU driver: invalid PPR (Page Request) events were logged but not
acknowledged to hardware.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Reported-by:** Gaultier Delbarre (AMD) — real hardware/spec issue
found inside AMD, not a theoretical cleanup.
- **Co-developed-by / Signed-off-by:** Wei Huang (AMD), Vasant Hegde
(AMD IOMMU maintainer/author).
- **Reviewed-by:** Ankit Soni (AMD).
- **Signed-off-by:** Joerg Roedel (IOMMU maintainer).
- **No Fixes: tag** (expected for this review pipeline).
- **No Cc: stable** (expected).
- **No syzbot, Link, Tested-by, or Acked-by.**
- Ignore any pipeline-added Sasha Levin SOB / Upstream commit markers.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** AMD IOMMU spec requires the host to issue `CMD_COMPLETE_PPR`
when an `EVENT_TYPE_INV_PPR_REQ` event arrives with the RX bit
**cleared**. The driver only printed `INVALID_PPR_REQUEST` and
returned.
- **Symptom:** Invalid PPR/PRI requests stay unacknowledged. The device
keeps the outstanding page-request slot; further PRI traffic can stall
(DMA/GPU/SVA hang), rather than a kernel oops.
- **Root cause:** Event-log handler treated INV_PPR_REQ as log-only; the
completion path used for valid PPR (`amd_iommu_complete_ppr()`) was
never invoked.
- **Fix:** New `amd_iommu_report_ppr_err()` logs the event and, if RX=0,
sends `CMD_COMPLETE_PPR` with `IOMMU_PAGE_RESP_FAILURE`.
- **Version info in message:** none.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a hidden fix.** The subject and body state a spec-mandated
missing hardware response. This is a protocol/hang fix, not a style
cleanup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `drivers/iommu/amd/amd_iommu_types.h`: +1 (`EVENT_FLAG_PPR_RX 0x001`).
- `drivers/iommu/amd/iommu.c`: ~+33/-6. New
`amd_iommu_report_ppr_err()`; `iommu_print_event()` INV_PPR_REQ case
now calls it; unused local `tag` removed.
- **Scope:** single-driver surgical fix. ~38 lines net. No API/ABI
change.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `iommu_print_event()` on type 0x9 extracted PASID/tag,
`dev_err()`, break. No IOMMU command.
- **After:** same log, then if `!(flags & EVENT_FLAG_PPR_RX)` look up
the PCI device, check IOMMU private data, call existing
`amd_iommu_complete_ppr(..., IOMMU_PAGE_RESP_FAILURE, tag)`.
- **Path:** threaded IRQ event-log poll (`amd_iommu_int_thread_evtlog` →
`iommu_poll_events` → `iommu_print_event`), not a syscall hot path.
Error/exception path for invalid hardware page requests.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Hardware protocol / hang (logic/correctness).** Missing
command on an exception event. Analogous to Intel VT-d
`handle_bad_prq_event()`, which already submits a page-group response
for invalid PRQ. Not UAF/leak/race/overflow.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Obviously correct** for the common case: RX=0 → complete with
FAILURE using the same helper as `ppr.c` already uses for “nobody
cared” PPR entries.
- **Minimal:** one flag, one helper, one call-site change.
- **Regression risk: low.** Patterns match existing event/PPR handling
(`pci_get_domain_bus_and_slot` + `pci_dev_put` already used from
`amd_iommu_report_page_fault()` in this same function).
`iommu_queue_command()` takes `iommu->lock` with
`raw_spin_lock_irqsave`; `iommu_print_event()` does not hold that
lock.
- **Known incompleteness (accepted in the committed form):** if
`pci_get_domain_bus_and_slot()` fails or there is no IOMMU priv, it
still returns without COMPLETE_PPR. Ankit Soni raised that on list;
the committed diff still has those early returns, and Ankit still
Reviewed-by. Those are devices not in the PCI tree / not bound — the
PRI-using devices this matters for have both.
- **Follow-up in the same series (not this commit):** patch 4 rate-
limits the log; patch 5 fixes GN derivation (`pri_tlp` vs v2 page-
table). This commit uses existing `amd_iommu_complete_ppr()` (GN from
`pri_tlp`), which is already how every COMPLETE_PPR in **this** tree
is built. Not a new regression vs current 6.12 behavior.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- INV_PPR_REQ case introduced in **e7f63ffc1bf19** (“iommu/amd: Update
logging information for new event type”, 2018-05-01, Gary R Hook) —
log-only from the start.
- PASID extraction: 470eb3b31134ad (Suravee, 2019).
- Log format: later Vasant Hegde updates (b36a5b0f1cedbb / pci_seg).
- Buggy behavior (log, no COMPLETE_PPR) has been in-tree for years,
including this 6.12 checkout.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** The missing response became operationally
important once PRI/PPR completion existed: **978d626b8f1a2**
(“iommu/amd: Add IO page fault notifier handler”, Wei Huang, 2024-04-18)
added `amd_iommu_complete_ppr()` and PPR log handling. That commit **is
an ancestor of HEAD**.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- This commit is **patch 3/5** of “iommu/amd: PRI related cleanup and
fixes” (Vasant Hegde, 2026-07-27).
1. Device ID in invalid PASID log — **already in this tree**
(`5a5cd58b1533e`).
2. `PPR_TAG_LAST_PAGE()` macro — cleanup; **not required** for this
patch.
3. **This fix** — missing COMPLETE_PPR.
4. Rate-limit INVALID_PPR_REQUEST — depends on 3; current 6.12 already
logs unbounded `dev_err` here, so 3 alone is not a log-flood
regression.
5. GN bit in COMPLETE_PPR — separate correctness fix; refactors
`amd_iommu_complete_ppr()`.
- Recent `iommu.c` churn is attach/flush locking, not this event case.
**Standalone for the bug it fixes.**
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Vasant Hegde is the AMD IOMMU driver author on this tree (many
`drivers/iommu/amd/` commits). Wei Huang added the 2024 IOPF/PPR
notifier. This is a maintainer-area fix, not a drive-by.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: **Can apply standalone on this tree.** Required symbols all
exist:
- `amd_iommu_complete_ppr()` (`iommu.c` ~1827, declared in
`amd_iommu.h`)
- `PPR_PASID()`, `IOMMU_PAGE_RESP_FAILURE`,
`pci_get_domain_bus_and_slot`, `dev_iommu_priv_get`, `iommu->pci_seg`
- `EVENT_TYPE_INV_PPR_REQ` case already present
- Patches 2/4/5 not required for this change to compile or to send a
completion.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Series: [PATCH 0/5] iommu/amd: PRI related cleanup and fixes, Vasant
Hegde, 2026-07-27.
- Patch 3: https://ratatoskr.run/linux-iommu/2026/07/17321958
- Cover: https://ratatoskr.run/linux-iommu/2026/07/17321955
- Review: https://ratatoskr.run/linux-iommu/2026/07/17327932 (Ankit
Soni, 2026-07-28): suggested issuing COMPLETE_PPR even when
`pdev`/priv is missing, via
`build_complete_ppr()`/`iommu_queue_command()`. **No NAK.** Committed
code matches v1 (early returns kept) and carries Ankit’s Reviewed-by.
- **UNVERIFIED:** `b4 dig -c` needs a SHA not in this checkout. `b4
mbox` of msgid `26cfa307-6c33-41f9-a7a0-fbf202b38a00@amd.com` returned
an unrelated IRT-cache thread. lore.kernel.org search URLs returned
**403**. No evidence of a later v2 that replaced this diff.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Recipients/maintainers on the series include Joerg Roedel (SOB
on the commit), Ankit Soni (Reviewed-by), Wei Huang (co-developer).
Appropriate AMD IOMMU reviewers.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: Reporter is AMD (Gaultier Delbarre). No public syzbot/bugzilla
link. This is spec non-compliance observed on AMD hardware/firmware, not
a fuzzer crash.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 5-patch PRI series. Patch 1 already backported here. 2 is
cosmetic. 3 is the hang/protocol fix. 4 is log-rate-limit on top of 3. 5
is GN-bit correctness for all COMPLETE_PPR, plus using event-flag GN on
this new path. **This commit is self-contained;** 5 is a nice follow-up,
not a hard apply dependency.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — lore.kernel.org/stable returned 403. No local
`git log --grep=CMD_COMPLETE_PPR` hits in this tree.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: Added `amd_iommu_report_ppr_err()`. Modified
`iommu_print_event()`. Calls existing `amd_iommu_complete_ppr()`.
**Step 5.2: TRACE CALLERS**
Record:
- `iommu_print_event()` ← `iommu_poll_events()` ←
`amd_iommu_int_thread_evtlog()` / `amd_iommu_int_thread()` (threaded
IRQ).
- `amd_iommu_complete_ppr()` already called from
`iommu_call_iopf_notifier()` and `amd_iommu_page_response()` in
`ppr.c` (same IRQ-thread class for PPR log).
**Step 5.3: TRACE CALLEES**
Record: `PPR_PASID()`, `pci_get_domain_bus_and_slot()`,
`dev_iommu_priv_get()`, `amd_iommu_complete_ppr()` →
`build_complete_ppr()` + `iommu_queue_command()` (command buffer, may
`udelay` under `iommu->lock` on full buffer — existing behavior).
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: **Reachable in production** on AMD IOMMU hardware with PPR
(Guest Translation + PPR + EPHSUP: `amd_iommu_gt_ppr_supported()`). PPR
log is enabled in `enable_iommus_ppr()`. PRI is enabled on SVA-capable
domain attach (`pdev_enable_caps()`). Userspace/devices that use
SVA/PASID/PRI (AMD GPU SVM, some VFIO) can generate PPR; invalid ones
produce INV_PPR_REQ in the event log. Not a syscall bug; a device
DMA/PRI stall.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: `ppr.c` already completes invalid/unhandled PPR log entries with
`IOMMU_PAGE_RESP_FAILURE`. Intel `handle_bad_prq_event()` always
responds to invalid PRQ when LPIG is set. This patch closes the AMD
event-log gap for the same class of bug.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Local tree is **6.12.111** (`p-6.12-3-gc504cf0baa3d8`,
Makefile VERSION/PATCHLEVEL/SUBLEVEL 6/12/111).
```973:979:drivers/iommu/amd/iommu.c
case EVENT_TYPE_INV_PPR_REQ:
pasid = PPR_PASID(*((u64 *)__evt));
tag = event[1] & 0x03FF;
dev_err(dev, "Event logged [INVALID_PPR_REQUEST ...
break;
```
No `EVENT_FLAG_PPR_RX`, no `amd_iommu_report_ppr_err()`. Bug introduced
as log-only in 2018; completion helper present since 978d626b8f1a2 (in
this tree).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Expected apply: clean or trivial context.** 6.12
`iommu_print_event()` lacks a later `ctrl = readq(MMIO_CONTROL_OFFSET)`
local that appears in the mainline hunk context; the INV_PPR_REQ case,
`report_page_fault` insertion point, and `EVENT_FLAG_I` site match. No
conflicting local change to this switch arm.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No existing COMPLETE_PPR on INV_PPR_REQ. Related:
`5a5cd58b1533e` (series patch 1, log-only), `1de4443f85e44` (pci_dev_put
after PPR faults). **This specific bug is unfixed here.**
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **drivers/iommu/amd** — **IMPORTANT** (not core mm/VFS). AMD
IOMMU is default DMA isolation on AMD x86; PRI/PPR is a subset
(SVA/IOPF), but a hung PRI-capable device (GPU) is user-visible.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained in 6.12 (flush, attach locking, SNP log
sizes, PPR). Mature driver; this event type is old. Fix is not for
brand-new code missing from 6.12.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Platform/config-specific:** AMD IOMMU + PPR/PRI-capable
devices (SVA/PASID). Not every AMD desktop, but real 6.12 users
(ROCm/KFD SVM, IOMMU page-fault devices).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Hardware logs INV_PPR_REQ (invalid PRI/PPR). RX=0 means software
**must** complete. Trigger is device-generated, not a userspace syscall.
Unprivileged code on an SVA-bound device can cause invalid page
requests. Timing: not a race; missing response every time RX=0.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Device/PRI hang (HIGH), not a kernel panic.** Unacked PRI
consumes outstanding page-request slots (PRI enable uses 32 outstanding
in `pdev_enable_cap_pri()`). Device DMA can stall; GPU/compute jobs
hang. Matches stable-rules “hang” / hardware protocol failure. Reporter
is AMD — they saw it.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit: high** for AMD PRI/SVA users (prevents stuck page-request
state).
- **Risk: low** (~30 lines, existing helper, same IRQ-thread context as
PPR completion, no lock-order novelty vs `report_page_fault`).
- **Ratio:** favorable. Worst extra load is queuing COMPLETE_PPR under a
PPR flood; spec requires that, and command-buffer timeout already
exists.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
**FOR backporting:**
- Real spec bug: missing `CMD_COMPLETE_PPR` for INV_PPR_REQ with RX=0.
- User-visible hang (PRI/DMA stall), reported by AMD.
- Buggy log-only path exists in this 6.12 tree; completion helper
already here.
- Small, obviously correct, uses existing `amd_iommu_complete_ppr()`.
- Reviewed by AMD; SOB from Joerg Roedel.
- Intel already answers invalid PRQ the same way.
- No new APIs/features.
**AGAINST:**
- Not a kernel oops/UAF; only PRI-capable AMD devices.
- Series follow-ups 4 (ratelimit) and 5 (GN bit) are not in this commit;
5 says `pri_tlp` is the wrong GN source — but that is **already** how
6.12 completes all PPRs.
- Corner-case still skips completion without `pdev`/priv.
- No Fixes:/Cc: stable (not a negative per pipeline rules).
**UNRESOLVED:**
- Exact mainline SHA (`b4 dig -c` not possible without it).
- Stable-list discussion (lore 403).
- Whether a v2 addressed Ankit’s always-complete suggestion (committed
diff matches v1).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — spec-aligned; AMD-
developed/reviewed; Joerg SOB. (Tested-by not in message; author +
reviewer are the hardware vendor.)
2. Fixes a real bug that affects users? **PASS** — unacked invalid PPR;
Reported-by AMD.
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
hang / hardware protocol stall (HIGH), not cosmetic.
4. Small and contained? **PASS** — ~30 lines, two files, one driver.
5. No new features or APIs? **PASS** — uses existing complete-PPR
command.
6. Can apply to the local tree? **PASS** — buggy code and helpers
present; apply should be clean or trivial context.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/doc exception. Qualifies as a
**normal hang/protocol bug fix**.
**Step 9.4: MAKE YOUR DECISION**
This should be backported to **this** 6.12.y tree. The INV_PPR_REQ
handler has never sent COMPLETE_PPR; 6.12 already has PRI/PPR completion
for the PPR log. The patch is small, uses that helper, and prevents
device-side PRI stalls on AMD IOMMU.
The problem is a missing hardware response, not a new feature. Stable
users with AMD IOMMU + PRI/SVA can hang outstanding page requests; the
fix is ~30 lines and matches code already used from `ppr.c`. Patch 5 (GN
bit) is a separate improvement already latent in 6.12’s `pri_tlp` usage
and is not required for this commit to help.
Verification:
- [Phase 1] Parsed tags: Reported-by Gaultier Delbarre (AMD); Co-
developed-by Wei Huang; SOB Vasant Hegde + Joerg Roedel; Reviewed-by
Ankit Soni; no Fixes/Cc:stable/syzbot.
- [Phase 2] Diff: +EVENT_FLAG_PPR_RX; new amd_iommu_report_ppr_err();
INV_PPR_REQ calls complete_ppr on RX=0; ~33/-6 lines.
- [Phase 3] git blame 973-979 iommu.c: e7f63ffc1bf19 (2018) introduced
log-only INV_PPR_REQ.
- [Phase 3] 978d626b8f1a2 is ancestor of HEAD (`git merge-base --is-
ancestor` succeeded); amd_iommu_complete_ppr exists at iommu.c:1827.
- [Phase 3] git log --oneline --grep=CMD_COMPLETE_PPR --
drivers/iommu/amd/: empty (fix not in this tree).
- [Phase 3] Series patch 1 already present: 5a5cd58b1533e.
- [Phase 4] Ratatoskr: series 0/5 17321955, patch 3 17321958, Ankit
review 17327932 (corner case, no NAK).
- [Phase 4] b4 dig -c: **UNVERIFIED** (SHA not in tree). b4 mbox of
26cfa307-… pulled the wrong thread.
- [Phase 4] lore.kernel.org and lore stable search: **UNVERIFIED** (HTTP
403).
- [Phase 5] Callers: amd_iommu_int_thread_evtlog → iommu_poll_events →
iommu_print_event (threaded IRQ). complete_ppr already used from ppr.c
in the PPR IRQ thread.
- [Phase 5] Intel analog: handle_bad_prq_event() in
drivers/iommu/intel/prq.c submits QI page-group response.
- [Phase 6] git describe HEAD: p-6.12-3-gc504cf0baa3d8; make
kernelversion: 6.12.111; buggy INV_PPR_REQ case present;
EVENT_FLAG_PPR_RX absent.
- [Phase 6] 6.12 iommu_print_event lacks later `ctrl` MMIO read;
INV_PPR_REQ hunk still matches.
- [Phase 7] Subsystem drivers/iommu/amd, IMPORTANT, actively maintained.
- [Phase 8] Failure mode: unacked PRI → device hang; severity HIGH;
trigger AMD PPR/PRI hardware.
- UNVERIFIED: mainline SHA; v2 of series; stable@ discussion.
**YES**
drivers/iommu/amd/amd_iommu_types.h | 1 +
drivers/iommu/amd/iommu.c | 38 ++++++++++++++++++++++++-----
2 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index dee077bd149b7..5f43a0fcdd1e3 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -158,6 +158,7 @@
#define EVENT_FLAGS_SHIFT 0x10
#define EVENT_FLAG_RW 0x020
#define EVENT_FLAG_I 0x008
+#define EVENT_FLAG_PPR_RX 0x001
/* feature control bits */
#define CONTROL_IOMMU_EN 0
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index e64e6da08a5f7..49587eafc0a8f 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -883,10 +883,40 @@ static void amd_iommu_report_page_fault(struct amd_iommu *iommu,
pci_dev_put(pdev);
}
+static void amd_iommu_report_ppr_err(struct amd_iommu *iommu, volatile u32 *event,
+ u16 devid, u64 address, int flags)
+{
+ struct pci_dev *pdev;
+ struct device *dev = iommu->iommu.dev;
+ u32 pasid = PPR_PASID(*((u64 *)event));
+ int tag = event[1] & 0x03FF;
+
+ dev_err(dev, "Event logged [INVALID_PPR_REQUEST device=%04x:%02x:%02x.%x pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
+ iommu->pci_seg->id, PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ pasid, address, flags, tag);
+
+ /* Skip COMPLETE_PPR_REQUEST response if RX=1 */
+ if (flags & EVENT_FLAG_PPR_RX)
+ return;
+
+ pdev = pci_get_domain_bus_and_slot(iommu->pci_seg->id, PCI_BUS_NUM(devid),
+ devid & 0xff);
+ if (!pdev)
+ return;
+
+ if (!dev_iommu_priv_get(&pdev->dev)) {
+ pci_dev_put(pdev);
+ return;
+ }
+
+ amd_iommu_complete_ppr(&pdev->dev, pasid, IOMMU_PAGE_RESP_FAILURE, tag);
+ pci_dev_put(pdev);
+}
+
static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
{
struct device *dev = iommu->iommu.dev;
- int type, devid, flags, tag;
+ int type, devid, flags;
volatile u32 *event = __evt;
int count = 0;
u64 address, ctrl;
@@ -960,11 +990,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
amd_iommu_report_rmp_hw_error(iommu, event);
break;
case EVENT_TYPE_INV_PPR_REQ:
- pasid = PPR_PASID(*((u64 *)__evt));
- tag = event[1] & 0x03FF;
- dev_err(dev, "Event logged [INVALID_PPR_REQUEST device=%04x:%02x:%02x.%x pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
- iommu->pci_seg->id, PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- pasid, address, flags, tag);
+ amd_iommu_report_ppr_err(iommu, event, devid, address, flags);
break;
default:
dev_err(dev, "Event logged [UNKNOWN event[0]=0x%08x event[1]=0x%08x event[2]=0x%08x event[3]=0x%08x\n",
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] wifi: mt76: set the EOSP bit in the QoS header of the last released frame
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (89 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] iommu/amd: Fix missing CMD_COMPLETE_PPR response for invalid PPR requests Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: fix debounce register selection Sasha Levin
` (425 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Felix Fietkau, Sasha Levin, lorenzo, ryder.lee, matthias.bgg,
angelogioacchino.delregno, linux-wireless, linux-kernel,
linux-arm-kernel, linux-mediatek
From: Felix Fietkau <nbd@nbd.name>
[ Upstream commit 0b8d2524716099ea4743fa65bc364f94b3106a31 ]
When the driver implements .release_buffered_frames, mac80211 leaves the
U-APSD signalling entirely to the driver: "In this case it is also
responsible for setting the EOSP flag in the QoS header of the frames"
(include/net/mac80211.h). Only IEEE80211_TX_STATUS_EOSP was being set,
which merely ends the service period inside mac80211, so on air the
service period was never terminated. Clients that wait for EOSP before
going back to doze keep the SP open and stop triggering, which stalls all
downlink traffic for that station.
Set the wire EOSP bit on the last frame of a U-APSD service period.
EOSP has no meaning for a PS-Poll response, so pass the release reason
down and leave those frames alone.
Link: https://patch.msgid.link/20260801145334.1166751-4-nbd@nbd.name
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a real U-APSD protocol bug in mt76 that already exists in this
5.15.221 tree. The fix is small, applies here, and is independent of the
rest of the series.
## Phase 1: Commit message forensics
**Step 1.1 — subject**
Record: `[wifi: mt76:]` `[set]` set the EOSP bit in the QoS header of
the last released frame. “Set” here is a protocol-correctness fix, not a
feature add.
**Step 1.2 — tags**
Record:
- `Link: https://patch.msgid.link/20260801145334.1166751-4-nbd@nbd.name`
(linux-wireless, series 04/10)
- `Signed-off-by: Felix Fietkau <nbd@nbd.name>` (mt76 maintainer; Sasha
Levin SOB ignored per instructions)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Cc:
stable` (absence is expected)
Mainline SHA (from `origin/master`, path-limited log):
`0b8d2524716099ea4743fa65bc364f94b3106a31`. First containing tag:
`v7.3-rc1`. Not an ancestor of this HEAD.
**Step 1.3 — body**
Record:
- **Bug:** `.release_buffered_frames` means mac80211 does not set the
on-air EOSP bit; the driver must. mt76 only set
`IEEE80211_TX_STATUS_EOSP` (ends the SP inside mac80211).
- **Symptom:** U-APSD clients that wait for EOSP never see it, keep the
service period open, stop triggering, **all downlink for that STA
stalls**.
- **Root cause:** missing `IEEE80211_QOS_CTL_EOSP` on the last QoS frame
of a U-APSD SP. PS-Poll must not get EOSP.
- **Version info:** none in the message. Buggy code dates to 2017.
**Step 1.4 — hidden fix?**
Record: Not hidden. Explicit protocol/connectivity fix.
## Phase 2: Diff analysis
**Step 2.1 — inventory**
Record:
- File: `drivers/net/wireless/mediatek/mt76/tx.c` (`+12 / -4`)
- Functions: `mt76_queue_ps_skb`, `mt76_release_buffered_frames`
- Scope: single-file surgical change. `mt76_queue_ps_skb` is static;
exported `mt76_release_buffered_frames` signature already has
`reason`.
**Step 2.2 — flow**
Record:
- Before: last PS-release frame gets `IEEE80211_TX_STATUS_EOSP |
IEEE80211_TX_CTL_REQ_TX_STATUS` and More Data cleared. QoS Control on
the wire is untouched.
- After: same flags, plus if `reason == IEEE80211_FRAME_RELEASE_UAPSD`
and the frame is QoS data, OR `IEEE80211_QOS_CTL_EOSP` into the QoS
control field. `reason` is passed through both call sites.
- Path: U-APSD/PS-Poll release via `.release_buffered_frames`, not the
normal TX burst path.
**Step 2.3 — bug mechanism**
Record: **Logic / protocol correctness.** mac80211’s own release path
(`net/mac80211/sta_info.c`) does `*qoshdr |= IEEE80211_QOS_CTL_EOSP` for
U-APSD. Drivers that implement `.release_buffered_frames` must do the
same (`include/net/mac80211.h`). mt76 did not.
**Step 2.4 — quality**
Record: Obviously correct and aligned with mac80211. Guards match the
docs (U-APSD only; QoS data only). skb is exclusively owned after
`ieee80211_tx_dequeue`. Header at `skb->data` matches existing
`mt76_skb_set_moredata()`. Regression risk is low: PS-Poll unchanged;
non-QoS last frames still lack wire EOSP (mac80211 already assumes
drivers mostly buffer QoS-data, or add a QoS-Null themselves). Pre-
existing unused `more_data` parameter is not changed.
## Phase 3: Git history
**Step 3.1 — blame**
Record: `mt76_queue_ps_skb` / `mt76_release_buffered_frames` introduced
in `17f1de56df0512` (“mt76: add common code…”, 2017-12-07,
**v4.16-rc1**). `IEEE80211_TX_STATUS_EOSP` added in `7267a7965dd7b`
(2018). Present for the entire 5.15 lifetime.
**Step 3.2 — Fixes: tag**
Record: None. Introducer is `17f1de56df0512`, which **is** in this tree.
**Step 3.3 — related file history**
Record: Recent 5.15 `tx.c` work is unrelated (locking, UAF, queue id).
This tree already has U-APSD AP support: `b807b368c4f9b` (mt76 AP
U-APSD), `4bf04d33f5b7e` (mt7915). No earlier EOSP-on-wire fix.
**Step 3.4 — author**
Record: Felix Fietkau is listed in `MAINTAINERS` as mt76 maintainer.
Sibling series patch 05 (`697badc27a9b3`, mt7603 U-APSD termination) is
a separate chip-specific fix, not a prerequisite.
**Step 3.5 — prerequisites**
Record: Series is **01–10**, but 04 does **not** depend on 01–03. Patch
01 (`a547b414bf7ea`) changes `mt76_txq_send_burst` / HW TIM buffering
and does not touch `mt76_queue_ps_skb`. 02/03/09/10 are
mt7915/mt7996/MLO (mt7996 is not in 5.15). 05–08 are mt7603-only. 04 is
standalone. All helpers used (`ieee80211_is_data_qos`,
`ieee80211_get_qos_ctl`, `IEEE80211_QOS_CTL_EOSP`,
`IEEE80211_FRAME_RELEASE_UAPSD`) exist in this tree via `mt76.h` →
`<net/mac80211.h>` / `ieee80211.h`.
## Phase 4: Mailing list / external
**Step 4.1 — original discussion**
Record: `b4 dig -c 0b8d252471609` →
https://patch.msgid.link/20260801145334.1166751-4-nbd@nbd.name
`b4 dig -a`: single **v1** series, 2026-08-01. Applied version is that
v1. Thread has the 10 patches plus a kernel-test-robot build error on
**10/10** (`ieee80211_txq_aql_pending` / patch 01), **not** on 04. No
NAK, no reviewer concern about EOSP. Merged via `wireless-
next-2026-08-06` into `v7.3-rc1`.
**Step 4.2 — recipients (`b4 dig -w`)**
Record: Felix Fietkau, `linux-wireless@vger.kernel.org`. Maintainer-
authored self-merge; no extra Reviewed-by. Normal for mt76.
**Step 4.3 — bug report**
Record: No syzbot/bugzilla. The series commit messages describe a
concrete on-air failure (clients waiting for EOSP). Unverified: no
public user stack trace beyond the author’s analysis.
**Step 4.4 — series context**
Record: 04 is the common-path EOSP fix. 05 is the mt7603 driver-PS-queue
analogue. Taking 04 without 05 still fixes mac80211-buffered frames on
**all** chips that use `mt76_release_buffered_frames` (mt76x0/x2,
mt7615, mt7915, mt7921, and mt7603’s fallback).
**Step 4.5 — stable list**
Record: `lore.kernel.org/stable/?q=mt76+EOSP+QoS` → **No results
found**. No recorded reason to skip it.
## Phase 5: Semantic / call graph
**Step 5.1 — functions**
Record: `mt76_queue_ps_skb`, `mt76_release_buffered_frames`.
**Step 5.2 — callers**
Record: `mt76_queue_ps_skb` only from `mt76_release_buffered_frames`.
That is `.release_buffered_frames` for mt76x0, mt76x2, mt7615, mt7915,
mt7921; mt7603 wraps it after draining `msta->psq`. mac80211 calls it
from `ieee80211_sta_ps_deliver_response()` →
`drv_release_buffered_frames()`.
**Step 5.3 — callees**
Record: `IEEE80211_SKB_CB`, `ieee80211_is_data_qos`,
`ieee80211_get_qos_ctl`, `mt76_skb_set_moredata`, `__mt76_tx_queue_skb`.
No new locks/allocs.
**Step 5.4 — reachability**
Record: Yes, from the air. AP RX of a U-APSD trigger
(`ieee80211_sta_uapsd_trigger` in `mac80211.c` / `rx.c`) →
`ieee80211_sta_ps_deliver_uapsd` → driver release. This tree sets
`WIPHY_FLAG_AP_UAPSD`. Typical trigger: a phone associated to an mt76
AP.
**Step 5.5 — similar patterns**
Record: mac80211 `sta_info.c` uses the same `*qoshdr |=
IEEE80211_QOS_CTL_EOSP`. Sibling mt7603 patch 05 does the same for TXD-
prefixed PS-queue frames (`skb->data[MT_TXD_SIZE]`). Common-path frames
from `ieee80211_tx_dequeue` have the 802.11 header at `skb->data` (same
as `mt76_skb_set_moredata`).
## Phase 6: This tree (5.15.221)
**Step 6.1 — buggy code present?**
Record: **Yes.** `drivers/net/wireless/mediatek/mt76/tx.c`
`mt76_queue_ps_skb()` (lines 344–358) sets only
`IEEE80211_TX_STATUS_EOSP`, not the QoS EOSP bit. Introduced v4.16;
U-APSD AP enabled here since 2020.
`git describe HEAD`: `p-5.15-2-g6703e5d2f3a29`. `make kernelversion`:
**5.15.221**. `git merge-base --is-ancestor 0b8d252471609 HEAD` → **not
present**.
**Step 6.2 — backport difficulty**
Record: **Clean apply.** `git apply --check` succeeded; hunks applied at
offset −69 only because `mt76_txq_dequeue` still uses
`MT_TX_HW_QUEUE_EXT_PHY` here vs `FIELD_PREP(MT_TX_HW_QUEUE_PHY, …)`
upstream. That function is context, not part of the change.
**Step 6.3 — related fixes already here?**
Record: No. Only `7267a7965dd7b` (TX status for the software EOSP flag),
which is exactly the incomplete behavior this commit finishes.
## Phase 7: Subsystem
**Step 7.1**
Record: `drivers/net/wireless/mediatek/mt76` — Wi-Fi driver.
**IMPORTANT** (not core kernel, but widely used: OpenWrt/home routers,
mt76x0/x2/7603/7615/7915/7921).
**Step 7.2**
Record: Mature driver; this PS-release path has been stable since 2017.
Not a bug in brand-new code.
## Phase 8: Impact and risk
**Step 8.1 — who**
Record: Driver/config-specific: `CONFIG_MT76*` AP mode with U-APSD
clients. Large real-world set (MediaTek AP SoCs).
**Step 8.2 — trigger**
Record: Associated STA in power-save using U-APSD (typical phones) sends
a trigger; AP releases buffered QoS data. Not a rare error path.
Unprivileged on the air (associated client). PS-Poll-only clients are
unaffected by the new bit.
**Step 8.3 — failure mode**
Record: **Station downlink stall** until the client gives up the SP. Not
a kernel oops. Severity: **HIGH** (loss of connectivity for that STA),
not CRITICAL (no panic/corruption).
**Step 8.4 — risk/benefit**
Record: Benefit high for mt76 AP + U-APSD clients. Risk very low: ~12
lines, QoS bit only on last U-APSD QoS-data frame, same pattern as
mac80211, clean apply, no API/struct change. Patch 01’s
`ieee80211_txq_aql_pending` is **not** required.
## Phase 9: Synthesis
**Step 9.1 — evidence**
For:
- Real, documented 802.11 bug: missing on-air EOSP → downlink stall
- Code and AP U-APSD flag exist in 5.15.221
- Bug since v4.16
- Maintainer-authored, merged to mainline (`v7.3-rc1`), no revert, no
later rewrite of this function
- 12 insertions / 4 deletions, clean apply
- Matches mac80211
- Standalone despite 04/10 numbering
Against:
- Not crash/security/corruption
- No `Reported-by` / syzbot
- No extra reviewer
- mt7603 hardware PS-queue still wrong without patch 05 (does not make
04 incorrect or unusable)
Unresolved: no independent end-user report found beyond the maintainer’s
analysis.
**Step 9.2 — stable rules**
1. Obviously correct and tested? **PASS** — same as mac80211; in
mainline since v7.3-rc1
2. Real bug affecting users? **PASS** — U-APSD clients on mt76 APs
3. Important? **PASS** — full downlink stall for the STA (HIGH)
4. Small/contained? **PASS** — one file, ~12 lines
5. No new features/APIs? **PASS** — sets a standard 802.11 bit the
driver was already required to set
6. Applies to this tree? **PASS** — `git apply --check` clean
**Step 9.3 — exceptions**
Record: None (not an ID/quirk/DT/build/doc exception). Qualifies as a
normal bugfix.
**Step 9.4 — decision**
This 5.15.221 tree has the buggy path, U-APSD AP support, and every API
the patch needs. The change is a small, self-contained protocol fix for
a serious AP-mode connectivity failure. It should be backported here.
---
### What it solves for 5.15 users
On MediaTek mt76 APs, U-APSD service periods never get the EOSP bit on
the last released QoS frame. mac80211 thinks the SP ended
(`IEEE80211_TX_STATUS_EOSP`), but the client never sees EOSP on the air,
stops triggering, and **downlink to that station stalls**. Setting
`IEEE80211_QOS_CTL_EOSP` on the last U-APSD QoS-data frame is what
mac80211 already documents and implements when the driver does not take
`.release_buffered_frames`.
### Stable rules / risk
Meets all six criteria. Benefit is restoring buffered downlink for
U-APSD clients; risk is a one-bit header update on a path that already
rewrites More Data. No series dependencies for this hunk. mt7603’s
separate PS-queue EOSP bug is a sibling, not a blocker.
### Verification
- [Phase 1] Parsed tags: Link to 04/10, author SOB only; no
Fixes/Reported-by/Cc:stable
- [Phase 1] `git log origin/master --grep='set the EOSP bit' --
drivers/net/wireless/mediatek/mt76/`: `0b8d252471609`
- [Phase 1] `git describe --contains --match 'v*' 0b8d252471609`:
`v7.3-rc1~133^2~99^2~15^2~8`
- [Phase 2] Diff: `mt76_queue_ps_skb` + `reason`; EOSP OR on last U-APSD
QoS-data frame; two call sites
- [Phase 2] Compared to `net/mac80211/sta_info.c:1708` (`*qoshdr |=
IEEE80211_QOS_CTL_EOSP`) — same mechanism
- [Phase 2] Confirmed `include/net/mac80211.h` requires the driver to
set EOSP when `.release_buffered_frames` is implemented
- [Phase 3] `git blame` on `tx.c` 345–403: introduced `17f1de56df0512`
(v4.16-rc1)
- [Phase 3] `git log --grep='EOSP' --
drivers/net/wireless/mediatek/mt76/`: only TX-status EOSP
(`7267a7965dd7b`) in this tree
- [Phase 3] Patch 01 `a547b414bf7ea` does not touch `mt76_queue_ps_skb`
(not a prerequisite)
- [Phase 4] `b4 dig -c 0b8d252471609`: lore URL above; `b4 dig -a`: v1
only; `b4 dig -w`: linux-wireless + author
- [Phase 4] 11-message mbox: no NAK on 04; kbuild error is on 10/10 /
patch 01
- [Phase 4] `curl` stable lore for `mt76 EOSP QoS`: no results
- [Phase 5] Callers: mt76x0/x2, mt7615, mt7915, mt7921 ops; mt7603
wrapper; mac80211 `drv_release_buffered_frames`
- [Phase 5] This tree: `WIPHY_FLAG_AP_UAPSD` and
`ieee80211_sta_uapsd_trigger` in `mt76/mac80211.c`
- [Phase 6] `git describe HEAD`: `p-5.15-2-g6703e5d2f3a29`; `make
kernelversion`: 5.15.221
- [Phase 6] `git merge-base --is-ancestor 0b8d252471609 HEAD`: not in
tree
- [Phase 6] `git apply --check` of 04/10: success, offset −69
- [Phase 6] APIs present: `IEEE80211_QOS_CTL_EOSP` `0x0010`,
`ieee80211_get_qos_ctl`, `ieee80211_is_data_qos`,
`IEEE80211_FRAME_RELEASE_UAPSD`
- [Phase 8] Failure mode: STA downlink stall (HIGH), not oops
- UNVERIFIED: no independent user bugzilla/syzbot report; impact
inferred from protocol + maintainer description
**YES**
drivers/net/wireless/mediatek/mt76/tx.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 731caeda72b52..93275bb692fa5 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -415,16 +415,23 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq)
static void
mt76_queue_ps_skb(struct mt76_phy *phy, struct ieee80211_sta *sta,
- struct sk_buff *skb, bool last)
+ struct sk_buff *skb, bool last,
+ enum ieee80211_frame_release_type reason)
{
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
- if (last)
+ if (last) {
info->flags |= IEEE80211_TX_STATUS_EOSP |
IEEE80211_TX_CTL_REQ_TX_STATUS;
+ if (reason == IEEE80211_FRAME_RELEASE_UAPSD &&
+ ieee80211_is_data_qos(hdr->frame_control))
+ *ieee80211_get_qos_ctl(hdr) |= IEEE80211_QOS_CTL_EOSP;
+ }
+
mt76_skb_set_moredata(skb, !last);
__mt76_tx_queue_skb(phy, MT_TXQ_PSD, skb, wcid, sta, NULL);
}
@@ -457,14 +464,15 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
nframes--;
if (last_skb)
- mt76_queue_ps_skb(phy, sta, last_skb, false);
+ mt76_queue_ps_skb(phy, sta, last_skb, false,
+ reason);
last_skb = skb;
} while (nframes);
}
if (last_skb) {
- mt76_queue_ps_skb(phy, sta, last_skb, true);
+ mt76_queue_ps_skb(phy, sta, last_skb, true, reason);
dev->queue_ops->kick(dev, hwq);
} else {
ieee80211_sta_eosp(sta);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: fix debounce register selection
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (90 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] wifi: mt76: set the EOSP bit in the QoS header of the last released frame Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] exfat: write moved entry before removing source Sasha Levin
` (424 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Tomer Maimon, Linus Walleij, Sasha Levin, andrew, avifishman70,
tali.perry1, openbmc, linux-gpio, linux-kernel
From: Tomer Maimon <tmaimon77@gmail.com>
[ Upstream commit 602ee6c9447e4382c7e145b26a1c940813f2a144 ]
Each DBNCS register programs debounce source selection for 16 GPIOs.
The current offset calculation advances the register address every four
GPIOs, so offsets 4-15 and 20-31 end up touching the wrong selector
register.
Advance the DBNCS offset per 16 GPIOs so each line uses the debounce
selector bank that matches the hardware layout.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is **v7.3-rc4** (mainline 7.3.0-rc4). The candidate
is a one-line DBNCS offset fix in the Nuvoton NPCM8XX pinctrl driver;
the buggy formula has been in this file since the driver landed in v6.7.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[pinctrl/npcm8xx] [fix] [debounce DBNCS register offset is
wrong for most GPIOs in a bank]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Tomer Maimon \<tmaimon77@gmail.com\> (author; original
NPCM8XX pinctrl driver author)
- Signed-off-by: Linus Walleij \<linusw@kernel.org\> (pinctrl
maintainer; applied the patch)
- No Fixes:, Reported-by, Tested-by, Reviewed-by, Acked-by, Link:, or
Cc: stable (absence of Fixes/Cc:stable is expected for this review)
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Each DBNCS register selects debounce source for 16 GPIOs. The
driver advanced the register pointer every four GPIOs (`gpio / 4`
bytes).
- **Symptom:** GPIOs 4–15 and 20–31 program the wrong selector register
(and, for most of those, an unaligned address).
- **Root cause:** Integer-division “simplification”: `(gpio / 16) * 4`
is not `gpio / 4`.
- **Version info:** None in the message. Driver introduced in v6.7-rc1.
- **Failure mode:** Hardware debounce source is programmed into the
wrong MMIO location.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. Subject and body describe a register-
selection bug. The 2022 pre-merge driver used `gpio / 16` with a `* 4`
stride; mainline shipped the broken `gpio / 4` form.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` (+2/−1)
- Function: `debounce_timing_setting()`
- Scope: single-file surgical fix (one expression)
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Hardware: `NPCM8XX_GP_N_DBNCS0` at 0x80, `DBNCS1` at 0x84; 2 bits per
GPIO; 16 GPIOs per 32-bit register. Bit index `(gpio % 16) * 2` was
already correct.
- Before: `base + 0x80 + (gpio / 4)`
- gpio 0–3: 0x80 (DBNCS0, aligned)
- gpio 4–7: 0x81, 8–11: 0x82, 12–15: 0x83 (unaligned, inside DBNCS0)
- gpio 16–19: 0x84 (DBNCS1, accidentally correct)
- gpio 20–31: 0x85–0x87 (unaligned; 32-bit RMW can overlap DBNCP0 at
0x88)
- After: `base + 0x80 + (gpio / 16) * 4` → 0x80 for 0–15, 0x84 for
16–31.
- Path: pinconf set of `PIN_CONFIG_INPUT_DEBOUNCE` only (not a
probe/error-path change).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Logic / hardware programming]** Wrong MMIO offset. Matches
the bit-field layout already in the same function. `npcm_gpio_set()`
does `iowrite32(ioread32(reg) | pinmask, reg)` on that pointer.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct against DBNCS0/DBNCS1 at 0x80/0x84 and `(gpio
% 16) * 2`. Minimal. Regression risk is very low: only the register
address changes; GPIOs 0–3 and 16–19 keep the same address.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Buggy line introduced in **acf4884a57170** (“pinctrl: nuvoton:
add NPCM8XX pinctrl and GPIO driver”, Tomer Maimon, 2023-09-11),
contained in **v6.7-rc1**. Present until 602ee6c9447e4.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Bug is in the original driver merge, not a later
regression.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same-author series merged via `pinctrl-v7.3-1` (drop RTS/CTS,
RMII, RG2 drive strength, pending GPIO events, IRQ setup, pin flags,
this debounce fix). This hunk does not depend on those other patches.
Only other debounce commit on this path is the original driver add.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Tomer Maimon is the Nuvoton/NPCM pinctrl author. Linus Walleij
applied the series. Recent npcm8xx work is a mix of pin-map corrections
and one feature (RG2 drive strength). This commit is the debounce
correctness fix.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. Uses `NPCM8XX_GP_N_DBNCS0` and
`debounce_timing_setting()` as they existed at driver introduction. No
new helpers or struct fields.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 602ee6c9447e4` →
https://patch.msgid.link/20260715122923.1938327-9-tmaimon77@gmail.com
- Subject: `[PATCH v1 8/8] pinctrl: npcm8xx: fix debounce register
selection` (2026-07-15)
- `b4 dig -a`: only **v1**; applied version matches v1
- lore.kernel.org fetches returned **403**; patch text confirmed via
LKML/openwall mirrors. No replies were visible on those mirror pages.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): linusw@kernel.org, brgl@kernel.org,
andrew@codeconstruct.com.au, linux-gpio, openbmc, Nuvoton/Google BMC
CCs. No Reviewed-by on the commit; maintainer SOB is Linus Walleij.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by, bugzilla, or syzbot link. Author-found hardware
mapping error.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Patch 8/8 of an npcm8xx pin/group cleanup series. Other patches
change groups, IRQ setup, or add RG2 drive strength. This offset change
does not require them. Pre-merge 2022 v2 driver used `int DBNCS_offset =
gpio / 16` and `DBNCS0 + (DBNCS_offset * 4)` — the correct formula this
commit restores.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search was not usable (403). No evidence
this was discussed on stable@ from the mirrors that did load.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `debounce_timing_setting()` only.
**Step 5.2: TRACE CALLERS**
Record:
- `debounce_timing_setting()` ← `npcm_set_debounce()` ←
`npcm8xx_config_set_one()` on `PIN_CONFIG_INPUT_DEBOUNCE` ←
`npcm8xx_config_set()` (`pinconf_ops.pin_config_set`)
- DT generic pinconf maps `input-debounce` to that param (`pinconf-
generic.c`).
- **GPIO cdev debounce does not hit this path here:**
`gpio_generic_chip_init()` does not set `gc->set_config`, and this
driver never assigns `gpiochip_generic_config`. `gpio_do_set_config()`
returns `-ENOTSUPP`; gpiolib-cdev then uses software debounce.
**Step 5.3: TRACE CALLEES**
Record: `npcm_gpio_set()` (32-bit RMW), `iowrite32` of DBNCPx period
registers, `DIV_ROUND_CLOSEST` for custom periods.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable when a pinctrl state applies `input-debounce` (boot DT
or pin_config_set). No in-tree dts/dtsi uses `input-debounce`
(verified). OpenBMC board DTs are often out of tree. Not a syscall hot
path on this driver as wired today.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: npcm7xx has PIN_CONFIG_INPUT_DEBOUNCE cases but no DBNCS
registers (NPCM8XX-specific adjustable debounce). No sibling copy of
this bug.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` is present.
Pre-image at 602ee6c9447e4^ is `+ (gpio / 4)`. Bug since v6.7. This
checkout already contains the fix (expected for a mainline candidate
tree). `PINCTRL_NPCM8XX` depends on `ARCH_NPCM || COMPILE_TEST`.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply on the debounce formula. Surrounding gpio-generic
API churn does not affect this one line. Expected backport difficulty:
**clean apply** on any tree that still has `(gpio / 4)` in
`debounce_timing_setting`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier debounce-offset fix. `git log --grep=debounce --
drivers/pinctrl/nuvoton/` only shows the original add and this commit.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **[pinctrl / Nuvoton NPCM8XX GPIO] [PERIPHERAL]** — Arbel BMC
(ARM64 Cortex-A35), used on OpenBMC server BMCs. Not core mm/fs/net.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature driver (v6.7), recent concentrated npcm8xx pin-map/IRQ
fixes in the 7.3 pinctrl pull. Debounce math had been unchanged since
introduction.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Platform-specific:** NPCM8XX BMC boards that set pinctrl
`input-debounce`. Not universal. No in-tree DT consumers found.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Applying hardware debounce via pinconf. Not every boot unless DT
requests it. Unprivileged GPIO debounce ioctl does **not** reach this
function on this driver (no `set_config`). Privilege/DT-dependent.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Primary (author): wrong DBNCS register → debounce source not applied
to the intended line; possible corruption of neighboring DBNCS/DBNCP
fields via unaligned 32-bit RMW.
- Unaligned `ioread32`/`iowrite32` on ARM64 Device mappings *can*
alignment-fault; **no crash was reported**. Treat crash as possible,
not verified.
- Severity: **MEDIUM** for functional debounce / adjacent-register
corruption on this SoC; not a demonstrated panic/UAF/security hole.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Makes hardware debounce match the documented 16-GPIO
DBNCS banks for NPCM8XX users who enable it.
- **Risk:** Very low (one address expression; GPIOs that already hit
0x80/0x84 unchanged).
- **Ratio:** Favorable. Small correctness fix, not a feature.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR backporting:
- Real hardware programming bug, present since the driver was added
(v6.7).
- Restores the mapping the author’s 2022 submission already used (`gpio
/ 16` × 4-byte stride).
- Matches DBNCS0/DBNCS1 at 0x80/0x84 and the existing `(gpio % 16) * 2`
bit layout.
- 3-line, single-function, no API/feature change.
- Author is the driver writer; pinctrl maintainer applied it.
- Standalone; other 8/8 series patches not required.
- Applies on this tree’s pre-image without surrounding refactor.
AGAINST:
- Peripheral BMC pinctrl, not a core crash/security/corruption class as
described.
- No Fixes/Cc:stable, no Reported-by/Tested-by (tags not required, but
no field report).
- No in-tree `input-debounce` DT users; GPIO cdev debounce does not call
this code.
- Series also contains non-stable material (e.g. RG2 drive strength);
this patch itself is independent.
UNRESOLVED:
- Full lore thread (reviews/NAKs) unverified due to lore 403.
- Whether any OpenBMC DT actually sets `input-debounce` (not in this
tree).
- Whether unaligned MMIO actually oopses on NPCM8XX (not reported).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — formula matches register
layout; maintainer applied. No extra Tested-by.
2. Fixes a real bug that affects users? **PASS** — wrong DBNCS bank for
24/32 lines per bank when hardware debounce is configured.
3. Important issue (crash, security, corruption, deadlock)? **PASS**
(borderline) — wrong MMIO and possible adjacent-register RMW; not a
documented oops. Still a hardware-feature break on a production BMC
SoC, which stable routinely takes in pinctrl/gpio.
4. Small and contained? **PASS** — +2/−1, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — same file/function; pre-image
is the buggy line.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary small
driver correctness fix.
**Step 9.4: MAKE YOUR DECISION**
This tree has the NPCM8XX driver and the long-standing `gpio / 4` bug.
The patch is a minimal, obviously correct register-index fix with no
dependencies. Benefit is limited to NPCM8XX debounce configuration, but
the risk of taking it is negligible and the bug is real. That meets
stable criteria for this checkout.
------------------------------------------------
What the commit solves, for stable users
------------------------------------------------
Hardware debounce on NPCM8XX is supposed to use DBNCS0 for GPIOs 0–15
and DBNCS1 for 16–31. Integer division turned `(gpio / 16) * 4` into
`gpio / 4`, so most lines wrote the wrong (often unaligned) address.
Boards that set pinctrl `input-debounce` would not get the intended
debounce source and could disturb neighboring debounce-period registers.
The fix is one address expression.
Risk vs benefit: very low risk, modest but real benefit for NPCM8XX BMC
GPIO debounce. No series dependencies.
Verification:
- [Phase 1] Parsed commit 602ee6c9447e4: SOB Tomer Maimon + Linus
Walleij; no Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: one expression in `debounce_timing_setting()`;
DBNCS0=0x80, DBNCS1=0x84 confirmed in this file
- [Phase 2] `npcm_gpio_set()` is 32-bit RMW at the computed pointer
(lines 124–129)
- [Phase 3] `git blame` on parent: acf4884a57170 (v6.7-rc1) introduced
`(gpio / 4)`
- [Phase 3] `git merge-base --is-ancestor acf4884a57170 HEAD` → yes; fix
is ancestor of HEAD
- [Phase 3] `git log --grep=debounce -- drivers/pinctrl/nuvoton/` → only
driver add + this fix
- [Phase 4] `b4 dig -c 602ee6c9447e4` → msgid 20260715122923.1938327-9;
v1 8/8; recipients linusw, brgl, openbmc
- [Phase 4] Pre-merge 2022 v2 used `gpio / 16` and `* 4`
(lists.ozlabs.org OpenBMC archive)
- [Phase 4] lore.kernel.org 403 — full review thread UNVERIFIED;
LKML/openwall showed the patch text only
- [Phase 5] Callers: `npcm_set_debounce` ← `npcm8xx_config_set_one`
PIN_CONFIG_INPUT_DEBOUNCE
- [Phase 5] This driver has no `gc->set_config`; GPIO cdev debounce does
not reach this function
- [Phase 5] `rg input-debounce` on dts/dtsi: no matches
- [Phase 6] `git describe HEAD` → v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` → 7.3.0-rc4
- [Phase 6] Parent of fix still has `(gpio / 4)`; apply is clean
- [Phase 8] Failure mode: wrong debounce MMIO; crash via unaligned
access UNVERIFIED
- UNVERIFIED: OpenBMC out-of-tree DT debounce use; stable@ discussion;
review NAKs
**YES**
drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 22cc87d43ea69..28464463ff833 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -2135,7 +2135,8 @@ static const struct pinmux_ops npcm8xx_pinmux_ops = {
static int debounce_timing_setting(struct npcm8xx_gpio *bank, u32 gpio,
u32 nanosecs)
{
- void __iomem *DBNCS_offset = bank->base + NPCM8XX_GP_N_DBNCS0 + (gpio / 4);
+ void __iomem *DBNCS_offset = bank->base + NPCM8XX_GP_N_DBNCS0 +
+ (gpio / 16) * 4;
int gpio_debounce = (gpio % 16) * 2, debounce_select, i;
u32 dbncp_val, dbncp_val_mod;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] exfat: write moved entry before removing source
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (91 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: fix debounce register selection Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] usb: fsl_qe_udc: check qe_alloc_request() failure in ch9getstatus() Sasha Levin
` (423 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Yichong Chen, Namjae Jeon, Sasha Levin, sj1557.seo, exfat,
linux-kernel
From: Yichong Chen <chenyichong@uniontech.com>
[ Upstream commit 896fcc93574fd511ee04a4110e8ea59d6d8d43d7 ]
exfat_move_file() removes the old directory entry before the new entry
has been written. If writing the new entry fails, rename returns an
error after the source entry has already been marked deleted.
Write the new entry first, then remove the old entry and update the
cached inode location. This keeps the source entry intact if creating
the destination entry fails.
Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This commit is a small filesystem data-loss fix: cross-directory rename
deleted the source before the destination write succeeded. Local tree is
**7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`); the change is already in
this history as `896fcc93574fd` (v7.3-rc1). The question is whether it
is technically worth sending to stable.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[exfat]** **[write … before]** write the destination directory
entry before removing the source during a move.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Yichong Chen <chenyichong@uniontech.com>` (author)
- `Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>` (exFAT
maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, `Link:`, or `Cc: stable`
- Absence of `Fixes:` / `Cc: stable` is expected for this review and is
not a negative signal
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `exfat_move_file()` marks the old directory entry deleted
before the new entry is written.
- **Symptom:** A failed destination write still returns an error from
rename, but the source is already gone.
- **Root cause:** Wrong operation order (remove source, then
`exfat_put_dentry_set()` of the new set).
- **Fix:** Write the new entry first; only then remove the old entry and
update the cached inode location.
- **Version info:** None in the message. Git: landed in v7.3-rc1; author
date 2026-07-27.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. The message describes a real rename
error-path data-loss bug.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `fs/exfat/namei.c` only (`5` insertions, `5` deletions)
- Function: `exfat_move_file()`
- Scope: single-file surgical reorder of existing statements; no new
helpers or APIs
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record: **Before** (parent of `896fcc93574fd`):
1. Copy file/stream entries into the new set and call
`exfat_init_ext_entry()`
2. `exfat_remove_entries()` on the source (`mov_es`)
3. Update `ei->dir` / `ei->entry` to the destination
4. `exfat_put_dentry_set(&new_es, …)` to write the destination
5. On failure: best-effort delete of the *new* entries, then `goto
put_mov_es` (source already deleted in memory)
**After:** steps 4 then 2–3. Destination write is attempted first. On
failure the source is still intact; only the incomplete destination is
cleaned up.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** logic/correctness; filesystem metadata loss on I/O error
- **Mechanism:** `exfat_remove_entries()` only marks dentries
`TYPE_DELETED` in the cached set (`dir.c`). Durability happens in
`exfat_put_dentry_set()` → `exfat_update_bhs()`. That returns `-EIO`
when `sync` is set (`IS_DIRSYNC`) and a buffer is not uptodate after
wait. On error, `exfat_put_dentry_set()` `bforget()`s the destination
buffers.
- Combined with `942296784b2a9` (v7.2-rc1), which added “best-effort
delete” of the *new* entries on that failure: source already deleted
**and** destination discarded/deleted → the file can disappear.
- Same-directory `exfat_rename_file()` already wrote the new set before
removing the old one after `942296784b2a9`. Only the cross-directory
path was wrong.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: matches `exfat_rename_file()` and the pre-v6.9
write-then-remove order.
- Minimal: three statements moved, no unrelated edits.
- Residual risk: if the destination write succeeds and the source-delete
write later fails, both names can exist (duplicate entries). That is
better than losing the file. No new locks, APIs, or data structures.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Original 2020 `exfat_move_file()` (`5f2aa075070cf`, v5.7 era) wrote
destination buffers with `exfat_update_bh()` **before**
`exfat_remove_entries()`.
- The inverted order was introduced by `d97e060673906d` (“exfat: convert
exfat_init_ext_entry() to use dentry cache”, contained in
**v6.9-rc1**). That commit batched destination writes into
`exfat_put_dentry_set(&new_es)` but left `exfat_remove_entries()`
*before* that put.
- `942296784b2a9` (v7.2-rc1) added the dest-cleanup error path while
keeping the bad order, making loss complete on that path.
- `896fcc93574fd` (Yichong Chen, 2026-07-27) restores write-then-remove.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The buggy conversion is `d97e060673906d`
(v6.9-rc1), present in this tree (`git merge-base --is-ancestor`
succeeded). `942296784b2a9` is also in this tree.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Immediate predecessor in `fs/exfat/`: `942296784b2a9` (preserve benign
secondary entries; `Cc: stable`)
- Follow-ups by the same author, independent: `ce12a39bed483` (free dir
cluster on zeroing failure), `0901a71e8cff5` (cleanup on
`exfat_add_entry()` write failure)
- Standalone ordering fix, not “patch X/Y”
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Yichong Chen is a recent exFAT contributor (three error-path
fixes in this cycle), not the listed maintainer. Maintainer Namjae Jeon
applied the patch.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- Clean apply of *this* diff assumes `942296784b2a9` (4-arg
`exfat_init_ext_entry()`, `free_benign` on `exfat_remove_entries()`,
best-effort dest delete). Both are in this 7.3 tree.
- The reorder itself does not need new functions. It can stand alone
here.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 896fcc93574fd`: https://patch.msgid.link/20260727091214.355
917-1-chenyichong@uniontech.com
- `b4 dig -a`: **v1 only**, no later revisions
- Thread (mbox): submission + maintainer reply. Namjae Jeon: “Applied it
to #dev.” No NAK, no requested changes.
- lore.kernel.org / patch.msgid.link HTTP fetch returned 403; discussion
recovered via `b4 dig -m` and public mirrors (spinics, LKML, Patchew).
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc Namjae Jeon, Sungjong Seo (maintainers),
Yuezhang Mo (reviewer), `exfat@lists.linux.dev`, `linux-
kernel@vger.kernel.org`. Maintainer applied it; no extra `Reviewed-by`
on the commit.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No `Reported-by` or bugzilla/syzbot link. Bug found by code
inspection of the error path, not a public crash report.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone v1. Related later patches target `exfat_add_entry()`
/ `exfat_alloc_new_dir()`, not this reorder.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No dedicated stable-list discussion of this subject was found.
`942296784b2a9` (prerequisite context) *did* carry `Cc: stable`.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `exfat_move_file()` only.
**Step 5.2: TRACE CALLERS**
Record:
- `exfat_move_file()` ← `__exfat_rename()` when `new_parent_inode !=
old_parent_inode`
- `__exfat_rename()` ← `exfat_rename()` (`inode_operations.rename`)
- Userspace trigger: `rename()` / `mv` across directories on an exFAT
mount
- Same-directory rename uses `exfat_rename_file()`, already ordered
correctly
**Step 5.3: TRACE CALLEES**
Record: `exfat_init_ext_entry()`, `exfat_put_dentry_set()` /
`exfat_update_bhs()`, `exfat_remove_entries()`, `exfat_get_dentry_set()`
on the error path. No allocations or new locks.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable from the rename syscall. Failure of
`exfat_put_dentry_set(&new_es)` is a DIRSYNC/sync write `-EIO`
(`exfat_update_bhs()` only waits when `sync` is set). That is the
`dirsync` mount option or `S_DIRSYNC` on the directory. Unprivileged
users with write access to the volume can hit the path; the I/O-error
half needs a failed dest directory write.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: `exfat_rename_file()` already put the new set, then removed the
old set, after `942296784b2a9`. This commit makes `exfat_move_file()`
match that.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes, in this tree’s history. `d97e060673906d` (v6.9) and
`942296784b2a9` (v7.2) are ancestors of HEAD. Current `fs/exfat/namei.c`
already has the fixed order at `exfat_move_file()` (write new, then
`exfat_remove_entries()`).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: On **this** 7.3-rc4 tree the patch applies (it is already
merged). Context matches `942296784b2a9`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This exact fix is already HEAD-reachable (`git merge-base --is-
ancestor 896fcc93574fd HEAD`). No later revert or competing fix on
`exfat_move_file()`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **exFAT** (`fs/exfat/`). **IMPORTANT** — not VFS core, but a
widely used filesystem (SD cards, USB sticks, Android/Windows
interchange). Metadata loss on rename is user-visible data loss.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained (Namjae Jeon / Sungjong Seo; frequent
7.2–7.3 exFAT pulls). This is a targeted error-path fix, not a drive-by
refactor.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Users of `CONFIG_EXFAT_FS` who cross-directory rename/move.
Default mounts without `dirsync` rarely take the `-EIO` return from
`exfat_put_dentry_set()` (non-sync `exfat_update_bhs()` only dirties
buffers). `dirsync` / `S_DIRSYNC` plus dest write failure is the
concrete fail path.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Cross-directory `rename()` on exFAT
- Destination directory-entry write fails (`IS_DIRSYNC` + I/O error)
- Not a race; sequential error handling
- Unprivileged if they can write the volume
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Source directory entry marked deleted, destination write
discarded (`bforget`), then best-effort delete of dest → **file
disappears / orphaned clusters**. **Severity: CRITICAL** (data loss),
even though the trigger is an I/O error path.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Prevents losing a file when cross-dir rename hits a dest
write error; also stops `942296784b2a9`’s dest-cleanup from deleting
the only remaining name.
- **Risk:** Very low (10-line reorder, same pattern as
`exfat_rename_file()`).
- **Ratio:** High benefit / very low risk.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real filesystem data-loss bug, not style
- Small, obviously correct reorder
- Matches the already-correct `exfat_rename_file()` path
- Bug introduced in v6.9 (`d97e060673906d`); made worse in v7.2
(`942296784b2a9`, which was `Cc: stable`)
- Maintainer applied v1 with no objections
- No new features/APIs; applies in this tree’s code
- Reachable from `rename(2)`
AGAINST:
- No public user report / syzbot / `Fixes:` tag
- Trigger needs DIRSYNC (or equivalent) plus dest I/O error — uncommon
- No `Tested-by`
- This 7.3-rc4 checkout already contains the commit (does not reduce
technical merit for stable)
UNRESOLVED:
- Could not HTTP-fetch lore.kernel.org (403); thread recovered via `b4
dig -m` and mirrors
- No evidence this was discussed on stable@ (search did not turn up this
subject)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — ordering is clearly right;
maintainer applied it. No extra tester tag, but the change is
reviewable from the code.
2. Fixes a real bug that affects users? **PASS** — rename can drop the
source name on dest write failure.
3. Important issue? **PASS** — data loss / missing directory entry.
**CRITICAL**
4. Small and contained? **PASS** — ±5 lines, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — already present; context with
`942296784b2a9` is here
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. It is a normal
important bugfix.
**Step 9.4: MAKE YOUR DECISION**
This is a surgical fix for metadata loss on cross-directory exFAT
rename. The wrong order has been in the dentry-cache path since v6.9 and
became fully destructive with v7.2’s dest-cleanup. Benefit is preventing
file disappearance; regression risk is negligible. It meets stable rules
for this tree’s exFAT code.
Verification:
- [Phase 1] Parsed tags: only author + maintainer SOBs; no
Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: 5+/5- in `exfat_move_file()`; moved
`exfat_remove_entries` + `ei->dir`/`ei->entry` to after successful
`exfat_put_dentry_set(&new_es)`
- [Phase 2] `exfat_put_dentry_set`/`exfat_update_bhs`: `-EIO` only when
`sync` and buffer not uptodate; error path `bforget()`s dest buffers
- [Phase 3] `git describe HEAD` / `make kernelversion`: v7.3-rc4 /
7.3.0-rc4
- [Phase 3] `git show 896fcc93574fd`: commit
`896fcc93574fd511ee04a4110e8ea59d6d8d43d7`
- [Phase 3] `git merge-base --is-ancestor 896fcc93574fd HEAD`: yes
(already in this tree)
- [Phase 3] `git describe --contains 896fcc93574fd`: v7.3-rc1~87^2~6
- [Phase 3] `git merge-base --is-ancestor d97e060673906d HEAD`: yes;
contained in v6.9-rc1 (introduced remove-before-put)
- [Phase 3] `git merge-base --is-ancestor 942296784b2a9 HEAD`: yes;
v7.2-rc1 (dest-cleanup error path)
- [Phase 3] `git blame fs/exfat/namei.c` around the hunk: reorder
attributed to `896fcc93574fd`; dest-cleanup to `942296784b2a9`
- [Phase 3] Original 2020 `exfat_move_file` wrote dest with
`exfat_update_bh` before `exfat_remove_entries`
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 only; maintainers CC’d; Namjae Jeon
applied to #dev; no NAK
- [Phase 4] lore HTTP 403; mbox + Patchew/LKML/spinics confirm the same
thread
- [Phase 4] No stable@ hit for this subject
- [Phase 5] Callers: only `__exfat_rename()` → `exfat_rename()` (VFS
rename), cross-directory only
- [Phase 6] Current `namei.c` already has the fixed order; no later
revert
- [Phase 7] MAINTAINERS: Namjae Jeon, Sungjong Seo; reviewer Yuezhang Mo
- [Phase 8] Failure mode verified in code: source deleted in cache, dest
write failed/forgotten, then dest also removed
- UNVERIFIED: whether any particular older stable series already carried
a handwritten equivalent (not needed for this 7.3 tree)
**YES**
fs/exfat/namei.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index 6b544df0a03a6..06bed867b46ad 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -1156,11 +1156,6 @@ static int exfat_move_file(struct inode *parent_inode,
exfat_init_ext_entry(&new_es, num_new_entries, p_uniname,
&mov_es, num_extra_entries);
- exfat_remove_entries(parent_inode, &mov_es, ES_IDX_FILE, false);
-
- ei->dir = newdir;
- ei->entry = newentry;
-
ret = exfat_put_dentry_set(&new_es, IS_DIRSYNC(parent_inode));
if (ret) {
/* Best-effort delete to avoid duplicate entries */
@@ -1174,6 +1169,11 @@ static int exfat_move_file(struct inode *parent_inode,
goto put_mov_es;
}
+ exfat_remove_entries(parent_inode, &mov_es, ES_IDX_FILE, false);
+
+ ei->dir = newdir;
+ ei->entry = newentry;
+
return exfat_put_dentry_set(&mov_es, IS_DIRSYNC(parent_inode));
put_mov_es:
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] usb: fsl_qe_udc: check qe_alloc_request() failure in ch9getstatus()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (92 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] exfat: write moved entry before removing source Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:20 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] ALSA: hda/realtek: add missing error checks for COEF index reads in alc269 Sasha Levin
` (422 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Haoxiang Li, Greg Kroah-Hartman, Sasha Levin, linux-usb,
linuxppc-dev, linux-kernel
From: Haoxiang Li <haoxiang_li2024@163.com>
[ Upstream commit 612551bf7cf7113b8bbd5e8c1eea86d9427c2f95 ]
qe_alloc_request() may return NULL on allocation failure. ch9getstatus()
passes the return value directly to container_of() and then immediately
dereferences the resulting qe_req pointer. Check the allocation result
before using it and stall the control request on failure.
Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
Link: https://patch.msgid.link/20260620120631.2894977-1-haoxiang_li2024@163.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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: `[usb / fsl_qe_udc] [check] check qe_alloc_request() failure in
ch9getstatus()` — USB gadget UDC driver; “check” here is a missing-NULL-
check fix, not a feature.
**Step 1.2: Tags**
Record:
- `Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>` (author)
- `Link: https://patch.msgid.link/20260620120631.2894977-1-
haoxiang_li2024@163.com`
- `Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>` (USB
maintainer applied it)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence expected)
**Step 1.3: Body**
Record:
- **Bug:** `qe_alloc_request()` can return NULL; that pointer is passed
to `container_of()` and immediately dereferenced.
- **Symptom:** kernel oops / NULL deref on `GET_STATUS` when allocation
fails.
- **Version info:** none in the message.
- **Root cause:** unchecked allocation result in `ch9getstatus()`.
- **Fix:** test the pointer; stall EP0 on failure.
**Step 1.4: Hidden bug fix?**
Record: Not hidden. This is an explicit NULL-deref fix. The “stall on
failure” path is the existing error path, not a new feature.
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/usb/gadget/udc/fsl_qe_udc.c` (+6 / −2)
- Function: `ch9getstatus()`
- Scope: single-file surgical fix
**Step 2.2: Code flow**
Record: Before, `container_of(qe_alloc_request(...), struct qe_req,
req)` ran unconditionally, then `req->req.length = 2` and later
`__qe_ep_queue()`. After, the result is stored in `usb_req`, NULL goes
to the existing `stall:` label (`dev_err` + `qe_ep0_stall()`), and only
a live request is converted with `container_of`.
**Step 2.3: Bug mechanism**
Record: **NULL pointer dereference** (memory safety).
`qe_alloc_request()` does `kzalloc_obj()` and returns NULL on failure.
`struct qe_req` has `struct usb_request req` as the first member, so
`container_of(NULL, ...)` is still NULL, then `req->req.length = 2`
oopses.
**Step 2.4: Fix quality**
Record: Obviously correct; uses the existing `stall` path; no API/data-
structure change. Regression risk is very low. Pre-existing issue not
introduced here: if alloc succeeds and `__qe_ep_queue()` fails, the
request is still not freed (leak on that older path). This patch does
not make that worse.
## Phase 3: Git history
**Step 3.1: Blame**
Record: Unchecked `container_of(qe_alloc_request(...))` comes from
`3948f0e0c999a6` (“usb: add Freescale QE/CPM USB peripheral controller
driver”, 2008-09-02), first in `v2.6.28-rc1`. The bug is ancient, not
new 7.3 code.
**Step 3.2: Fixes: tag**
Record: No `Fixes:` tag. The introducing commit is `3948f0e0c999a6`
(above). That commit is an ancestor of this tree.
**Step 3.3: File history**
Record: Related work on the same function: `ce9daa2efc087` (2023) added
`pipe >= USB_MAX_ENDPOINTS` before indexing `udc->eps[]` — that patch
was AUTOSEL’d into stable 5.15. Recent file churn is
kmalloc→`kzalloc_obj` conversion, not a refactor of `ch9getstatus()`.
Standalone, not `patch X/Y`.
**Step 3.4: Author**
Record: Haoxiang Li has several USB NULL/leak-style fixes (`mtu3`,
`cdnsp`, `typec`, `renesas_usbhs`). Not the UDC maintainer. Greg Kroah-
Hartman applied this one. Similar sibling: `4ab2b48c98f2e`
(`fsl_udc_core` allocation check).
**Step 3.5: Dependencies**
Record: None. Uses existing `qe_alloc_request()`, `stall:` /
`qe_ep0_stall()`, and `container_of`. Applies standalone.
`qe_alloc_request()` still returns NULL on failure after the
`kzalloc_obj` conversion.
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
Record: `b4 dig -c 612551bf7cf71` → https://patch.msgid.link/20260620120
631.2894977-1-haoxiang_li2024@163.com
`b4 dig -a`: **v1 only**, 2026-06-20, same subject. Mbox is the patch
with **no replies**. LKML/Openwall mirrors match; no NAK, no v2, no `Cc:
stable` in review (there was no public review thread).
**Step 4.2: Recipients (`b4 dig -w`)**
Record: To: `kees@kernel.org`, `gregkh@linuxfoundation.org`; Cc: `linux-
usb`, `linuxppc-dev`, `linux-kernel`. USB maintainer was in To and
committed it.
**Step 4.3: Bug report**
Record: No `Reported-by` / syzbot / bugzilla. Looks like static analysis
(NULL after alloc), not a user crash report.
**Step 4.4: Series**
Record: Standalone v1. Not part of a multi-patch series.
**Step 4.5: Stable list**
Record: Direct lore.kernel.org fetches returned 403. No stable-list
discussion found via `b4` or web search. Precedent: the earlier
`ch9getstatus` bounds check in this file **was** AUTOSEL’d to 5.15.
## Phase 5: Semantic / call-graph
**Step 5.1: Functions**
Record: `ch9getstatus()` only (uses `qe_alloc_request`, `container_of`,
`__qe_ep_queue`, `qe_ep0_stall`).
**Step 5.2: Callers**
Record: Only `setup_received_handle()` on `USB_REQ_GET_STATUS`.
**Step 5.3: Callees**
Record: `qe_alloc_request` → `kzalloc_obj`; `__qe_ep_queue`;
`qe_ep0_stall`; `ownercomplete` kfree’s the request on completion.
**Step 5.4: Call chain / reachability**
Record:
`qe_udc_irq` (hardirq, `spin_lock_irqsave(&udc->lock)`)
→ `rx_irq` → `qe_ep0_rx` → `ep0_setup_handle` → `setup_received_handle`
→ `ch9getstatus`
Reachable from USB host `GET_STATUS` during gadget enumeration.
Unprivileged **host** can send it; not a typical local-syscall path.
GFP_KERNEL under a spinlock in IRQ is a pre-existing atomic-sleep smell
and makes NULL more plausible under memory pressure.
**Step 5.5: Similar patterns**
Record: `qe_alloc_request()` is only used here plus the
`usb_ep_ops.alloc_request` hook. Sibling FSL UDC had the same class of
alloc-check fix.
## Phase 6: This checkout
**Step 6.1: Does the buggy code exist?**
Record: Local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`).
Driver and `ch9getstatus()` are present. The unchecked alloc was
introduced in v2.6.28 and lived until `612551bf7cf71` (`v7.2-rc1-40`,
2026-07-10). HEAD already has the fixed form (`usb_req =
qe_alloc_request...; if (!usb_req) goto stall`). That is the mainline
source of the candidate, not a reason to treat the bug as absent from
this driver.
**Step 6.2: Backport difficulty**
Record: Surrounding `ch9getstatus()` matches the patch; `git diff
612551bf7cf71 HEAD -- drivers/usb/gadget/udc/fsl_qe_udc.c` is empty.
Clean apply on this tree’s file; older stables still have the same
`container_of(qe_alloc_request(...))` shape from 2008.
**Step 6.3: Related fixes already here**
Record: Endpoint-index check `ce9daa2efc087` is already in this file. No
other fix covers the alloc NULL. This patch is the alloc-failure check,
not a duplicate of that bounds check.
## Phase 7: Subsystem context
**Step 7.1:** Record: USB gadget UDC (`drivers/usb/gadget/udc/`).
**PERIPHERAL** — Freescale QE/CPM USB device controller.
`CONFIG_USB_FSL_QE` depends on `FSL_SOC && (QUICC_ENGINE || CPM)` and
`!64BIT || BROKEN` (32-bit PowerPC QE/CPM, e.g. MPC8360/MPC8272).
**Step 7.2:** Record: Mature, low-churn driver (2008). Recent commits
are conversions/typos plus this NULL check. Long-lived bug, not a new-
subsystem issue.
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
Record: Driver-specific / config-specific: USB gadget on 32-bit
Freescale QE/CPM SoCs.
**Step 8.2: Trigger**
Record: Host sends standard `GET_STATUS`; `qe_alloc_request(GFP_KERNEL)`
fails. Uncommon (memory pressure / atomic GFP_KERNEL), but the control
request is a normal enumeration path. Host-triggered.
**Step 8.3: Failure mode**
Record: NULL deref → oops in hardirq UDC path. **Severity: HIGH** (crash
of the gadget/UDC path; can take the machine down depending on
panic_on_oops). Not silent corruption.
**Step 8.4: Risk vs benefit**
Record: **Benefit:** medium for those boards (prevents oops), low
globally (niche HW). **Risk:** very low (6 net lines, existing stall
path). Ratio favors taking it: same class of fix already AUTOSEL’d in
this function.
## Phase 9: Synthesis
**Step 9.1: Evidence**
For:
- Real NULL deref on a live USB control path
- `qe_alloc_request()` documented to return NULL
- Tiny, obviously correct check + existing stall
- Bug present since 2008 in this driver
- USB maintainer merged it
- Same function already had a stable AUTOSEL bounds fix
- Call path is IRQ + spinlock, so GFP_KERNEL failure is not purely
theoretical
Against:
- Niche 32-bit PowerPC QE/CPM gadget (`BROKEN` on 64-bit)
- No user/syzbot report; static-analysis style v1 with no mailing-list
review
- No `Tested-by`
- Alloc-failure is uncommon
- Pre-existing queue-failure leak left unfixed (not a regression)
Unresolved: lore.kernel.org HTTP 403; no public review comments beyond
the patch itself (confirmed via `b4` mbox).
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** on correctness (code is
unambiguous). Testing is only “merged by Greg”; no hardware Tested-
by, but the change does not need runtime proof beyond reading
`qe_alloc_request()`.
2. Real bug affecting users? **PASS** — oops if this UDC handles
`GET_STATUS` and alloc fails.
3. Important (crash/security/corruption/deadlock)? **PASS** — kernel
oops. Not a new API.
4. Small and contained? **PASS** — 8-line hunk, one function.
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — file and function exist; context
matches.
**Step 9.3: Exception category**
Record: None (not an ID/quirk/DT/build/doc exception). It is a normal
crash fix.
**Step 9.4: Decision**
This is a textbook missing-NULL-check on a kmalloc-backed helper, in a
path a USB host hits with `GET_STATUS`. It is small, applies to the
driver in this tree, and prevents an oops. Niche hardware lowers
population, not severity for the people who have it. It meets stable-
kernel-rules.
### What it solves for stable users
Without the check, `ch9getstatus()` oopses when `qe_alloc_request()`
returns NULL. With it, EP0 stalls and the gadget stays up. That matters
on QE/CPM gadget devices under memory pressure, including in hardirq.
### Risk vs benefit
Very low risk, contained error-path change. Benefit is avoiding a real
oops on existing hardware. Worth taking.
---
Verification:
- [Phase 1] Parsed tags: author SOB, Greg KH SOB, msgid link; no
Fixes/Reported-by/Cc stable
- [Phase 2] Diff: +6/−2 in `ch9getstatus()`; NULL check then existing
`stall:`
- [Phase 2] `struct qe_req`: `req` is first member
(`fsl_qe_udc.h:252-259`); `container_of(NULL)` is NULL
- [Phase 2] `qe_alloc_request()` returns NULL after `kzalloc_obj`
failure (lines 1669–1681)
- [Phase 3] `git blame` / `git log -1 3948f0e0c999a6`: buggy pattern
from 2008, `v2.6.28-rc1`
- [Phase 3] No Fixes tag; introducing commit is in this tree
- [Phase 3] Related: `ce9daa2efc087` bounds check in same function;
AUTOSEL 5.15 (lkml archive)
- [Phase 3] Author USB fixes listed via `git log --author="Haoxiang Li"`
- [Phase 4] `b4 dig -c 612551bf7cf71`: lore msgid
20260620120631.2894977-1
- [Phase 4] `b4 dig -a`: v1 only; `b4 dig -w`: gregkh + kees + linux-usb
+ linuxppc-dev
- [Phase 4] mbox: patch only, no replies
- [Phase 4] lore WebFetch 403; LKML/Openwall mirrors used instead
- [Phase 5] Callers: only `setup_received_handle` for
`USB_REQ_GET_STATUS`
- [Phase 5] Call chain: `qe_udc_irq` → `rx_irq` → `qe_ep0_rx` →
`ep0_setup_handle` → `setup_received_handle` → `ch9getstatus`
(spinlock held)
- [Phase 6] `git describe HEAD`: `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion`: 7.3.0-rc4
- [Phase 6] `git merge-base --is-ancestor 612551bf7cf71 HEAD`: yes
(mainline already contains the candidate)
- [Phase 6] File at HEAD matches the fixed version; reverse-apply of the
commit succeeds
- [Phase 7] Kconfig `USB_FSL_QE`: FSL_SOC QE/CPM, `!64BIT || BROKEN`
- [Phase 8] Failure mode: NULL deref oops in UDC IRQ, severity HIGH
- UNVERIFIED: full lore thread beyond the mbox (HTTP 403); whether any
reviewer privately asked for Cc: stable
**YES**
drivers/usb/gadget/udc/fsl_qe_udc.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index aacfde06387c0..7911dca2135cf 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -1945,6 +1945,7 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
u16 index, u16 length)
{
u16 usb_status = 0;
+ struct usb_request *usb_req;
struct qe_req *req;
struct qe_ep *ep;
int status = 0;
@@ -1983,8 +1984,11 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
}
}
- req = container_of(qe_alloc_request(&ep->ep, GFP_KERNEL),
- struct qe_req, req);
+ usb_req = qe_alloc_request(&ep->ep, GFP_KERNEL);
+ if (!usb_req)
+ goto stall;
+
+ req = container_of(usb_req, struct qe_req, req);
req->req.length = 2;
req->req.buf = udc->statusbuf;
*(u16 *)req->req.buf = cpu_to_le16(usb_status);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] ALSA: hda/realtek: add missing error checks for COEF index reads in alc269
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (93 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] usb: fsl_qe_udc: check qe_alloc_request() failure in ch9getstatus() Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] Revert "namei: don't reveal overmounted entries in refwalk" Sasha Levin
` (421 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Bob Song, Takashi Iwai, Sasha Levin, perex, tiwai, linux-sound,
linux-kernel
From: Bob Song <songxiebing@kylinos.cn>
[ Upstream commit 5b106b40ed22098f2bc049efb645148d038444bd ]
alc_read_coef_idx() and alc_read_coefex_idx() can return -1 on error
via snd_hda_codec_read(). Several codec initialization and shutdown
functions save these return values and later write them back to
hardware registers without checking for errors, potentially corrupting
COEF register state on a read failure.
Add error checks in:
- alc282_init() and alc282_shutup(): check coef78 before write-back
- alc285_hp_init(): check coef38/coef0d/coef36 before update, check
val before write-back, and break polling loop on error
- alc294_hp_init(): break polling loop on read error
Signed-off-by: Bob Song <songxiebing@kylinos.cn>
Link: https://patch.msgid.link/20260730015302.253008-1-songxiebing@kylinos.cn
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This tree is **6.1.188**. The unguarded COEF save/restore paths are
present in `sound/pci/hda/patch_realtek.c`, and the same class of bug
already went to stable in 2014 because writing a failed COEF read can
stall the codec.
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
Record: `[ALSA/hda/realtek] [add] missing error checks for COEF index
reads in alc269`
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Bob Song <songxiebing@kylinos.cn>` (author)
- `Link: https://patch.msgid.link/20260730015302.253008-1-
songxiebing@kylinos.cn`
- `Signed-off-by: Takashi Iwai <tiwai@suse.de>` (ALSA maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Cc:
stable` (absence expected)
- Ignore any pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit
...]` if present
**Step 1.3 — Body**
Record:
- Bug: `alc_read_coef_idx()` / `alc_read_coefex_idx()` can return `-1`
via `snd_hda_codec_read()`. Init/shutdown save that value and write it
back.
- Symptom: COEF register corruption on read failure (wrong headphone-amp
/ depop state; historically this class of write can stall the codec).
- Root cause: missing `!= -1` checks on save/restore and on depop
polling.
- No version bounds in the message.
**Step 1.4 — Hidden bug fix?**
Record: Yes. “Add missing error checks” is a real error-path fix, not
style. Same pattern as `alc_update_coefex_idx()` and
`alc269_fill_coef()` in this tree.
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
Record:
- File in the candidate: `sound/hda/codecs/realtek/alc269.c` (`+14/-8`)
- Functions: `alc282_init`, `alc282_shutup`, `alc285_hp_init`,
`alc294_hp_init`
- Scope: single-file surgical fix
**Step 2.2 — Flow change**
Record:
- `alc282_init` / `alc282_shutup`: save coef 0x78, temporarily write
`0x9004`, then restore. After: restore only if `coef78 != -1`.
- `alc285_hp_init`: depop poll `val & 0x8000` for up to 20×50ms, then
write `val` and restore coef 0x38/0x0d/0x36. After: stop poll on `-1`;
skip those writes if the saved/read value is `-1`.
- `alc294_hp_init`: same poll pattern on bit `0x0080`; after: break on
`-1`. No val write-back here.
**Step 2.3 — Bug mechanism**
Record: Logic / hardware-state corruption on error.
- `codec_read()` in this tree returns `-1` when `snd_hdac_exec_verb()`
fails (`sound/hda/hdac_device.c`).
- COEF payload is 16-bit, so `-1` becomes `0xFFFF` on write.
- `alc_update_coef_idx(..., mask, coefXX)` with `coefXX == -1` does
`(current & ~mask) | 0xFFFFFFFF` and sets every bit.
- `val & 0x8000` is true for `-1`, so the depop loop always runs the
full ~1s then writes `0xFFFF`.
**Step 2.4 — Fix quality**
Record: Obviously correct and matches existing `if (val != -1)` guards.
Success path unchanged. Regression risk is low: skipping a restore when
there is no valid saved value is safer than writing `0xFFFF`.
## Phase 3: Git history
**Step 3.1 — Blame / introduction**
Record:
- ALC282 save/restore: `7b5c7a0240b11` (2014) “Fix the noise after
suspend and resume on ALC282 codec” — ancestor of this HEAD.
- ALC285 HP init: `3c24e48330adf` (2021) — ancestor of this HEAD.
- 2014 COEF-guard: `f3ee07d8b6e06` “Avoid setting wrong COEF on ALC269 &
co” — ancestor of this HEAD; `Cc: stable`; documented that writing
after a `-1` read can stall the codec and broke resume on Acer AO725.
**Step 3.2 — Fixes: tag**
Record: None. The incomplete coverage of `f3ee07d8b6e06` is the
historical analogue.
**Step 3.3 — Related file history**
Record: Recent `patch_realtek.c` commits are quirks, not this fix. `git
log --grep="missing error checks"` / `"COEF index reads"` on this file:
no hit. Candidate `5b106b40ed220` is **not** an ancestor of HEAD.
**Step 3.4 — Author**
Record: Bob Song (Kylinos), not the ALSA maintainer. Takashi Iwai
applied it after a v1→v2 split.
**Step 3.5 — Dependencies**
Record: Standalone. Needs only `alc_read_coef*_idx()` returning `-1`,
which this tree already has. No new helpers.
## Phase 4: Mailing list
**Step 4.1 — Original discussion**
Record: `b4 dig -c 5b106b40ed220` →
https://patch.msgid.link/20260730015302.253008-1-songxiebing@kylinos.cn
- v1 combined this with a `codec->bus->pci` NULL check.
- Takashi: “Could you split the NULL check to another patch? Basically
it's a completely different sort of fix from others.”
- v2: this COEF patch only. Takashi: “Applied to for-next branch.
Thanks.”
- No NAK, no stable nomination, no reviewer concern about the COEF
checks.
**Step 4.2 — Recipients (`b4 dig -w`)**
Record: `tiwai@suse.com`, `perex@perex.cz`, `linux-sound@`, `linux-
kernel@`. Maintainer was To: and applied it.
**Step 4.3 — Bug report**
Record: No syzbot/bugzilla for *these* sites. The stall/resume failure
for the same `-1` write pattern is documented in `f3ee07d8b6e06` /
bugzilla 52181.
**Step 4.4 — Series**
Record: v2 series patch 1/2 is this fix; patch 2/2 is the PCI NULL check
(separate). This patch is self-contained.
**Step 4.5 — Stable list**
Record: lore.kernel.org WebFetch returned 403 (Anubis). UNVERIFIED
whether stable@ already discussed this specific commit. Full linux-sound
thread was recovered via `b4 dig -m`.
## Phase 5: Code semantics (this tree)
**Step 5.1 — Functions**
Record: `alc282_init`, `alc282_shutup`, `alc285_hp_init`,
`alc294_hp_init` in `sound/pci/hda/patch_realtek.c`.
**Step 5.2 — Callers (verified)**
Record:
- `alc282_init` / `alc282_shutup`: codec `0x10ec0282` (`spec->init_hook`
/ `spec->shutup`).
- `alc285_hp_init`: from `alc225_init` on boot and S3/S4 resume (skipped
only for ALC287/ALC245).
- `alc225_init`: ALC215/245/285/289, ALC225/295/299, ALC287.
- `alc294_hp_init`: from `alc294_init` on boot / S4 restore;
ALC234/274/294 and ALC700.
- `alc_init()` runs `spec->init_hook`; `.init = alc_init`.
- `alc_suspend()` → `alc_shutup()` → `spec->shutup`; `alc_resume()` →
`patch_ops.init`.
**Step 5.3 — Callees**
Record: `alc_read_coef*_idx`, `alc_write_coef*_idx`,
`alc_update_coef*_idx`, `snd_hda_codec_write`, `msleep`.
**Step 5.4 — Reachability**
Record: Yes. Probe, suspend, and resume on common Realtek laptop codecs.
Not an obscure config path.
**Step 5.5 — Similar patterns**
Record: Already guarded in this file:
- `__alc_update_coefex_idx()`: `if (val != -1)`
- `alc269_fill_coef()`: `if (val != -1 && ...)` before write
These four functions were the remaining save/restore holes.
## Phase 6: This checkout (6.1.188)
**Step 6.1 — Does the buggy code exist?**
Record: Yes. Unguarded write-backs:
```3429:3431:sound/pci/hda/patch_realtek.c
/* Headphone capless set to normal mode */
alc_write_coef_idx(codec, 0x78, coef78);
}
```
```3465:3468:sound/pci/hda/patch_realtek.c
alc_auto_setup_eapd(codec, false);
alc_shutup_pins(codec);
alc_write_coef_idx(codec, 0x78, coef78);
}
```
```3718:3727:sound/pci/hda/patch_realtek.c
val = alc_read_coefex_idx(codec, 0x58, 0x00);
for (i = 0; i < 20 && val & 0x8000; i++) {
msleep(50);
val = alc_read_coefex_idx(codec, 0x58, 0x00);
} /* Wait for depop procedure finish */
alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the
result */
alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
```
Same unguarded poll in `alc294_hp_init`. Introduced 2014/2021; both are
in this tree.
**Step 6.2 — Backport difficulty**
Record: Minor path rework. Candidate path
`sound/hda/codecs/realtek/alc269.c` does not exist here; equivalent code
is `sound/pci/hda/patch_realtek.c`. Function bodies match the pre-patch
logic. Not a semantic conflict.
**Step 6.3 — Already fixed here?**
Record: No. `git merge-base --is-ancestor 5b106b40ed220 HEAD` failed. No
later substitute fix in this file.
## Phase 7: Subsystem
**Step 7.1**
Record: ALSA HD-audio Realtek codec. **IMPORTANT** (default audio on a
huge set of laptops).
**Step 7.2**
Record: Mature driver; current 6.1.y activity is mostly quirks. These
init/shutup paths have been stable for years, which is why leftover `-1`
write-backs still matter.
## Phase 8: Impact and risk
**Step 8.1 — Who**
Record: Users of ALC282, ALC215/225/285/289, ALC225/295/299,
ALC234/274/294, ALC700 — typical `CONFIG_SND_HDA_CODEC_REALTEK` x86
laptops.
**Step 8.2 — Trigger**
Record: Codec COEF read returns `-1` (verb timeout, invalid COEF on a
variant, flaky link during suspend/resume). Not an unprivileged syscall
exploit; it is a common device PM path.
**Step 8.3 — Failure mode**
Record: Wrong COEF restore / depop result. Severity **HIGH** for audio:
headphone noise, failed depop, or codec stall (the failure
`f3ee07d8b6e06` already shipped to stable). Not a kernel oops by itself.
**Step 8.4 — Ratio**
Record: Benefit medium-high (PM path on common hardware, same class as a
prior stable fix). Risk very low (~14 lines of `!= -1` guards, success
path identical).
## Phase 9: Synthesis
**Evidence FOR**
- Real write of error sentinel `-1`/`0xFFFF` into codec COEF state.
- `alc_update_coef_idx(..., saved)` with `saved == -1` sets all bits on
a register that may still be readable.
- Depop poll treats `-1` as “still busy” for a full second.
- Same class as `f3ee07d8b6e06` (codec stall / resume failure, `Cc:
stable`).
- Small, obviously correct, maintainer-applied.
- Buggy functions exist in this 6.1.188 tree and are not fixed.
**Evidence AGAINST**
- No user report for these four sites.
- Exact patch needs a file-path backport (`alc269.c` →
`patch_realtek.c`).
- Static-analysis style; trigger is an already-failing verb.
**Unresolved**
- lore.kernel.org HTTP 403 for stable@ search (thread itself was
retrieved with b4).
**Stable rules**
1. Obviously correct and tested? **PASS** (maintainer applied v2;
success path unchanged)
2. Real user-visible bug? **PASS** (bad COEF restore on
init/suspend/resume)
3. Important (stall / broken audio / register corruption)? **PASS**
(same class as the 2014 stable COEF-stall fix)
4. Small and contained? **PASS** (`+14/-8`, four local checks)
5. No new features/APIs? **PASS**
6. Can apply here? **PASS** with a trivial path backport to
`patch_realtek.c`
**Exception category:** none (not an ID/quirk/DT/build/docs exception).
It is a normal small bugfix.
This should go into this 6.1.188 tree. The bug is in the local
`alc282_*` / `alc285_hp_init` / `alc294_hp_init` paths; the fix is a few
`!= -1` guards that this tree already uses elsewhere.
Verification:
- [Phase 1] Parsed tags: author Bob Song; Link msgid; SOB Takashi Iwai;
no Fixes/Reported-by/Cc stable
- [Phase 2] Diff: 14 insertions / 8 deletions; four functions; skip
write-back and stop poll on `-1`
- [Phase 2] `codec_read()` in this tree returns `-1` on
`snd_hdac_exec_verb()` failure (`sound/hda/hdac_device.c:988-997`)
- [Phase 3] `git merge-base --is-ancestor 7b5c7a0240b11 HEAD` — yes
(ALC282 write-back, 2014)
- [Phase 3] `git merge-base --is-ancestor 3c24e48330adf HEAD` — yes
(alc285_hp_init, 2021)
- [Phase 3] `git merge-base --is-ancestor f3ee07d8b6e06 HEAD` — yes
(2014 COEF-guard, Cc:stable, codec stall)
- [Phase 3] `git merge-base --is-ancestor 5b106b40ed220 HEAD` — no (fix
not in this tree)
- [Phase 4] `b4 dig -c 5b106b40ed220`: v1 split requested, v2 applied;
no NAK
- [Phase 4] UNVERIFIED: lore.kernel.org/stable search (HTTP 403)
- [Phase 5] Callers: `alc_init` → init_hook; `alc_suspend` → shutup;
`alc_resume` → init; vendor IDs 0x10ec0282 / 0215 / 0225 / 0234 / 0285
/ 0294 / …
- [Phase 6] `git describe HEAD`: `p-6.1-2-g8ee893656ef69`; `make
kernelversion`: **6.1.188**
- [Phase 6] Buggy code present in `sound/pci/hda/patch_realtek.c` lines
3430, 3467, 3719-3727, 3992
- [Phase 6] Target file `sound/hda/codecs/realtek/alc269.c` missing
here; equivalent functions exist
- [Phase 8] Failure mode: COEF corruption / possible codec stall on
resume; severity HIGH for audio, not a kernel oops
**YES**
sound/hda/codecs/realtek/alc269.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index d88627558150f..3364f6ad91fcb 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -296,7 +296,8 @@ static void alc282_init(struct hda_codec *codec)
msleep(100);
/* Headphone capless set to normal mode */
- alc_write_coef_idx(codec, 0x78, coef78);
+ if (coef78 != -1)
+ alc_write_coef_idx(codec, 0x78, coef78);
}
static void alc282_shutup(struct hda_codec *codec)
@@ -333,7 +334,8 @@ static void alc282_shutup(struct hda_codec *codec)
alc_auto_setup_eapd(codec, false);
alc_shutup_pins(codec);
- alc_write_coef_idx(codec, 0x78, coef78);
+ if (coef78 != -1)
+ alc_write_coef_idx(codec, 0x78, coef78);
}
static const struct coef_fw alc283_coefs[] = {
@@ -585,15 +587,19 @@ static void alc285_hp_init(struct hda_codec *codec)
alc_write_coefex_idx(codec, 0x58, 0x00, 0xf888); /* HP depop procedure start */
val = alc_read_coefex_idx(codec, 0x58, 0x00);
- for (i = 0; i < 20 && val & 0x8000; i++) {
+ for (i = 0; i < 20 && val != -1 && val & 0x8000; i++) {
msleep(50);
val = alc_read_coefex_idx(codec, 0x58, 0x00);
} /* Wait for depop procedure finish */
- alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */
- alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
- alc_update_coef_idx(codec, 0x0d, 0x110, coef0d);
- alc_update_coef_idx(codec, 0x36, 3<<13, coef36);
+ if (val != -1)
+ alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */
+ if (coef38 != -1)
+ alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
+ if (coef0d != -1)
+ alc_update_coef_idx(codec, 0x0d, 0x110, coef0d);
+ if (coef36 != -1)
+ alc_update_coef_idx(codec, 0x36, 3<<13, coef36);
msleep(50);
alc_update_coef_idx(codec, 0x4a, 1<<15, 0);
@@ -858,7 +864,7 @@ static void alc294_hp_init(struct hda_codec *codec)
/* Wait for depop procedure finish */
val = alc_read_coefex_idx(codec, 0x58, 0x01);
- for (i = 0; i < 20 && val & 0x0080; i++) {
+ for (i = 0; i < 20 && val != -1 && val & 0x0080; i++) {
msleep(50);
val = alc_read_coefex_idx(codec, 0x58, 0x01);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] Revert "namei: don't reveal overmounted entries in refwalk"
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (94 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] ALSA: hda/realtek: add missing error checks for COEF index reads in alc269 Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] wifi: rtlwifi: rtl8723be: Remove unnecessary irq save/restore in hw_init() Sasha Levin
` (420 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Christian Brauner, Sasha Levin, viro, linux-fsdevel, linux-kernel
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit 214897acc8c2e5d6b63189d23ccaed6fa2af45a9 ]
This reverts commit 8189ab688f5a2c745dc90b63374da02f213d6994.
This bug class is bigger than can be fixed with this simple patch.
Back out of it and give us some time to fix this properly.
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This revert should go into this 6.18.57 tree. The incomplete
`unlink_may_reveal()` check is already in v6.18.57, the VFS maintainer
pulled it back as an rc8 fix, and leaving it here regresses common
unlink/open races.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: `[vfs/namei] [Revert] undo "don't reveal overmounted entries in
refwalk"`
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- No `Fixes:` tag on the revert itself (it names the reverted SHA in the
body)
- No `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-by:`, `Link:`,
or `Cc: stable`
- `Signed-off-by: Christian Brauner <brauner@kernel.org>` (VFS
maintainer; ignore Sasha Levin SOB)
- Body: `This reverts commit 8189ab688f5a2c745dc90b63374da02f213d6994`
The original commit that is being reverted **did** have `Fixes:
8ed936b5671b`, `Cc: stable@vger.kernel.org`, and `Link:
https://patch.msgid.link/20261002-work-mount-
fixes-4-v1-2-dd44b89d44ce@kernel.org`. That is why 8189ab68 already
landed in this stable series; the revert is the follow-up.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug description: the earlier “simple patch” does not cover this bug
class
- Symptom/failure mode: not a crash; an incomplete pathwalk/mount-cover
check that must be withdrawn
- Version information: none in the revert message
- Root cause (author): “This bug class is bigger than can be fixed with
this simple patch. Back out of it and give us some time to fix this
properly.”
Linus’s `vfs-7.3-rc8.fixes` pull restates the same thing: *Revert
"namei: don't reveal overmounted entries in refwalk" from the rc7 fixes.
The bug class is bigger than that patch.*
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not disguised cleanup. This is an explicit revert of a recently
merged, incomplete VFS change. A later (unmerged) follow-up documented a
real regression: any unlink/rename racing a refwalk returned `-ESTALE`
and forced a full `LOOKUP_REVAL` walk, which on NFS/FUSE revalidates
every path component.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `fs/namei.c` only
- Mainline revert: remove `unlink_may_reveal()` (~27 lines) and its one
call site (2 lines). Net −29
- Local 6.18.y equivalent of the original add is `5f97df8ca7fad`; the
revert is its inverse
- Functions: delete `unlink_may_reveal`; one call removed from
`step_into()` (this tree) / `step_into_slowpath()` (mainline after a
later split)
- Scope: single-file surgical revert
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before (v6.18.57): in the non-RCU / refwalk arm of `step_into()`,
after `handle_mounts()`, `unlink_may_reveal()` returns true if the
dentry is `cant_mount()` **and** `d_unlinked()`, the walk has not
crossed a mount, and flags are not `WALK_NOFOLLOW`/`LOOKUP_REVAL`. It
`dput()`s `path->dentry` and the caller returns `-ESTALE`.
- After: that check is gone; refwalk accepts the dentry as it did before
5f97.
- Path: common pathname lookup (`open`/`stat`/`lookup`), refwalk only
(RCU walk already retries via `d_seq`/`mount_lock`).
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: revert of an incomplete logic/correctness change that also
caused a lookup-retry regression
- Mechanism: `dont_mount()` runs on **every** successful `vfs_unlink()`
/ `vfs_rmdir()` / rename-over, not only mountpoints. Combined with
`d_unlinked()`, the helper treated ordinary unlinks as “may reveal a
covered file” and forced `-ESTALE` → `LOOKUP_REVAL`. That is far
broader than the mount-cover race it meant to close, and it still did
not cover the rest of the bug class.
Verified `dont_mount()` call sites in this tree: `vfs_rmdir()` ~4558,
`vfs_unlink()` ~4679, `vfs_rename()` ~5230.
Verified ESTALE retry in this tree:
```2708:2709:fs/namei.c
if (unlikely(retval == -ESTALE))
retval = path_lookupat(&nd, flags | LOOKUP_REVAL, path);
```
Same pattern in `do_filp_open()` / `do_file_open_root()`. The helper
itself skipped the check when `LOOKUP_REVAL` was already set, which
matches the “fail once, then full revalidate” behavior.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Quality: obviously correct as a revert — it is the exact inverse of
5f97 in this tree
- Regression risk of the revert: re-opens the remaining refwalk window
where a walker that already held the dentry can see a file after its
covering mounts were detached. That race is old (Fixes target
8ed936b5671b, 2014). 6.18.y lived with it until 6.18.57. A sibling
backport, `d29cd99db3db7` (“unhash a dentry before detaching the
mounts”), remains and still shrinks the *new lookup* side of the race.
- Risk of keeping 5f97: extra `LOOKUP_REVAL` on common unlink/create
storms; incomplete security fix in core pathwalk
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: At v6.18.57, every `unlink_may_reveal` line and the
`step_into()` call are `5f97df8ca7fad` (Christian Brauner, 2026-10-02;
committed to 6.18.y by Greg Kroah-Hartman on 2026-10-15). Surrounding
`step_into()` logic is old Al Viro/Linus code (2011–2022).
Step 3.2: FOLLOW THE FIXES: TAG
Record: The revert has no Fixes tag. It reverts mainline `8189ab688f5a`
= local `5f97df8ca7fad`.
- `git merge-base --is-ancestor 5f97df8ca7fad v6.18.57` → yes
(v6.18.57~479)
- `git merge-base --is-ancestor 5f97df8ca7fad v6.18.56` → no
- Original 8189ab68 `Fixes: 8ed936b5671b` **is** an ancestor of this
tree (2014-10-09)
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- `d29cd99db3db7 namespace: unhash a dentry before detaching the mounts
on it` is also in v6.18.57 (same Greg KH batch, same original series).
It stays; this revert does not undo it.
- No other `unlink_may_reveal` / `DCACHE_UNCOVERED` commits in this tree
- Standalone revert, not patch 2/N of something this tree still needs
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Christian Brauner is the VFS maintainer. Recent `fs/namei.c`
work in this history includes the original add, this revert, and other
VFS fixes. Weight: high.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: The only prerequisite is that 5f97 exists, which it does. The
revert applies as the exact inverse of 5f97 (`step_into`, not mainline’s
later `step_into_slowpath`). No new helpers. Standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 214897acc8c2` failed: lore.kernel.org returned errors
(UNVERIFIED: no dedicated mailed revert thread found; Brauner likely
committed this directly)
- WebFetch of lore.kernel.org returned 403 (UNVERIFIED: full lore
thread)
- Original add was series `work-mount-fixes-4` patch 02/21 (msgid
`20261002-work-mount-fixes-4-v1-2-dd44b89d44ce@kernel.org`); also on
lkml.iu.edu / patchew
- Linus merged the revert in `1dbb7422053fa` *Merge tag
'vfs-7.3-rc8.fixes'* and called it out in the pull text
- An unmerged follow-up (syzbot CI series) explained the LOOKUP_REVAL
regression and tried `DCACHE_UNCOVERED`; that approach was **not**
merged — they reverted instead
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: `b4 dig -w` failed (lore error). Author is the VFS maintainer;
Linus merged it as an rc8 VFS fix. That is stronger than a typical
mailing-list Ack.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla on the revert. The **original** add included
a userspace reproducer (`unlink_covered`) showing the mount-cover race
(~27 hits/60s without widening). The unmerged follow-up’s `unlink_storm`
reproducer showed 463 LOOKUP_REVAL retries in 16.8 million opens from
the too-broad check.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Original add was 02/21 of a large mount-fixes series. Sibling
`unhash a dentry before detaching` is already in 6.18.57 and is **not**
reverted. No merged “proper” replacement for `unlink_may_reveal` exists
in this tree or in the nearby mainline objects inspected.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search could not be fetched (403).
UNVERIFIED whether anyone separately requested this revert on the stable
list. Not needed: the original went to 6.18.57 via `Cc: stable`, and the
author immediately backed it out in mainline.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `unlink_may_reveal` (removed), `step_into` (call removed). No
semcode tools available.
Step 5.2: TRACE CALLERS
Record: `step_into()` callers in this tree:
- `handle_dots()` (WALK_NOFOLLOW — helper returned false anyway)
- `walk_component()` — every normal path component
- one more WALK_NOFOLLOW site ~2660
- `open_last_lookups` path ~3922 (`WALK_TRAILING`)
Impact surface: **every pathname lookup** that drops out of RCU-walk
into refwalk.
Step 5.3: TRACE CALLEES
Record: Helper used `cant_mount()`, `d_unlinked()`,
`dput(no_free_ptr(path->dentry))`. Returning `-ESTALE` skipped the
normal `dput(nd->path.dentry)` / `mntput` in `step_into()`;
`terminate_walk()` still owns `nd->path`. The extra `dput` was only on
the ESTALE path.
Step 5.4: FOLLOW THE CALL CHAIN
Record: userspace `open`/`openat`/`stat`/`fstatat`/etc. →
`filename_lookup` / `do_filp_open` → `link_path_walk` → `walk_component`
→ `step_into`. Unprivileged users trigger this constantly. The false
ESTALE path is a realistic unlink vs open race, not only the exotic
mount-cover case.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: No other `unlink_may_reveal` copies. `cant_mount()` remains in
`fs/namespace.c` and `fs/dcache.c` for mount setup, which is correct and
unrelated.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes, in **v6.18.57** (`fs/namei.c` `unlink_may_reveal` + call in
`step_into`). Tree identity: `git describe HEAD` =
`v6.18.57-155-gcdf239ca885b2`, `make kernelversion` = 6.18.57.
Introduced here by 5f97 (upstream 8189ab68), first in 6.18.57, not
6.18.56.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. Local revert hunks match 5f97 exactly (`step_into`,
not `step_into_slowpath`). No conflicting namei refactor between 5f97
and v6.18.57.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No later replacement for this check. `d29cd99` (unhash before
detach) is present and complementary; it must stay. This revert does not
remove it.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: `fs/namei.c` — VFS pathname lookup. **CORE**. Affects every user
of every filesystem.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature, still actively fixed (recent mount/namespace series).
This is not staging/experimental code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Universal for anyone running 6.18.57+. NFS/FUSE users feel the
LOOKUP_REVAL retry cost most. Container/user-ns users care about the
original mount-cover race; that race is only partially addressed by
d29cd99 and was not fully fixed by 5f97.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- False ESTALE: concurrent unlink/rename vs refwalk on any name
(`dont_mount` is unconditional). Common.
- Original cover-reveal race: unlink of a mountpoint while another task
walks the covering name. Narrow but real; original commit measured 27
hits/60s.
- Unprivileged users can trigger both (open/unlink). The cover case
typically needs mount privileges or a shared mount namespace.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- Keeping 5f97: extra full-path revalidation (MEDIUM–HIGH on NFS/FUSE;
LOW on local tmpfs except under unlink storms). Incomplete mount-cover
fix (the author says the class is bigger).
- After revert: restore pre-6.18.57 `step_into` behavior; remaining
cover-reveal race is the long-standing one (MEDIUM, security-adjacent,
narrow), with d29cd99 still reducing new-lookup hits.
- Severity of **not** reverting a known-wrong core pathwalk change that
already shipped in 6.18.57: HIGH (stable regression vs 6.18.56).
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: remove a too-broad ESTALE/LOOKUP_REVAL regression from core
lookup; align 6.18.y with the VFS maintainer’s rc8 correction; drop an
incomplete security bandage rather than pretend it closed the class
- Risk: very low — exact inverse of a 29-line function added in 6.18.57
- Ratio: strongly favors backporting the revert
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- The commit being reverted **is in this tree** (5f97, v6.18.57~479)
- VFS maintainer authored the revert; Linus merged it as
vfs-7.3-rc8.fixes
- Documented too-broad check: every unlink/rename vs refwalk, not only
overmounts
- Small, exact inverse, applies cleanly
- Sibling unhash-before-detach fix remains
- Revert of a stable-to-stable mistake (5f97 was itself a 6.18.57
backport)
AGAINST:
- Re-opens the remaining “walker already holds the dentry” cover-reveal
window
- Original add had a reproducer and `Cc: stable`
UNRESOLVED:
- Full lore thread for the revert itself (b4/lore failed)
- Whether a later proper fix exists only on branches not in this object
store (none found on 214897’s nearby history)
The “against” point is why 5f97 was written. The maintainer’s later
judgment, merged by Linus, is that keeping that patch is worse than
living with the old narrow race until a real fix exists. For stable,
shipping 5f97 for a few days and then following the revert is the
conservative choice.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — exact revert of a known SHA;
merged as an rc8 VFS fix
2. Fixes a real bug that affects users? **PASS** — removes a too-broad
ESTALE/LOOKUP_REVAL pathwalk regression introduced in 6.18.57
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
core VFS lookup regression; incomplete security check is worse than
no check plus the remaining unhash fix
4. Small and contained? **PASS** — −29 lines, one file
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — inverse of 5f97 on
`step_into()`
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/quirk/DT/docs case. It is the documented revert
case: original commit **is** in this stable tree, so the revert is
needed.
Step 9.4: MAKE YOUR DECISION
This tree is 6.18.57. It already contains the incomplete refwalk check.
The revert is the maintainer’s correction of that 6.18.57 backport and
should be applied here.
What it does for stable users: it takes `unlink_may_reveal()` out of
`step_into()` so ordinary unlink/open races no longer force a full
`LOOKUP_REVAL` walk, and it stops treating a known-incomplete mount-
cover check as a finished fix. `d29cd99` still unhashes before detaching
mounts.
Risk vs benefit: benefit is high (undo a core-pathwalk regression that
is only days old in 6.18.57); risk is very low (surgical revert).
Concerns: the original cover-reveal race is not fully solved; that is
intentional per the author. No extra prerequisites.
Verification:
- [Phase 1] Parsed revert tags: Brauner SOB only; body reverts
8189ab688f5a; original add had Fixes/Cc stable/Link
- [Phase 1] Linus vfs-7.3-rc8.fixes pull explicitly names this revert
- [Phase 2] Diff: −29 lines in fs/namei.c; removes unlink_may_reveal +
ESTALE return in step_into
- [Phase 2] Verified dont_mount() on vfs_unlink/vfs_rmdir/vfs_rename;
ESTALE→LOOKUP_REVAL in filename_lookup/do_filp_open
- [Phase 3] git describe HEAD: v6.18.57-155-gcdf239ca885b2;
kernelversion 6.18.57
- [Phase 3] git merge-base --is-ancestor 5f97df8ca7fad v6.18.57: yes;
v6.18.56: no
- [Phase 3] git blame v6.18.57: unlink_may_reveal entirely 5f97df8ca7fad
- [Phase 3] 8ed936b5671b is an ancestor; d29cd99 unhash-before-detach is
in v6.18.57 and stays
- [Phase 3] Local revert is the exact inverse of 5f97 on step_into (not
step_into_slowpath)
- [Phase 4] b4 dig -c 214897acc8c2: lore server error — UNVERIFIED
mailed thread
- [Phase 4] lore WebFetch 403 — UNVERIFIED lore discussion
- [Phase 4] Unmerged DCACHE_UNCOVERED follow-up documents LOOKUP_REVAL
regression (syzbot CI / series text)
- [Phase 5] step_into callers: walk_component, handle_dots,
open_last_lookups — core pathwalk
- [Phase 6] Buggy helper present at v6.18.57:fs/namei.c:1983; clean
apply
- [Phase 8] Failure mode: extra LOOKUP_REVAL on unlink vs open; NFS/FUSE
revalidate whole path
- UNVERIFIED: stable@ mailing list discussion of this specific revert
**YES**
fs/namei.c | 29 -----------------------------
1 file changed, 29 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index 2e86733b4bacb..003c9a1b2f904 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1973,33 +1973,6 @@ static const char *pick_link(struct nameidata *nd, struct path *link,
return NULL;
}
-/*
- * Be careful in case the dentry is unlinked or renamed. Any mounts
- * stacked on top of it are going away. We need to make sure that we
- * don't reveal the underyling dentry during refwalk. In rcuwalk we
- * catch this via d_seq and another lookup for the name. Give the same
- * guarantee in refwalk.
- */
-static bool unlink_may_reveal(struct nameidata *nd, int flags,
- struct path *path, struct dentry *dentry)
-{
- /* ".." and LOOKUP_DOWN may land on an unhashed directory */
- if (flags & WALK_NOFOLLOW)
- return false;
- if (nd->flags & LOOKUP_REVAL)
- return false;
- /* We crossed onto a mount and the name led us here while it still existed */
- if (path->mnt != nd->path.mnt)
- return false;
- /* only a name on its way out is flagged */
- if (likely(!cant_mount(dentry)))
- return false;
- if (!d_unlinked(dentry))
- return false;
- dput(no_free_ptr(path->dentry));
- return true;
-}
-
/*
* Do we need to follow links? We _really_ want to be able
* to do this check without having to look at inode->i_op,
@@ -2028,8 +2001,6 @@ static const char *step_into(struct nameidata *nd, int flags,
if (unlikely(!inode))
return ERR_PTR(-ENOENT);
} else {
- if (unlikely(unlink_may_reveal(nd, flags, &path, dentry)))
- return ERR_PTR(-ESTALE);
dput(nd->path.dentry);
if (nd->path.mnt != path.mnt)
mntput(nd->path.mnt);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] wifi: rtlwifi: rtl8723be: Remove unnecessary irq save/restore in hw_init()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (95 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] Revert "namei: don't reveal overmounted entries in refwalk" Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets Sasha Levin
` (419 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: William Hansen-Baird, Ping-Ke Shih, Sasha Levin, linux-wireless,
linux-kernel
From: William Hansen-Baird <william.hansen.baird@gmail.com>
[ Upstream commit 1b4cd55626b6ffa93d18848412afb912a4add585 ]
rtl8723be hw_init() calls local_save_flags(flags) followed by
local_irq_enable(). Later, local_irq_restore(flags) is called.
This causes warnings from Lockdep on boot and modprobe,
as local_irq_restore(flags) should only be called while irqs are disabled.
The warning was introduced to detect this class of bug in [1].
With testing I found that all paths which call hw_init() have irqs
already enabled for rtl8723be.
Furthermore, the calls were originally added for the rtl8192ce
in commit f78bccd79ba3 ("rtlwifi: rtl8192ce: Fix too long disable of IRQs")
before later being added to most other rtlwifi drivers.
Commit d3feae41a347 ("rtlwifi: Update power-save routines for 062814 driver")
then replaces the call to spin_lock_irqsave() before hw_init(),
and thus the codepath which caused irqs to be disabled in hw_init and
prompted the original commit has been removed.
The same irq save/restore pattern is also present in the hw_init() of
rtl8192ce, rtl8723ae, rtl8188ee, rtl8192se and rtl8192cu,
however I don't have the hardware to test them,
so I did not include them in my changes.
Tested on a Razer Blade 14 2017.
Example of output from Lockdep prior to fix:
raw_local_irq_restore() called with IRQs enabled
...
Call Trace:
<TASK>
rtl8723be_hw_init+0x5992/0x7220 [rtl8723be]
? static_obj+0x61/0xa0
rtl_pci_start+0x222/0x5c0 [rtl_pci]
rtl_op_start+0x128/0x1a0 [rtlwifi]
? __kasan_check_read+0x11/0x20
drv_start+0x16c/0x550 [mac80211]
...
irq event stamp: 887679
hardirqs last enabled at (887689): [<ffffffff96511170>] __up_console_sem+0x90/0xa0
hardirqs last disabled at (887698): [<ffffffff96511155>] __up_console_sem+0x75/0xa0
softirqs last enabled at (887670): [<ffffffff962f4675>] __irq_exit_rcu+0x175/0x2f0
softirqs last disabled at (887649): [<ffffffff962f4675>] __irq_exit_rcu+0x175/0x2f0
---[ end trace 0000000000000000 ]---
[1] https://lore.kernel.org/all/20210111153707.10071-1-mark.rutland@arm.com/
Signed-off-by: William Hansen-Baird <william.hansen.baird@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260609095359.2964193-1-william.hansen.baird@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **v7.3-rc4** (mainline 7.3). The candidate is a six-
line IRQ API fix in `rtl8723be_hw_init()` that stops a real `WARN_ONCE`
on boot. Full phase walkthrough follows.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[wifi: rtlwifi: rtl8723be]** **[Remove]** unnecessary irq
save/restore in `hw_init()`. Intent: drop a leftover `local_save_flags`
/ `local_irq_enable` / `local_irq_restore` sequence that is no longer
valid.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Acked-by:** Ping-Ke Shih `<pkshih@realtek.com>` (rtlwifi maintainer)
- **Signed-off-by:** William Hansen-Baird (author); Ping-Ke Shih
(maintainer)
- **Link:** https://patch.msgid.link/20260609095359.2964193-1-
william.hansen.baird@gmail.com
- No Fixes:, Reported-by:, Tested-by:, Cc: stable (absence expected)
- Ignore pipeline SOBs
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `rtl8723be_hw_init()` does `local_save_flags(flags);
local_irq_enable();` … `local_irq_restore(flags)` while IRQs are
already enabled.
- **Symptom:** `WARN_ONCE` from `warn_bogus_irq_restore()`:
`raw_local_irq_restore() called with IRQs enabled`, on boot and
`modprobe`. Stack: `rtl8723be_hw_init` → `rtl_pci_start` →
`rtl_op_start` → `drv_start`.
- **Root cause:** The save/enable/restore was copied from rtl8192ce
(`f78bccd79ba3`, 2014) to keep IRQs enabled during a long `hw_init()`
that used to run under `spin_lock_irqsave()`. `d3feae41a347` (2014)
removed that irqsave around the power-save/`hw_init` path, so callers
now enter with IRQs enabled. Restore of already-enabled flags is
forbidden.
- **Version info:** Pattern present since the rtl8723be driver was added
(`a619d1abe20cc`, 2014-02-28). Warning added in `997acaf6b4b59`
(2021).
- **Author explanation:** All current rtl8723be `hw_init()` callers have
IRQs enabled (tested on a Razer Blade 14 2017). Sibling chips still
have the pattern but were left alone for lack of hardware.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. Explicit lockdep/IRQ-restore warning fix. “Remove
unnecessary” is accurate: the sequence became a no-op plus a warning
after the 2014 caller change.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c` — **6
deletions, 0 additions**
- Function: `rtl8723be_hw_init()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** Save flags, force IRQs on for the whole init, restore
flags at the `exit:` label (success and error).
- **After:** Init runs in the caller’s IRQ state; `exit:` only clears
`being_init_adapter`.
- **Path:** Normal and error `hw_init()` (boot, `modprobe`, interface
start, IPS nic-on).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Logic / IRQ-flag API misuse** (WARN_ON class).
`local_irq_restore()` must be called with IRQs disabled
(`raw_check_bogus_irq_restore()` in `include/linux/irqflags.h`). Callers
already have IRQs enabled, so restore trips `WARN_ONCE`. Same class as
`8b144dedb928e` (“rtlwifi: rtl8192cu: Fix WARNING when calling
local_irq_restore() with interrupts enabled”), which used
`local_irq_disable()` before restore and was **Cc: stable**. Here the
save/enable/restore is removed because it is no longer needed.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct if all callers have IRQs enabled (author tested;
maintainer agreed; `rtl_pci_start` / `rtl_op_start` /
`rtl_ps_enable_nic` are process-context, mutex/work, not
`spin_lock_irqsave`).
- Minimal: six lines deleted, no unrelated edits.
- Regression risk: if some caller still had IRQs off, `hw_init()` could
run ~hundreds of ms with IRQs disabled (the 2014 audio-underrun/clock-
freeze bug). Verified not the case in this tree. Maintainer: “current
`hw_init()` is not in scope of `spin_lock_irqsave()`, so irqs is not
disabled.”
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: IRQ save/restore was in rtl8723be from **`a619d1abe20cc`
(“rtlwifi: rtl8723be: Add new driver”, 2014-02-28)**. Pattern copied
from rtl8192ce `f78bccd79ba3` (2014-02-01). Present for ~12 years.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Related history:
- `f78bccd79ba3` — **in this tree** — added save/enable/restore because
`hw_init` ran too long with IRQs off.
- `d3feae41a347` — **in this tree** — replaced `spin_lock_irqsave`
before `hw_init` with `spin_lock` / mutex; IRQ-disabled caller gone.
- `997acaf6b4b59` — **in this tree** — added the `WARN_ONCE`.
- `8b144dedb928e` (2021) — **in this tree** — same warning on rtl8192cu;
**Cc: stable**.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Recent `rtl8723be/hw.c` commits are unrelated (stack size, const
arrays, LED, `kfree_skb`). Standalone; not patch X/Y in the committed
form (v2 was a single patch).
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: William Hansen-Baird is a contributor, not the maintainer.
Nearby work is separate ASPM quirks for the same chip (June 30), not
prerequisites. Maintainer Ping-Ke Shih acked and applied it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None. Deletes three API calls that have existed since 2014.
Applies standalone.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore/msgid: https://patch.msgid.link/20260609095359.2964193-1-
william.hansen.baird@gmail.com
- v1: https://patch.msgid.link/20260608135345.2526325-3-
williamhb+k@fastmail.com
- v1 → v2: drop dmesg timestamps, `[1]` footnote, `rtw-next` subject
prefix. **Code unchanged.**
- Maintainer: “I think removal is okay.” No NAK. No Cc: stable in
review. Applied to rtw-next as `1b4cd55626b6`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: To/Cc: `pkshih@realtek.com`, linux-wireless, linux-kernel.
Subsystem maintainer reviewed and Acked.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla for this exact chip. Author reproduced on a
Razer Blade 14 2017 with a full lockdep-style trace. Same warning class
was syzbot+stable for rtl8192cu in 2021.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: v1 msgid `-3` looks like a series slot; v2 was sent standalone.
Other June 2026 Hansen-Baird rtlwifi patches are ASPM, independent.
Sibling drivers (rtl8192ce, rtl8723ae, rtl8188ee, rtl8192se, rtl8192cu)
still have the pattern; not required for this chip’s fix.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No stable-thread discussion found for this subject. Precedent:
`8b144dedb928e` was explicitly Cc: stable for the same warning.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `rtl8723be_hw_init()` only.
**Step 5.2: TRACE CALLERS**
Record:
- `rtl_pci_start()` (`pci.c:1737`) ← `rtl_op_start()` (`core.c:129`,
`conf_mutex`) ← mac80211 `drv_start`. Matches the reported stack.
Process context, IRQs on.
- `rtl_ps_enable_nic()` (`ps.c:26`) ←
`_rtl8723be_phy_set_rf_power_state()` IPS ERFON path (`phy.c:2534`) ←
`rtl_ps_set_rf_state()` (plain `spin_lock`, not irqsave) ←
`rtl_ips_nic_on()` (`ips_mutex`). Process/work context, IRQs on.
- USB `rtl_usb_start()` also calls `hw_init`; **RTL8723BE is PCIe-only**
(`CONFIG_RTL8723BE`).
**Step 5.3: TRACE CALLEES**
Record: MAC/FW/PHY init, register I/O, `rtl8723be_dm_init`. Long-
running, sleepable. Must not run with IRQs off for hundreds of ms —
which is why 2014 added enable, and why it is safe to drop now that
callers already have IRQs on.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace-reachable: interface up / module load / IPS wake.
Unprivileged users who can bring the interface up can hit it. Debug
kernels dump a warning on every start.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same save/enable/restore still in rtl8723ae, rtl8192ce,
rtl8188ee, rtl8192se, rtl8192cu. rtl8192cu already does
`local_irq_disable()` before restore (`8b144dedb928e`). Systematic
leftover; this patch only fixes the tested chip.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: **`v7.3-rc4-27-gf0100363d8c37`**, `VERSION=7 PATCHLEVEL=3`
(7.3.0-rc4).
- Driver and `rtl8723be_hw_init()` exist. Buggy sequence was here from
2014 until **`1b4cd55626b6f`**, which is already in **v7.3-rc1** (not
in v7.2).
- Current `hw.c` has no `local_save_flags` (grep empty). Evaluation is
of the fix’s merit for this lineage, where the bug lived for years and
the code still matches.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Expected apply: **clean**. Six-line deletion of a pattern
unchanged since 2014. No structural dependency on later rtlwifi
refactors.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This exact fix is in 7.3-rc1. No alternate fix for rtl8723be.
rtl8192cu’s 2021 workaround is a sibling, not a substitute.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **wifi / rtlwifi / rtl8723be** (Realtek RTL8723BE PCIe 802.11n).
**IMPORTANT** (common 2014–2018 laptop WiFi: ThinkPads, Razers, etc.),
not core mm/net.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature, low-churn vendor driver. Bug is old leftover, not a new-
feature regression.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific**, `CONFIG_RTL8723BE`. Warning only with
**`CONFIG_DEBUG_IRQFLAGS`** (selected by `DEBUG_LOCKDEP`). Debug/lockdep
kernels, syzbot-style configs, `panic_on_warn`. Production distro
kernels usually omit lockdep, so they would not print it — the API
misuse is still present.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every `hw_init()`: boot, `modprobe`, iface start. Not a race.
Unprivileged users can trigger via network start if the module is
loaded.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: `WARN_ONCE` in `warn_bogus_irq_restore()`. Not a panic/oops by
default. Can panic if `panic_on_warn`. Mark Rutland’s 2021 commit notes
restore-with-IRQs-enabled can desync IRQ-state tracing and break archs
whose `arch_local_irq_restore()` assumes IRQs are off. **Severity:
MEDIUM** (WARN_ON), with a documented arch/lockdep correctness angle.
Prompt lists WARN_ON triggers as a strong backport signal.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Stops a boot-time warning on a common laptop chip;
restores correct IRQ API use. Same class already taken into stable for
rtl8192cu.
- **Risk:** Very low (6-line delete). Residual risk is long IRQ-off
`hw_init` if some caller still had IRQs disabled — **not true in this
tree**.
- **Ratio:** Favorable.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real, reproduced `WARN_ONCE` on boot/`modprobe` (Razer Blade 14 2017).
- Incorrect `local_irq_restore()` usage; can confuse lockdep and some
arch restore paths.
- Six-line deletion, obviously correct once callers have IRQs enabled
(verified in `rtl_pci_start` / `rtl_op_start` / IPS).
- Tested on hardware; Acked and applied by Ping-Ke Shih.
- Same warning on rtl8192cu was **Cc: stable** in 2021.
- Driver present since 2014; no missing prerequisites.
- WARN_ON is listed as a strong stable signal.
**AGAINST:**
- Warning is gated on `CONFIG_DEBUG_IRQFLAGS`; typical production
kernels never print it.
- Not a crash, deadlock, corruption, or security hole in the default
config.
- Sibling chips left unfixed (incomplete family-wide cleanup, not a
dependency).
- Removing enable-IRQs-during-init would be harmful if an IRQ-disabled
caller still existed (none found here).
**UNRESOLVED:** Could not fetch lore HTML (403); used `b4 dig -m` mbox
instead. No stable@ thread found for this specific subject.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — hardware test + maintainer
ack; callers have IRQs on.
2. Fixes a real bug that affects users? **PASS** — lockdep/debug warning
on every start of this NIC.
3. Important issue? **PASS** (MEDIUM) — WARN_ONCE; same class previously
shipped to stable; not a production panic.
4. Small and contained? **PASS** — 6 lines, one function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — code exists; deletion applies
cleanly to the pre-fix file.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None (not a device ID, quirk table, DT, build, or docs-only
change). Qualifies as a normal small bugfix.
**Step 9.4: MAKE YOUR DECISION**
This is a small, verified fix for a real IRQ-flag warning that fires on
a common PCIe WiFi chip whenever `hw_init()` runs under debug
IRQ/lockdep configs. Callers in this tree already have IRQs enabled, so
deleting the leftover save/enable/restore is the right fix and does not
reintroduce long IRQ-off init. Benefit clearly beats risk.
---
### What the commit solves for stable users
`rtl8723be_hw_init()` restored IRQ flags while IRQs were already
enabled, which `CONFIG_DEBUG_IRQFLAGS` treats as broken and warns on
every boot/`modprobe`. The enable/restore dance was only needed when
`hw_init()` ran under `spin_lock_irqsave()`; that path has been gone
since 2014. Users of RTL8723BE (many 2014–2018 laptops) on debug kernels
get a stack dump at start; `panic_on_warn` would panic.
### Stable rules / risk vs benefit
Meets all six rules: tiny, tested, no new API, applies cleanly. Risk is
a 6-line delete. Benefit is removing a boot-time WARN and illegal
restore. Same bug class was already backported for rtl8192cu.
### Concerns
None that block a backport here: no extra commits required; sibling
chips are independent; production kernels without `DEBUG_IRQFLAGS`
simply never print the warning, but the misuse is still worth fixing.
---
Verification:
- [Phase 1] Parsed tags: Acked-by Ping-Ke Shih; Link msgid
20260609095359; no Fixes/Cc:stable/syzbot
- [Phase 1] Body: lockdep `raw_local_irq_restore() called with IRQs
enabled`; stack `rtl8723be_hw_init` → `rtl_pci_start` → `rtl_op_start`
- [Phase 2] Diff: 6 deletions in `rtl8723be_hw_init()` only (`git show
1b4cd55626b6f`)
- [Phase 3] `git merge-base --is-ancestor`: `f78bccd79ba3`,
`d3feae41a347`, `997acaf6b4b59`, `8b144dedb928e` all in HEAD
- [Phase 3] `git log -S local_save_flags -- rtl8723be/hw.c`: introduced
in `a619d1abe20cc` (2014), removed in `1b4cd55626b6f`
- [Phase 3] `8b144dedb928e`: same warning on rtl8192cu, Cc: stable,
added `local_irq_disable()` before restore
- [Phase 4] `b4 dig -c 1b4cd55626b6f`: lore match; v1→v2 message-only;
maintainer ack, no NAK
- [Phase 4] `b4 dig -m`: saved /tmp/rtl8723be-thread.mbox (721 lines);
WebFetch lore HTML 403
- [Phase 5] Callers: `rtl_pci_start` under `conf_mutex`;
`rtl_ps_enable_nic` from IPS via `spin_lock` not irqsave
- [Phase 5] Grep: sibling drivers still have `local_save_flags`;
rtl8723be file has none after the fix
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` 7.3.0-rc4
- [Phase 6] Commit in v7.3-rc1, not v7.2; current hw.c already patched
- [Phase 7] `CONFIG_RTL8723BE` PCIe 802.11n; driver added 2014
- [Phase 8] `warn_bogus_irq_restore()` is `WARN_ONCE`; `DEBUG_LOCKDEP`
selects `DEBUG_IRQFLAGS`
- UNVERIFIED: no stable@ mailing-list thread for this exact subject
(search not exhaustive beyond b4/git)
The fix is small, surgical, and meets the stable criteria for this tree.
**YES**
drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index e1f8112188949..bf7b5a32adaaf 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -1333,11 +1333,6 @@ int rtl8723be_hw_init(struct ieee80211_hw *hw)
bool rtstatus = true;
int err;
u8 tmp_u1b;
- unsigned long flags;
-
- /* reenable interrupts to not interfere with other devices */
- local_save_flags(flags);
- local_irq_enable();
rtlhal->fw_ready = false;
rtlpriv->rtlhal.being_init_adapter = true;
@@ -1443,7 +1438,6 @@ int rtl8723be_hw_init(struct ieee80211_hw *hw)
rtl8723be_dm_init(hw);
exit:
- local_irq_restore(flags);
rtlpriv->rtlhal.being_init_adapter = false;
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (96 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] wifi: rtlwifi: rtl8723be: Remove unnecessary irq save/restore in hw_init() Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] wifi: ath10k: trigger hardware recovery upon rx failures Sasha Levin
` (418 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Minghao Zhang, Florian Westphal, Jianjun Chen, Pablo Neira Ayuso,
Sasha Levin, davem, edumazet, kuba, pabeni, netfilter-devel,
coreteam, netdev, linux-kernel
From: Minghao Zhang <zhangmh25@mails.tsinghua.edu.cn>
[ Upstream commit bf80e6802273a900311b44e47c9b1a59c6d2473c ]
Commit be0502a3f2e9 ("netfilter: conntrack: tcp: only close if RST
matches exact sequence") keeps an established conntrack entry in
ESTABLISHED when an in-window RST does not match the expected sequence
number exactly, so the endpoint can validate the RST with a challenge
ACK.
The timeout selection nevertheless uses the CLOSE timeout for every RST
packet. The bug is that timeout selection is based on the packet type,
not on the state transition result: even when RST validation keeps
new_state in ESTABLISHED, the timeout is still forced to
TCP_CONNTRACK_CLOSE.
Linux TCP independently rate limits challenge ACKs per socket. A second
non-exact RST can therefore arrive after the first challenge ACK has
restored the timeout but before the rate limit expires. The second RST
lowers the timeout to 10 seconds again while the endpoint suppresses the
second challenge ACK, allowing the conntrack entry to expire while both
TCP endpoints remain established.
Using the ESTABLISHED timeout for such RSTs would avoid this short
expiration window, but it could also retain stale entries for the
five-day default because conntrack cannot reliably match the endpoint's
exact TCP state.
Use the UNACK timeout for RST packets that leave the conntrack entry in
TCP_CONNTRACK_ESTABLISHED. Exact-match RSTs and accepted RST packet
trains still fall through to timeouts[new_state], which preserves the
CLOSE timeout when conntrack accepts the RST as closing the flow.
This avoids the aggressive 10-second expiration window for non-exact
RSTs while preserving the short timeout for RSTs that conntrack accepts
as closing the flow.
Suggested-by: Florian Westphal <fw@strlen.de>
Reported-by: Minghao Zhang <zhangmh25@mails.tsinghua.edu.cn>
Reported-by: Jianjun Chen <jianjun@tsinghua.edu.cn>
Signed-off-by: Minghao Zhang <zhangmh25@mails.tsinghua.edu.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The evaluation is for the **6.6.y** tree this session opened on
(`pending-6.6` / 6.6.157). The bug is present there; the patch is a
small, real conntrack timeout fix.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: **[netfilter/conntrack/tcp] [use] use UNACK timeout for non-
closing RST packets**
- Subsystem: `netfilter: conntrack: tcp:`
- Verb: “use” here is a timeout-policy correction after RST validation
already keeps the entry ESTABLISHED.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- **Suggested-by:** Florian Westphal `<fw@strlen.de>` (conntrack
maintainer)
- **Reported-by:** Minghao Zhang `<zhangmh25@mails.tsinghua.edu.cn>`
- **Reported-by:** Jianjun Chen `<jianjun@tsinghua.edu.cn>` (two
reporters)
- **Signed-off-by:** Minghao Zhang; Pablo Neira Ayuso (netfilter
maintainer)
- **No Fixes: / Cc: stable in the committed text** (expected for this
review queue)
- **v1 and v2 on the list both had** `Fixes: be0502a3f2e9 ("netfilter:
conntrack: tcp: only close if RST matches exact sequence")`. That
tag was dropped when the patch was folded into an nf-next pull.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record:
- **Bug:** After `be0502a3f2e9`, an in-window RST that does not match
`td_maxack` leaves conntrack in ESTABLISHED so the peer can
challenge-ACK. Timeout selection still keys off packet type
(`TCP_RST_SET`) and always applies **CLOSE (10s)**.
- **Symptom:** A second non-exact RST can land after the first
challenge ACK restored the timer, but while Linux still rate-limits
challenge ACKs. The second RST drops the timer to 10s again; the
suppressed challenge ACK never refreshes it; the conntrack entry
expires while both TCP endpoints stay established. NAT/firewall then
drop a live flow.
- **Root cause:** Timeout is chosen from the RST flag, not from the
resulting state.
- **Fix:** RST that leaves `new_state == TCP_CONNTRACK_ESTABLISHED`
uses **UNACK (5 min)**. Exact-match / RST-train RSTs still fall
through to `timeouts[new_state]` (CLOSE).
- **Version info:** Tied to `be0502a3f2e9` (2019-03-01), which is in
this 6.6 tree.
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: **Not hidden.** It is a real timeout/state mismatch. v1/v2
called the 10s window **“exploitable”**. Pablo’s nf-next cover letter
softened that to “more conservative timeout”; the failure mode is
still live-session teardown through conntrack/NAT.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- Record: **one file**, `net/netfilter/nf_conntrack_proto_tcp.c`; **~3
lines** in `nf_conntrack_tcp_packet()`. Surgical single-file logic
fix.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record: After window validation, timeout selection:
- **Before:** any `index == TCP_RST_SET` →
`timeouts[TCP_CONNTRACK_CLOSE]` (10s), even if `new_state` was
forced back to ESTABLISHED (`new_state = old_state` at the non-exact
RST path).
- **After:** only RST **and** `new_state == TCP_CONNTRACK_ESTABLISHED`
→ UNACK (5 min). Closing RSTs (`tcp_conntracks[][]` maps
ESTABLISHED+RST → CLOSE, exact-seq / RST-train `break` without
restoring ESTABLISHED) still get CLOSE.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record: **[Logic / correctness]** plus a **security-relevant NAT
teardown window**. Timeout no longer contradicts the RFC 5961 “stay
ESTABLISHED for challenge ACK” path from `be0502a3f2e9`.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record: **Obviously correct** for defaults (ESTABLISHED=5 days,
UNACK=5 min, CLOSE=10s). Minimal. Regression risk is low:
- Dead flows after a bogus RST linger **5 min instead of 10s** (same
UNACK used for unacked data / out-of-window FIN|RST).
- If sysctl sets ESTABLISHED **below** UNACK (e.g. 120s NAT boxes),
this commit can **extend** the timer. Follow-up `73df81b38cb7f`
(`timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]`) closes that.
Pablo: “Not a big deal… only affect timeout configurations where
unack timeout is longer than established.” Defaults on 6.6 are fine.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Record: The unconditional RST→CLOSE timeout was added in
**`be0502a3f2e9`** (Florian Westphal, 2019-03-01, v5.1 era). It is an
ancestor of `pending-6.6`. Long-lived 6.6 code, not a new-mainline-
only bug.
**Step 3.2: FOLLOW THE FIXES: TAG**
- Record: Committed message has **no Fixes:**. Submissions targeted
**`be0502a3f2e9`**, which **is** in this tree (`git merge-base --is-
ancestor be0502a3f2e9 pending-6.6` → YES). That commit documented
CLOSE timeout for non-exact RSTs as intentional; this patch revises
that because challenge-ACK rate limiting makes the 10s window drop
live flows.
**Step 3.3: CHECK FILE HISTORY**
- Record (on `pending-6.6`): related RST work includes `2bb6d82b586ea`
(invalid-seq RST direction check) and `628d694344a02` (UNACK for out-
of-window FIN/RST). **Standalone** timeout change; not patch 2/N.
Follow-up `73df81b38cb7f` is **not** in `pending-6.6` and should ride
along once this is applied (it has `Fixes: bf80e6802273`).
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
- Record: Minghao Zhang / Jianjun Chen (Tsinghua) —
reporters/researchers, not netfilter maintainers. Weight comes from
**Suggested-by Florian** and **SOB Pablo**. No other Minghao commits
on this file in 6.6.
**Step 3.5: DEPENDENT/PREREQUISITE COMMITS**
- Record: Needs the `be0502` non-exact-RST ESTABLISHED path (present).
Uses existing `TCP_CONNTRACK_UNACK`. **Applies standalone** on 6.6.
Optional follow-up for inverted sysctl timeouts.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record:
- `b4 dig -c bf80e6802273a` → v2: https://patch.msgid.link/20260729154
654.3599616-1-zhangmh25@mails.tsinghua.edu.cn
- **v1** (2026-07-29): explicit CLOSE branch + UNACK fallback;
**Fixes:** + “exploitable 10-second expiration window”
- **v2:** Pablo/Florian simplification; UNACK only if `new_state ==
ESTABLISHED`
- Florian (https://patch.msgid.link/amoXj6UGRW8SQXBT@strlen.de): asked
to drop redundant CLOSE assignment and test a narrower condition.
Author tested ESTABLISHED-only UNACK and sent v2.
- **No NAK.** Queued in Pablo’s nf-next pull (patch 9/9), 2026-07-31:
https://lists.openwall.net/netdev/2026/07/31/313
- Jakub forwarded an AI review
(https://lists.openwall.net/netdev/2026/08/05/12): should have
Fixes:; CLOSE-for-inexact-RST was intentional in 2019; missing “only
lower, never extend” guard; closing-RST CLOSE timeout not preserved
for some non-default sysctls. The **extend** issue is exactly what
`73df81b38cb7f` later fixed.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
- Record (`b4 dig -w`): To/Cc **netfilter-devel**,
**pablo@netfilter.org**, **fw@strlen.de**, Jianjun Chen. Right
maintainers. Florian reviewed v1; Pablo merged.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: Dual Reported-by from Tsinghua. v1/v2 text: **exploitable**
10s window via RST + challenge-ACK rate limit. Concrete trigger, not
syzbot. Syzbot CI on the series: **passed**
(https://ci.syzbot.org/series/36445e46-2abc-4e64-93d2-bb558ec1f53b).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
- Record: Standalone nf-next patch (not a 9-patch dependency; the other
8 were unrelated flowtable/conncount work). Follow-up: `73df81b38cb7f`
/ https://lists.openwall.net/netdev/2026/08/10/387 — “Reported by
sashiko”.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
- Record: **No useful stable-list discussion found** for this subject
(lore.kernel.org/stable search did not surface this patch). Not
previously rejected for 6.6.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
- Record: **`nf_conntrack_tcp_packet()`** only.
**Step 5.2: TRACE CALLERS**
- Record: `pending-6.6:net/netfilter/nf_conntrack_core.c:1897` — every
tracked TCP packet. Softirq/hook path, not init-only.
**Step 5.3: TRACE CALLEES**
- Record: `nf_ct_timeout_lookup()`, `tn->timeouts[]`, later
`nf_ct_refresh_acct()`. Writes entry expiry.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: Userspace/network reachable whenever `CONFIG_NF_CONNTRACK`
tracks TCP (iptables/nftables/NAT, Docker, Kubernetes, firewalls).
**High impact.** An on-path or in-window RST injector can hit it.
Unprivileged remote: needs in-window (not exact) SEQ; that is the RFC
5961 threat model.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
- Record: Sibling branches already only **lower** timeout
(RETRANS/UNACK/zero-window). This RST branch was the odd one-out.
`nf_tcp_handle_invalid()` also uses UNACK for out-of-window FIN/RST
(`628d694`).
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
- Record: **Yes on `pending-6.6` / 6.6.157:**
```
else if (unlikely(index == TCP_RST_SET))
timeout = timeouts[TCP_CONNTRACK_CLOSE];
```
at `nf_conntrack_proto_tcp.c` ~1327–1328. Non-exact RST still does
`new_state = old_state` (~1260). `be0502a3f2e9` is an ancestor.
Candidate **`bf80e6802273a` is not** an ancestor of `pending-6.6`.
Introduced with `be0502` (2019), present for the whole 6.6 lifetime.
*(HEAD later detached at `v7.3-rc4-70` during this session; that
mainline tree already contains the fix. The stable tree this review is
for remains 6.6.157 / `pending-6.6`, where the bug is still open.)*
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
- Record: **Clean apply.** Exact before-image on `pending-6.6`. No
refactor of this hunk vs the candidate.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
- Record: `2bb6d82b586ea` is a **different** RST CLOSE issue (SYN/RST
direction). It does **not** change RST timeout selection. No earlier
UNACK-for-non-closing-RST fix in 6.6.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
- Record: **netfilter conntrack TCP** — **IMPORTANT**. Core firewall/NAT
path on virtually every router, distro firewall, and container host.
**Step 7.2: SUBSYSTEM ACTIVITY**
- Record: Mature tracker; this file still gets targeted RST/timeout
fixes. Bug is old (`be0502`), not churn from a new subsystem.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
- Record: **Conntrack/NAT users** (`CONFIG_NF_CONNTRACK`) — default on
most distro kernels. Not arch-specific.
**Step 8.2: TRIGGER CONDITIONS**
- Record: In-window, non-exact RST on an ESTABLISHED tracked flow. 6.6
still **per-socket** rate-limits challenge ACKs via
`__tcp_oow_rate_limited()` and `sysctl_tcp_invalid_ratelimit = HZ/2`
(500ms), even with global `tcp_challenge_ack_limit = INT_MAX`. A
second RST inside that window matches the commit’s scenario. Also:
single RST + lost/unseen challenge ACK (asymmetric routing) leaves a
10s expiry. **On-path attacker or sequence-in-window injection.**
**Step 8.3: FAILURE MODE SEVERITY**
- Record: **Live TCP dropped through NAT/firewall** after ~10s;
endpoints stay ESTABLISHED. Not a panic. **HIGH** (session disruption
/ DoS on middleboxes). Authors called it **exploitable**.
**Step 8.4: RISK-BENEFIT RATIO**
- Record: **Benefit high** (stops silent NAT teardown of established
sessions). **Risk low** (3-line, default UNACK < ESTABLISHED).
Residual risk: short ESTABLISHED sysctl vs longer UNACK — mitigated by
a one-line follow-up, not a reason to skip this fix.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: EVIDENCE**
**FOR:**
- Real, user-visible bug: conntrack expires while TCP stays up.
- Security-relevant (in-window RST + challenge-ACK throttle); v1/v2 said
“exploitable”; had `Fixes: be0502a3f2e9`.
- `be0502` and the buggy CLOSE timeout are in 6.6.
- Challenge-ACK **per-socket** throttle exists in 6.6 (`HZ/2`).
- Tiny, obviously correct for default timeouts; Florian suggested, Pablo
merged, author tested v2.
- Applies cleanly to `pending-6.6`.
**AGAINST:**
- Merged via **nf-next**, not nf; committed text dropped Fixes: and
“exploitable”.
- `be0502` originally **meant** CLOSE timeout for non-exact RSTs (policy
shift 10s → 5 min).
- Follow-up needed for ESTABLISHED < UNACK sysctl.
- Not a crash/corruption/deadlock.
**UNRESOLVED:** Full lore.kernel.org HTML was 403 (used `b4` + openwall
+ local mbox instead). No CVE number found.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — v2 tested by author;
Florian/Pablo; syzbot CI passed.
2. Fixes a real bug that affects users? **PASS** — NAT/firewall drop of
live TCP.
3. Important (crash/security/corruption/deadlock)? **PASS** —
exploitable middlebox teardown / DoS, not a panic.
4. Small and contained? **PASS** — ~3 lines, one function.
5. No new features or APIs? **PASS** — existing UNACK timeout.
6. Can apply to this tree? **PASS** — exact match on `pending-6.6`.
**Step 9.3: EXCEPTION CATEGORIES**
- Record: None (not a device ID/quirk/DT/build/doc exception). Ordinary
netfilter bugfix.
**Step 9.4: DECISION**
Backport. 6.6 has the 2019 RST-validation change **and** the 10s CLOSE
timeout that undermines it. The 5-minute UNACK value is the same
compromise already used for other “conntrack and endpoints disagree”
cases. Take follow-up `73df81b38cb7f` with it when possible; this commit
is still right on default 6.6 timeouts without it.
---
## What the commit solves for stable users
On 6.6 firewalls/NAT, an in-window RST that is **not** the exact next
SEQ leaves conntrack ESTABLISHED (RFC 5961) but still arms a **10s**
timer. Linux then rate-limits challenge ACKs (~500ms per socket). A
second such RST re-arms 10s with no refresh ACK, so conntrack deletes a
flow that both endpoints still consider established. That is a real
production failure and a plausible DoS on NAT.
## Stable rules / risk vs benefit
Meets the rules: small, tested, no new API, applies cleanly, fixes an
important conntrack bug. Benefit is high for a common config; regression
risk is a slightly longer hold of *stale* entries (5 min vs 10s), which
is acceptable.
## Concerns
- Pair with `73df81b38cb7f` so sysctl ESTABLISHED < UNACK cannot extend
lifetime.
- Behavior change vs 2019 “intentional CLOSE timeout” is the point of
the fix, not a blocker.
---
## Verification
- **[Phase 1]** Tags: Suggested-by Florian, two Reported-by, Pablo SOB;
committed text has no Fixes:/Cc:stable; v1/v2 mbox **did** include
`Fixes: be0502a3f2e9` and “exploitable”.
- **[Phase 2]** Diff: 3-line change in `nf_conntrack_tcp_packet()` RST
timeout arm; CLOSE preserved when `new_state != ESTABLISHED`.
- **[Phase 3]** `be0502a3f2e9` is ancestor of `pending-6.6`; candidate
is not. Blame: CLOSE-on-every-RST from `be0502`. Follow-up
`73df81b38cb7f` not in 6.6.
- **[Phase 3]** `git show
pending-6.6:net/netfilter/nf_conntrack_proto_tcp.c` lines 1327–1328:
buggy `index == TCP_RST_SET` → CLOSE.
- **[Phase 4]** `b4 dig -c bf80e6802273a`: v1+v2; Florian review
`amoXj6UGRW8SQXBT@strlen.de`; Pablo nf-next 9/9; Jakub AI review
2026-08-05; follow-up 2026-08-10 “Reported by sashiko”.
- **[Phase 4]** `b4 dig -w`: netfilter-devel, pablo, fw. `b4 dig -a`:
v1→v2 only.
- **[Phase 4]** lore.kernel.org WebFetch: **403**; used b4 mbox +
openwall. Stable list: no hit on this subject.
- **[Phase 5]** Caller: `nf_conntrack_core.c:1897` on every tracked TCP
packet.
- **[Phase 6]** First probe: `pending-6.6`, `make kernelversion`
6.6.157. Later HEAD detached at `v7.3-rc4-70` (mainline already has
the fix). Re-checked **`pending-6.6`**: VERSION 6.6.157, buggy timeout
present, exact before-image, candidate not ancestor.
- **[Phase 6]** 6.6 challenge ACK: `__tcp_oow_rate_limited` +
`sysctl_tcp_invalid_ratelimit = HZ/2`; global limit INT_MAX does
**not** disable per-socket limit.
- **[Phase 6]** Defaults on 6.6: ESTABLISHED 5 days, UNACK 5 min, CLOSE
10s.
- **[Phase 8]** Failure: NAT/conntrack drop of live TCP; severity HIGH /
security-relevant.
- **UNVERIFIED:** CVE id (none found). Could not fetch lore HTML
directly.
**YES**
net/netfilter/nf_conntrack_proto_tcp.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 91da35e2b0d8d..456721e40ed0c 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1325,8 +1325,9 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
if (ct->proto.tcp.retrans >= tn->tcp_max_retrans &&
timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
timeout = timeouts[TCP_CONNTRACK_RETRANS];
- else if (unlikely(index == TCP_RST_SET))
- timeout = timeouts[TCP_CONNTRACK_CLOSE];
+ else if (unlikely(index == TCP_RST_SET &&
+ new_state == TCP_CONNTRACK_ESTABLISHED))
+ timeout = timeouts[TCP_CONNTRACK_UNACK];
else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] wifi: ath10k: trigger hardware recovery upon rx failures
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (97 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: qmi_wwan: add Rolling Wireless RN947R Sasha Levin
` (417 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Manikanta Pubbisetty, Rameshkumar Sundaram, Baochen Qiang,
Jeff Johnson, Sasha Levin, jjohnson, linux-wireless, ath10k,
linux-kernel
From: Manikanta Pubbisetty <manikanta.pubbisetty@oss.qualcomm.com>
[ Upstream commit f78210dd4bea09090b828adc2733cad4b9916306 ]
When an error occurs during RX packet processing (e.g., MSDU done
failure), the driver sets rx_confused and drops all subsequent RX
packets until a Wi-Fi ON/OFF cycle clears the flag. This can leave
the device in a bad state where it cannot process RX data traffic.
Instead of leaving the device in such a state, trigger hardware
recovery so that such an error state can be reset and the device
can function again normally.
Tested-on: WCN3990 hw1.0 WLAN.HL.3.2.2.c10-00754-QCAHLSWMTPL-1
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00288-QCARMSWPZ-1
Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00189
Signed-off-by: Manikanta Pubbisetty <manikanta.pubbisetty@oss.qualcomm.com>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20260710060406.3323260-1-manikanta.pubbisetty@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **Linux 7.3-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
surrounding ath10k RX and recovery code is present, and this is a small,
real device-hang fix.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[wifi/ath10k] [trigger] [start hardware recovery when RX
processing fails instead of leaving the device stuck]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected)
- **Reported-by:** none
- **Tested-on:** WCN3990 hw1.0; QCA6174 hw3.2 PCI; QCA6174 hw3.2 SDIO
(three hardware/firmware combinations)
- **Reviewed-by:** Rameshkumar Sundaram, Baochen Qiang (Qualcomm ath
reviewers)
- **Acked-by:** none
- **Link:** https://patch.msgid.link/20260710060406.3323260-1-
manikanta.pubbisetty@oss.qualcomm.com
- **Cc: stable:** none (expected)
- **Signed-off-by:** Manikanta Pubbisetty (author); Jeff Johnson (ath
maintainer). Ignoring Sasha Levin SOB if present in pipeline copies;
the tree copy has none.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** On RX processing errors (e.g. MSDU_DONE not set), the driver
sets `htt->rx_confused` and then drops all further RX until a Wi-Fi
ON/OFF cycle.
- **Symptom:** Device stays in a bad state and cannot process RX data
traffic; connectivity is dead until the user toggles the interface.
- **Version info:** none in the message. The FIXME this removes dates to
2014 (`e0bd7513bbc85`, v3.19-rc1).
- **Root cause:** Error paths mark the ring confused but never reset
hardware, so the device stays inoperable.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. It is an explicit functional fix:
replace “leave device inoperable” with the existing recovery path. The
removed FIXME said the same thing since 2014.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/net/wireless/ath/ath10k/htt_rx.c` — **3 insertions, 3
deletions** (`git show --stat`: 6 lines changed).
- Functions: `ath10k_htt_rx_handle_amsdu()`,
`ath10k_htt_rx_in_ord_ind()` (two sites).
- Scope: single-file surgical error-path change.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
1. `ath10k_htt_rx_handle_amsdu()` when `ath10k_htt_rx_amsdu_pop()`
returns `< 0`: previously purged skbs, set `rx_confused`, returned.
Now also calls `ath10k_core_start_recovery(ar)`. FIXME removed.
2. `ath10k_htt_rx_in_ord_ind()` when pop-paddr-list fails: same recovery
call after `rx_confused = true`.
3. Same function when `ath10k_htt_rx_extract_amsdu()` fails: same
recovery call after purge + `rx_confused`.
All three are **error paths only**. Normal RX is unchanged.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Logic / hardware-stuck recovery.** After RX ring corruption
the driver permanently refuses RX (`if (htt->rx_confused) return -EIO`).
Recovery queues `restart_work` → `ath10k_halt()` →
`ieee80211_restart_hw()` → `ath10k_start()` → `ath10k_core_start()` →
`ath10k_htt_rx_alloc()`, which sets `htt->rx_confused = false`. That is
the same recovery used on firmware crash and WMI timeout.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct and minimal. `ath10k_core_start_recovery()`
only queues work (`queue_work(ar->workqueue_aux,
&ar->recovery_check_work)` in this tree), so it is safe from NAPI.
Existing consecutive-failure logic can WEDGE the device, so this does
not create an infinite restart loop. Risk is a brief firmware restart on
a path that was already dead. No API or data-structure changes.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Confused-without-reboot behavior introduced in **`e0bd7513bbc85`**
(“ath10k: refactor htt->rx_confused”, 2014-11-20), first in
**v3.19-rc1**.
- `handle_amsdu` error path from **`18235664e7f9a`** (Rajkumar
Manoharan, 2016).
- In-order pop/extract error paths from **`c545070e404bf`** (“ath10k:
implement rx reorder support”, 2015), v4.1 era.
- Recovery calls added by this commit **`f78210dd4bea0`**.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Historical introducer is `e0bd7513bbc85`
(ancestor of HEAD). `git merge-base --is-ancestor e0bd7513bbc85 HEAD` is
true.
**Step 3.3: CHECK FILE HISTORY**
Record: Related but independent: `7393878255e49` (skb leak on incomplete
MSDU pop) is a different patch/date/msgid. This commit is standalone
`1/1`. No prerequisite refactor in htt_rx.c.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Manikanta Pubbisetty is a Qualcomm ath10k contributor (leak fix
on the same file shortly before). Not the listed maintainer; maintainer
Jeff Johnson applied it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record:
- `ath10k_core_start_recovery()` exists since **`5dadbe4e3718`**
(v5.11-rc1) — ancestor of HEAD.
- Current implementation from **`f35a07a4842a8`** (Oct 2025) — ancestor
of HEAD; queues work, does not block in the caller.
- Can apply standalone on this tree: the function, `rx_confused`, and
both RX handlers exist.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore/msgid: https://patch.msgid.link/20260710060406.3323260-1-
manikanta.pubbisetty@oss.qualcomm.com
- `b4 dig -a`: **v1 only**, single patch, no v2/v3.
- Reviews: Baochen Qiang Reviewed-by; Rameshkumar Sundaram “Actual
change looks fine” + Reviewed-by. No NAKs, no stable nomination, no
risk flags.
- Jeff Johnson: “Applied, thanks!” (`da5d73e12af2` in ath.git; mainline
sha `f78210dd4bea0`).
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: `b4 dig -w` original To/Cc: author,
`ath10k@lists.infradead.org`, `linux-wireless@vger.kernel.org`. Applied
by **Jeff Johnson**, listed ATH10K maintainer.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. Qualcomm Tested-on on three chipsets implies
they hit RX-stuck in product testing, not a theoretical FIXME-only
cleanup.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone `[ath-next] 1/1`. The earlier skb-leak patch is not
required for this change.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org HTTP fetch returned 403. `b4 dig` thread has no
stable discussion. **UNVERIFIED** whether linux-stable ever discussed
this specific patch; no evidence it was rejected.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `ath10k_htt_rx_handle_amsdu`, `ath10k_htt_rx_in_ord_ind`; callee
`ath10k_core_start_recovery`.
**Step 5.2: TRACE CALLERS**
Record: Both called from `ath10k_htt_txrx_compl_task()` (NAPI poll): in-
order queue then `num_mpdus_ready` loop. On `-EIO` it stops processing.
That is the normal data RX completion path, not init-only.
**Step 5.3: TRACE CALLEES**
Record: `ath10k_core_start_recovery()` → `queue_work(workqueue_aux,
recovery_check_work)` → may `queue_work(workqueue, restart_work)` → halt
+ `ieee80211_restart_hw()`. No lock taken in `start_recovery`.
`in_ord_ind` holds `rx_ring.lock` while queuing work; that is safe.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace/network RX → mac80211 → NAPI → htt_rx. Reachable on
any associated ath10k interface when firmware/DMA delivers a bad MSDU or
corrupted ring. Unprivileged traffic can contribute; the actual trigger
is firmware/hardware RX error, not a crafted syscall.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same `ath10k_core_start_recovery()` already used in `pci.c`
(firmware crash), `wmi.c` (command timeout), `sdio.c`/`snoc.c`,
`debug.c`. This patch extends that pattern to RX ring failure. All
`rx_confused = true` sites in htt_rx.c are covered.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- `git describe HEAD` / `make kernelversion`: **7.3.0-rc4**.
- File and functions exist. `rx_confused` still used. Recovery API
present.
- Bug introduced v3.19; long present in this lineage.
- Working tree already contains `f78210dd4bea0` (`git merge-base --is-
ancestor` exit 0). That is the mainline commit under review, not a
reason to treat the bug as absent from this series’ code.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Hunks match this tree’s htt_rx.c. Recovery is the non-blocking
workqueue form. Expected apply: **clean** on a 7.3-era tree that still
has the pre-image; current HEAD is already post-image.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier alternative fix for “reboot on rx_confused”.
`51fc7d74ce4a1` only clears the flag on load. This is the fix that
actually starts recovery.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: **drivers/net/wireless/ath/ath10k** — **IMPORTANT** (not core
mm/fs, but QCA6174/WCN3990 are common laptop/phone Wi-Fi). Status in
MAINTAINERS: Supported; maintainer Jeff Johnson.
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Actively maintained (Qualcomm patches through 2026). The stuck-
RX behavior itself is old; the recovery helper is mature.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: **Driver-specific**, `CONFIG_ATH10K*`. QCA6174 is widely used in
PCs; WCN3990 on Qualcomm platforms.
**Step 8.2: TRIGGER CONDITIONS**
Record: RX ring pop/extract failure (incomplete MSDU, corrupted ring).
Not every packet; when it hits, RX stays dead until iface toggle. Not a
userspace exploit path.
**Step 8.3: FAILURE MODE SEVERITY**
Record: **Wi-Fi RX permanently stopped** until ON/OFF. Not a panic/UAF,
but the device is inoperable — the 2014 FIXME called it that. Severity
**HIGH** (driver hang / loss of connectivity). Consecutive recovery
failures can WEDGE, which is existing policy, not new.
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit:** Restores Wi-Fi after RX ring confusion without a manual
toggle; uses the same recovery as firmware crash.
- **Risk:** Very low (3 calls to an existing queue_work helper; error
paths only). Worst case is a restart of an already-dead radio.
- **Ratio:** Strongly favors taking the fix.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real user-visible bug: all RX dropped until Wi-Fi toggle.
- Acknowledged since 2014 in-tree FIXME.
- Small (3 calls, one file), obviously correct.
- Uses existing, NAPI-safe recovery.
- Tested on three chip/bus combinations.
- Reviewed and applied by ath maintainers; no NAKs.
- All `rx_confused = true` sites updated.
- Code and `ath10k_core_start_recovery()` exist in this 7.3-rc4 tree.
AGAINST:
- Not a crash, UAF, or security bug; workaround exists (iface bounce).
- Trigger is firmware/hardware RX error, not every boot.
- No `Fixes:`/`Cc: stable` (not a negative per the rules).
UNRESOLVED:
- lore.kernel.org WebFetch 403; thread recovered via `b4 dig -m`.
- No independent end-user bugzilla; product Tested-on only.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — three Tested-on lines, two
Reviewed-by, maintainer applied.
2. Fixes a real bug that affects users? **PASS** — RX stays dead until
ON/OFF.
3. Important issue? **PASS** — device inoperable / connectivity hang,
HIGH.
4. Small and contained? **PASS** — 3/3 lines, one file.
5. No new features or APIs? **PASS** — only calls existing recovery.
6. Can apply to the local tree? **PASS** — htt_rx.c and
`ath10k_core_start_recovery()` match; this tree is 7.3-rc4.
**Step 9.3: EXCEPTION CATEGORIES**
Record: None (not a device ID/quirk/DT/build/doc). Qualifies as a normal
bugfix.
**Step 9.4: DECISION**
This tree has the ath10k RX confused paths and the recovery helper.
Leaving `rx_confused` set without restart makes the radio unusable;
kicking `ath10k_core_start_recovery()` is the same response already used
for firmware crash and is safe from NAPI. That is a contained, tested
hang fix appropriate for this tree.
---
## What the commit solves for this tree
When htt RX pop/extract fails, ath10k previously set `rx_confused` and
discarded all later RX until a full Wi-Fi cycle. Users see a dead
receive path. The patch queues the existing hardware restart so
`ath10k_htt_rx_alloc()` clears the flag and the device can RX again.
It meets stable rules: obviously correct, real hang, ~3 lines, no new
API. Benefit is restoring Wi-Fi after ring confusion; risk is a restart
of an already-stuck device.
---
## Verification
- **[Phase 1]** Tags: Tested-on ×3, Reviewed-by ×2, Link msgid; no
Fixes/Reported-by/Cc:stable.
- **[Phase 2]** `git show --stat f78210dd4bea0`: htt_rx.c +3/-3; three
`ath10k_core_start_recovery()` calls on error paths; FIXME removed.
- **[Phase 2]** Read `ath10k_core_start_recovery()` at core.c:2534 —
`queue_work` only.
- **[Phase 2]** Read restart path: `ath10k_core_restart` →
`ieee80211_restart_hw` → `ath10k_start` → `ath10k_core_start` →
`ath10k_htt_rx_alloc()` sets `rx_confused = false` (htt_rx.c:796).
- **[Phase 3]** `git log -S` / `git describe --contains e0bd7513bbc85`:
FIXME from v3.19-rc1.
- **[Phase 3]** `ath10k_core_start_recovery` added in `5dadbe4e3718`
(v5.11-rc1); ancestor of HEAD.
- **[Phase 3]** `git merge-base --is-ancestor` for f35a07a4842a8,
5dadbe4e3718, c545070e404bf, e0bd7513bbc85: all 0.
- **[Phase 3]** Related leak commit `7393878255e49` is a separate patch,
not a prerequisite.
- **[Phase 4]** `b4 dig -c f78210dd4bea0`: msgid
20260710060406.3323260-1.
- **[Phase 4]** `b4 dig -a`: v1 only.
- **[Phase 4]** `b4 dig -w`: linux-wireless + ath10k lists.
- **[Phase 4]** `b4 dig -m`: Baochen/Rameshkumar Reviewed-by; Jeff
Johnson applied; no NAK; no Cc:stable in thread.
- **[Phase 4]** WebFetch lore.kernel.org: 403. UNVERIFIED via HTTP;
thread obtained via b4.
- **[Phase 5]** Callers: `ath10k_htt_txrx_compl_task`
(htt_rx.c:4382–4395).
- **[Phase 5]** Grep: all three `rx_confused = true` sites got recovery;
other start_recovery users are pci/wmi/sdio/snoc/debug.
- **[Phase 6]** `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; `make
kernelversion`: 7.3.0-rc4.
- **[Phase 6]** `git merge-base --is-ancestor f78210dd4bea0 HEAD`: 0
(commit is in this tree’s history).
- **[Phase 7]** MAINTAINERS: ATH10K Supported, Jeff Johnson.
- **[Phase 8]** Failure mode: RX hung until iface toggle; recovery
already rate-limited to WEDGED.
- **UNVERIFIED:** linux-stable mailing list (HTTP 403); no public non-
Qualcomm reproducer.
The fix is small, surgical, and meets the stable criteria for this
7.3-rc4 tree.
**YES**
drivers/net/wireless/ath/ath10k/htt_rx.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index d7e429041065a..e4162d2faae66 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2345,10 +2345,8 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
if (ret < 0) {
ath10k_warn(ar, "rx ring became corrupted: %d\n", ret);
__skb_queue_purge(&amsdu);
- /* FIXME: It's probably a good idea to reboot the
- * device instead of leaving it inoperable.
- */
htt->rx_confused = true;
+ ath10k_core_start_recovery(ar);
return ret;
}
@@ -3313,6 +3311,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
if (ret < 0) {
ath10k_warn(ar, "failed to pop paddr list: %d\n", ret);
htt->rx_confused = true;
+ ath10k_core_start_recovery(ar);
return -EIO;
}
@@ -3346,6 +3345,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
ath10k_warn(ar, "failed to extract amsdu: %d\n", ret);
htt->rx_confused = true;
__skb_queue_purge(&list);
+ ath10k_core_start_recovery(ar);
return -EIO;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] net: usb: qmi_wwan: add Rolling Wireless RN947R
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (98 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] wifi: ath10k: trigger hardware recovery upon rx failures Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] usb: mtu3: Fix double dereference in TP_printk Sasha Levin
` (416 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Reinhard Speyerer, Jakub Kicinski, Sasha Levin, bjorn,
andrew+netdev, davem, edumazet, pabeni, netdev, linux-usb,
linux-kernel
From: Reinhard Speyerer <rspmn@arcor.de>
[ Upstream commit 7375d38364a9aa66fb31716bcefef38aecad75d8 ]
Add Rolling Wireless RN947R 0x9300 composition:
DIAG + ADB + NMEA + MODEM + RMNET + QDSS + ADPL
T: Bus=01 Lev=01 Prnt=01 Port=02 Cnt=02 Dev#= 6 Spd=480 MxCh= 0
D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=33f8 ProdID=9300 Rev= 0.00
S: Manufacturer=Rolling Wireless
S: Product=RN947R
S: SerialNumber=xxxxxxxxxxx
C:* #Ifs= 7 Cfg#= 1 Atr=a0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option
E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option
E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 8 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan
E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#=21 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none)
E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#=22 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none)
E: Ad=8a(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Signed-off-by: Reinhard Speyerer <rspmn@arcor.de>
Link: https://patch.msgid.link/arZzuOOvLUZtdOlv@arcor.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a one-line USB ID addition to the existing `qmi_wwan` driver for
Rolling Wireless RN947R (`33f8:9300`). That is a standard stable
exception, and the ID table plus DTR quirk already exist in this 6.18.y
tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [net: usb: qmi_wwan] [add] [USB device ID for Rolling Wireless
RN947R]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Link: https://patch.msgid.link/arZzuOOvLUZtdOlv@arcor.de
- Signed-off-by: Reinhard Speyerer <rspmn@arcor.de> (author)
- Signed-off-by: Jakub Kicinski <kuba@kernel.org> (netdev maintainer,
applied)
- No Fixes: tag (expected)
- No Reported-by / Tested-by / Reviewed-by / Acked-by
- No Cc: stable (expected)
- Ignored pipeline SOB / Upstream commit marker
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug description: RN947R USB WWAN modem (`Vendor=33f8 ProdID=9300`) is
not in `qmi_wwan`’s ID table, so the RMNET/QMI network function does
not bind.
- Symptom: no `qmi_wwan` netdev for this modem; cellular data does not
come up out of the box.
- Version information: none stated.
- Root cause: missing USB ID / interface mapping. `lsusb -t`-style dump
shows If#=8 Cls=ff Sub=ff Prot=50 as the QMI/RMNET function.
Composition is DIAG + ADB + NMEA + MODEM + RMNET + QDSS + ADPL.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a hidden crash/leak fix. It is an explicit device-ID
enablement, which stable rules treat as a first-class exception.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/net/usb/qmi_wwan.c` (+1 / -0)
- Function/table: `products[]` (`static const struct usb_device_id`)
- Scope: single-file, one-line surgical ID addition
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: `33f8:9300` is unmatched; USB core does not probe `qmi_wwan`
for interface 8.
- After: `QMI_QUIRK_SET_DTR(0x33f8, 0x9300, 8)` matches
vendor/product/interface 8 and sets `qmi_wwan_info_quirk_dtr`.
- Path: USB enumeration / driver probe only. No error-path or hot-path
logic change.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: hardware enablement / USB device ID (stable exception 1).
- Mechanism: `QMI_QUIRK_SET_DTR` expands to
`USB_DEVICE_INTERFACE_NUMBER` plus DTR quirk `driver_info`. Interface
8 matches the dump (`Prot=50`, QMI/RMNET). DTR quirk is the same
pattern as Rolling RW101 (`33f8:0104`) and other Qualcomm USB WWAN
entries.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: VID/PID/interface taken from a real device dump;
match is interface-number-specific so DIAG/ADB/NMEA/MODEM/QDSS/ADPL
are not claimed.
- Minimal: one table entry, no API or structure change.
- Regression risk: very low; only `33f8:9300` is affected. Wrong
interface number would be the main risk, and the dump confirms If#=8.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Insertion sits next to Rolling RW101: `d362046021ea12`
(“net:usb:qmi_wwan: support Rolling modules”, Vanillan Wang,
2024-04-16).
- That RW101 ID is in this tree’s v6.18.57 base (`git merge-base --is-
ancestor d362046021ea1 v6.18.57` succeeded).
- This is extending an existing vendor block, not introducing a new
driver.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Not applicable. This does not revert or repair a
prior logic bug.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Recent `qmi_wwan` history is dominated by the same class of ID
additions (Quectel, Telit, MeiG, Fibocom, SIMCom).
- No prerequisite refactor is required; `products[]` and
`QMI_QUIRK_SET_DTR` are long-standing.
- Standalone: subject is not “patch X/Y”. `b4 dig -a` shows a single v1
patch.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record:
- Reinhard Speyerer has prior `qmi_wwan` ID/work in this history (e.g.
Fibocom FG132 `64761c980cbf7`).
- Not the listed maintainer; maintainer is Bjørn Mork (`MAINTAINERS`:
USB QMI WWAN NETWORK DRIVER). The patch was mailed to `bjorn@mork.no`.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record:
- Depends only on `QMI_QUIRK_SET_DTR` / `USB_DEVICE_INTERFACE_NUMBER`,
both present.
- No companion `option.c` change is in this series. Serial AT/NMEA/DIAG
auto-bind is separate; this patch alone still enables the WWAN netdev.
Can apply standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 7375d38364a9aa66fb31716bcefef38aecad75d8` matched
https://patch.msgid.link/arZzuOOvLUZtdOlv@arcor.de
- `b4 dig -a`: only v1, 2026-09-25, `[PATCH net] net: usb: qmi_wwan: add
Rolling Wireless RN947R`
- Thread (saved via `b4 dig -m`): submission, then patchwork-bot
“applied to netdev/net.git (main) by Jakub Kicinski”. No NAK, no
review objections, no later revision.
- No reviewer Cc: stable in the thread.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To `bjorn@mork.no`, Cc `netdev@vger.kernel.org`.
Subsystem maintainer was on To. Applied by netdev maintainer. No
explicit Reviewed-by in the committed message.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Evidence of a real device is the author’s
usb-devices dump (Manufacturer=Rolling Wireless, Product=RN947R,
33f8:9300). User population is owners of that modem.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Single-patch series. No `option.c` RN947R commit in this tree
(`git log --grep=RN947R -- drivers/` only finds this qmi_wwan change).
Web search did not find a matching option serial patch.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: UNVERIFIED. `WebFetch` of lore.kernel.org/stable/?q=RN947R
returned 403. No local evidence this ID was rejected for stable.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: No function body edited. Data change in `products[]`, consumed
as `qmi_wwan_driver.id_table`.
Step 5.2: TRACE CALLERS
Record:
- `products` -> `qmi_wwan_driver.id_table` -> USB core match ->
`qmi_wwan_probe()` -> `usbnet` bind path (`qmi_wwan_bind`).
- Reachable on device plug-in / boot with the modem attached. Not
interrupt or syscall hot path for other devices.
Step 5.3: TRACE CALLEES
Record: Unchanged. Bind still uses existing `qmi_wwan_bind` / DTR
handling (`qmi_wwan_change_dtr` when `QMI_WWAN_QUIRK_DTR` or `bcdUSB >=
0x0201`). Dump has `Ver= 2.10`, so DTR would be set even with
`QMI_FIXED_INTF`; `QMI_QUIRK_SET_DTR` matches sibling Rolling entries.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace-visible: plugging the modem should create a QMI WWAN
netdev and cdc-wdm control node. Trigger is ordinary USB enumeration,
not an obscure debug path.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same `QMI_QUIRK_SET_DTR(vend, prod, intf)` pattern is used
throughout `products[]`, including `33f8:0104` RW101. This is the
established way to add Qualcomm RMNET compositions.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- Local tree: `git describe HEAD` / `make kernelversion` => **6.18.57**
(`VERSION=6 PATCHLEVEL=18 SUBLEVEL=57`).
- `drivers/net/usb/qmi_wwan.c` exists; `CONFIG_USB_NET_QMI_WWAN` exists;
`QMI_QUIRK_SET_DTR` exists.
- `git show v6.18.57:drivers/net/usb/qmi_wwan.c` has Rolling RW101
(`33f8:0104`) and **does not** have `33f8:9300` / RN947R. The missing-
ID problem exists on this 6.18.y base.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. v6.18.57 context is identical around the insertion
point:
```
{QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
{QMI_FIXED_INTF(0x2dee, 0x4d22, 5)}, /* MeiG Smart SRM825L */
```
No refactor between mainline hunk and this tree.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No other RN947R ID in this tree’s `option.c` or `qmi_wwan.c` on
the v6.18.57 base. No alternate fix for 33f8:9300.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [drivers/net/usb/qmi_wwan] [IMPORTANT for WWAN users, peripheral
for everyone else]. Mature, non-staging driver used by laptops and
embedded LTE/5G modems.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Actively maintained via ID-table additions. Maintainer Bjørn
Mork; netdev applies these routinely. Mature ID-table design.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific / hardware-specific. Only Rolling Wireless
RN947R (`33f8:9300`). Other USB devices unchanged.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Plug in the modem or boot with it attached. Common for those
users. Unprivileged users do not get a new attack surface; this is bind-
table matching.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Without the ID, the RMNET function stays unbound; WWAN
networking does not work. Not a panic/UAF. Severity MEDIUM as a
functional hardware-support miss, and it still qualifies under the
device-ID exception.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: HIGH for RN947R users (modem network interface works); zero
effect on others.
- Risk: VERY LOW (1 line, existing macro, existing driver,
VID:PID:interface match).
- Ratio: strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Explicit stable exception: USB ID added to an existing driver.
- One line, obviously correct, matches a real device dump (If#=8,
Prot=50).
- Driver, macros, and Rolling vendor support already in 6.18.57.
- Applies cleanly next to RW101.
- Mailed to qmi_wwan maintainer, applied by netdev maintainer, v1 with
no NAK.
- Same pattern as many other qmi_wwan ID additions.
AGAINST:
- Does not fix a crash, UAF, or corruption.
- No Tested-by/Reviewed-by tags.
- `option.c` still lacks `33f8:9300`, so serial ports may need a
separate ID or `new_id`; that does not block the netdev ID.
UNRESOLVED:
- lore.kernel.org WebFetch 403 for stable@ search.
- Whether an option serial companion exists upstream later than this
tree.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — dump-backed ID, applied to
netdev/net.
2. Fixes a real bug that affects users? PASS — modem otherwise has no
QMI netdev.
3. Important issue? PASS under device-ID exception (hardware enablement
for existing driver).
4. Small and contained? PASS — +1 line in one table.
5. No new features or APIs? PASS — no new driver, syscall, or userspace
API; ID only.
6. Can apply to the local tree? PASS — v6.18.57 has identical context.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Device ID addition to existing driver (USB ID in `qmi_wwan`).
Step 9.4: MAKE YOUR DECISION
This should be backported to this 6.18.y tree. It is the standard, low-
risk USB ID pattern stable already takes for `qmi_wwan`.
What problem it solves: RN947R owners on 6.18.y get a working QMI/RMNET
interface instead of an unbound USB function.
Risk vs benefit: one matching table entry vs. a non-working WWAN modem.
Benefit dominates.
Concerns: serial `option` binding is incomplete without a separate ID;
that is independent and not a reason to drop this netdev ID.
Verification:
- [Phase 1] Parsed subject/tags/body: device-ID add; Link to
patch.msgid.link; SOB Speyerer + Kicinski; no Fixes/syzbot.
- [Phase 2] Diff: +1 line in `products[]`; `QMI_QUIRK_SET_DTR(0x33f8,
0x9300, 8)` matches dump If#=8.
- [Phase 2] Read `QMI_QUIRK_SET_DTR` / `qmi_wwan_info_quirk_dtr` / DTR
logic at bind (lines 804–825, 938–958).
- [Phase 3] `git blame` around insertion: RW101 from `d362046021ea12`
(2024); ancestor of v6.18.57.
- [Phase 3] `git log --oneline -20 -- drivers/net/usb/qmi_wwan.c`: many
similar ID adds; this is standalone.
- [Phase 3] `git log --author='Reinhard Speyerer' -- drivers/net/usb/`:
prior qmi_wwan ID work.
- [Phase 4] `b4 dig -c 7375d38364a9…`: lore URL found; `-a` v1 only;
`-w` To bjorn@mork.no Cc netdev; `-m` thread is submit + applied-bot,
no NAK.
- [Phase 4] lore WebFetch 403; used b4 mbox instead.
- [Phase 4] WebSearch: no option.c RN947R companion found.
- [Phase 5] `products` -> `qmi_wwan_driver.id_table` ->
`qmi_wwan_probe`; `MODULE_DEVICE_TABLE(usb, products)`.
- [Phase 5] `option.c` has other 33f8 IDs, not 0x9300.
- [Phase 6] `git describe HEAD` / Makefile: 6.18.57. `git show
v6.18.57:drivers/net/usb/qmi_wwan.c` has RW101, lacks RN947R. Apply
context matches.
- [Phase 6] `git merge-base --is-ancestor 7375d38364a9 HEAD` is false
(upstream SHA not this history); evaluate against local 6.18.y code,
not that SHA.
- [Phase 7] MAINTAINERS: USB QMI WWAN NETWORK DRIVER, M: Bjørn Mork.
- [Phase 8] Failure mode: unbound RMNET on this VID:PID only; risk
confined to that device.
- UNVERIFIED: stable@ lore discussion (HTTP 403).
**YES**
drivers/net/usb/qmi_wwan.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index aa66a30e56cdc..85d2daae805fd 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1453,6 +1453,7 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
{QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
+ {QMI_QUIRK_SET_DTR(0x33f8, 0x9300, 8)}, /* Rolling RN947R RMNET */
{QMI_FIXED_INTF(0x2dee, 0x4d22, 5)}, /* MeiG Smart SRM825L */
{QMI_QUIRK_SET_DTR(0x2dee, 0x4d63, 0)}, /* MeiG SRM813Q w/ Modem(PPP) */
{QMI_QUIRK_SET_DTR(0x2dee, 0x4d64, 0)}, /* MeiG SRM813Q w/ NMEA */
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] usb: mtu3: Fix double dereference in TP_printk
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (99 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: qmi_wwan: add Rolling Wireless RN947R Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:18 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: notify parent directory leases on child create Sasha Levin
` (415 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Vladimir Murzin, Paul E. McKenney, Mark Rutland, Steven Rostedt,
Sasha Levin, chunfeng.yun, gregkh, linux-usb, linux-arm-kernel,
linux-mediatek, linux-kernel
From: Vladimir Murzin <vladimir.murzin@arm.com>
[ Upstream commit cfb3293c4573289f11f913611f530ea6b1926d67 ]
Paul reported kernel splat:
[ 0.000000] TRACE EVENT ERROR: Event mtu3_gadget_ep_set_halt has double dereference in TP_printk: &REC->gpd_ring->dma
[ 0.000000] ------------[ cut here ]------------
[ 0.000000] Event mtu3_gadget_ep_set_halt has double dereference in TP_printk: &REC->gpd_ring->dma
[ 0.000000] WARNING: kernel/trace/trace_events.c:420 at test_double_dereference+0x144/0x14c, CPU#0: swapper/0/0
[ 0.000000] Modules linked in:
[ 0.000000] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.3.0-rc1 #15247 PREEMPT
[ 0.000000] Hardware name: linux,dummy-virt (DT)
[ 0.000000] pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 0.000000] pc : test_double_dereference+0x144/0x14c
[ 0.000000] lr : test_double_dereference+0x144/0x14c
[ 0.000000] sp : ffffc80aa7633bf0
[ 0.000000] x29: ffffc80aa7633bf0 x28: ffffc80aa7c0f047 x27: 000508b58019388f
[ 0.000000] x26: 0000000000000003 x25: 0000000000000007 x24: ffffc80aa5fceff8
[ 0.000000] x23: ffffc80aa7c0f05a x22: ffffc80aa64edfe8 x21: ffffc80aa7c0fce8
[ 0.000000] x20: ffffc80aa7c0f047 x19: 0000000000000013 x18: 0000000000000001
[ 0.000000] x17: 6572656420656c62 x16: 756f642073616820 x15: 746c61685f746573
[ 0.000000] x14: 0000000000000000 x13: ffff000139d90000 x12: 0000000000000045
[ 0.000000] x11: 00000000000000cf x10: ffff00013f546428 x9 : ffff000139d90000
[ 0.000000] x8 : 3fffffffffffc000 x7 : 0000000000000001 x6 : 0000000000000001
[ 0.000000] x5 : ffff00013f4e6440 x4 : 0000000000000000 x3 : 0000000000000000
[ 0.000000] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffffc80aa764a700
[ 0.000000] Call trace:
[ 0.000000] test_double_dereference+0x144/0x14c (P)
[ 0.000000] trace_event_raw_init+0x37c/0x5d8
[ 0.000000] event_init+0x34/0xc0
[ 0.000000] trace_event_init+0xec/0x588
[ 0.000000] trace_init+0x24/0x6e0
[ 0.000000] start_kernel+0x4a0/0x8ec
[ 0.000000] __primary_switched+0x88/0x90
[ 0.000000] irq event stamp: 0
[ 0.000000] hardirqs last enabled at (0): [<0000000000000000>] 0x0
[ 0.000000] hardirqs last disabled at (0): [<0000000000000000>] 0x0
[ 0.000000] softirqs last enabled at (0): [<0000000000000000>] 0x0
[ 0.000000] softirqs last disabled at (0): [<0000000000000000>] 0x0
[ 0.000000] ---[ end trace 0000000000000000 ]---
[ 0.000000] TRACE EVENT ERROR: Event mtu3_gadget_ep_disable has double dereference in TP_printk: &REC->gpd_ring->dma
[ 0.000000] TRACE EVENT ERROR: Event mtu3_gadget_ep_enable has double dereference in TP_printk: &REC->gpd_ring->dma
Which also observed by Mark and myself.
The splat it result of new check introduced by b5cc230af5e5 ("tracing:
Warn when an event dereferences a pointer in TP_printk()") which
correctly catches issue with %pad dereferencing the address saved in
the ring buffer. TP_fast_assign() logic gets executed when the
tracepoint is triggered, however the TP_printk() is executed when the
user reads the trace buffer which could be seconds, minutes, hours,
days, even months later and nothing guarantee that __entry->gpd_ring
pointer will still be pointing to what it was when it was recorded.
Fix the issue by capturing immediate value of gpd_ring.dma when trace
point is triggered.
Reported-by: Paul E. McKenney <paulmck@kernel.org>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
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: **[usb/mtu3]** **[Fix]** Double dereference in `TP_printk` for
the `mtu3_log_ep` trace class
(`mtu3_gadget_ep_enable/disable/set_halt`).
**Step 1.2: Tags**
Record:
- **Reported-by:** Paul E. McKenney
- **Tested-by:** Mark Rutland
- **Reviewed-by:** Steven Rostedt (tracing maintainer)
- **Signed-off-by:** Vladimir Murzin (author); Paul E. McKenney (merged
via his tree)
- **No Fixes:** tag (expected for this review)
- **No Cc: stable** (expected)
- No syzbot, no CVE, no bugzilla Link
- Ignore pipeline “Upstream commit” / Sasha Levin SOB
Notable: three independent observers (Paul, Mark, the author). Rostedt
reviewed it.
**Step 1.3: Body**
Record:
- **Bug:** `TP_printk` uses `%pad` with `&REC->gpd_ring->dma`, i.e. it
follows a pointer stored in the ring buffer when the trace is printed,
not when it is recorded.
- **Symptom that motivated the patch:** boot `WARNING` in
`test_double_dereference()` on 7.3.0-rc1 (`linux,dummy-virt`), events
`mtu3_gadget_ep_set_halt/disable/enable`.
- **Root cause (author):** check added by `b5cc230af5e5` (“tracing: Warn
when an event dereferences a pointer in TP_printk()”).
`TP_fast_assign()` runs at the tracepoint; `TP_printk()` can run much
later, when `__entry->gpd_ring` may be stale.
- **Fix:** snapshot `mep->gpd_ring.dma` into a `dma_addr_t` field at
assign time and print `&__entry->gpd_ring_dma`.
- **Versions in the message:** 7.3.0-rc1 only. Mailing list later says
the splat was still present in 7.3-rc5/rc6.
Linus’s merge of `8fc6e594884a` describes the same bug as pre-existing:
it can dump garbage traces because `TP_printk()` may run after the
pointed-to memory is gone. Extra tracing checks only **exposed** it.
**Step 1.4: Hidden bug fix?**
Record: Not hidden. It is an explicit tracing UAF/stale-pointer fix. The
boot WARN is how it was found; the real defect is delayed dereference of
a saved kernel pointer.
---
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/usb/mtu3/mtu3_trace.h` only (+3 / −1; 4-line class)
- Function/class: `DECLARE_EVENT_CLASS(mtu3_log_ep)` (shared by
`mtu3_gadget_ep_enable`, `mtu3_gadget_ep_disable`,
`mtu3_gadget_ep_set_halt`)
- Scope: single-file surgical tracing fix
**Step 2.2: Code flow**
Record: **Before:** `TP_fast_assign` stores `__entry->gpd_ring =
&mep->gpd_ring`. `TP_printk` prints `%p/%pad` with `__entry->gpd_ring,
&__entry->gpd_ring->dma`. **After:** also stores `__entry->gpd_ring_dma
= mep->gpd_ring.dma` and prints `&__entry->gpd_ring_dma`. Affected path
is trace **print**, not gadget I/O.
Verified in this tree’s `lib/vsprintf.c` `address_val()`: `%pad` does
`*(const dma_addr_t *)addr`. The old argument therefore both follows
`gpd_ring` and then dereferences `.dma`.
**Step 2.3: Bug mechanism**
Record: **Memory safety / delayed pointer dereference in tracing (UAF or
garbage).** `%p` of the saved pointer is safe; `%pad` is not. `gpd_ring`
is embedded in `struct mtu3_ep` (`mtu3.h`). `mtu3_gpd_ring_free()`
`memset`s the ring on disable; the `mtu3_ep` itself is freed on unbind.
Reading traces after unbind is a use-after-free. Reading after disable
but before unbind can print a later (zeroed) DMA address instead of the
recorded one.
**Step 2.4: Fix quality**
Record: Obviously correct and minimal. `%pad` still gets a `dma_addr_t
*`, now into the ring-buffer entry. The missing semicolon on the new
assign is harmless: `TP_fast_assign` is expanded with a trailing `;`. No
API/locking/hot-path change. Regression risk is very low. The leftover
`__field(struct mtu3_gpd_ring *, gpd_ring)` is still only printed with
`%p`.
---
## Phase 3: Git history
**Step 3.1: Blame**
Record: Buggy `mtu3_log_ep` pattern comes from `83374e035b628` (“usb:
mtu3: add tracepoints to help debug”, Chunfeng Yun, 2019-03-21). Present
in this tree (`git merge-base --is-ancestor 83374e035b628 HEAD`
succeeded). Long-lived, not recent code.
**Step 3.2: Fixes: tag**
Record: None on the merged commit. An earlier unused submission
(Shixiong Ou, 2026-08-28) tagged `Fixes: 83374e035b62`. That introducing
commit **is** in this tree.
**Step 3.3: File history**
Record (path-limited log):
- `83374e035b628` add tracepoints
- later style/`__vstring`/`__assign_str` churn
- this fix
Standalone; not patch X/Y. No prerequisite refactor in this file beyond
what 6.18 already has (`__assign_str(name)` without a second argument is
already here).
**Step 3.4: Author**
Record: Vladimir Murzin is not the mtu3 maintainer (that is Chunfeng
Yun, CC’d). He is an ARM engineer fixing a splat he, Paul, and Mark hit.
Rostedt reviewed. Paul merged it when USB maintainers were slow (splat
still in 7.3-rc6).
**Step 3.5: Dependencies**
Record: None. Uses existing `dma_addr_t`, `TP_*`, and
`mep->gpd_ring.dma`. No new tracing helpers. `b5cc230af5e5` is the
detector, **not** a prerequisite for the fix.
---
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
Record:
- `b4 dig -c cfb3293c4573289f11f913611f530ea6b1926d67` → https://patch.m
sgid.link/20260922103756.104846-1-vladimir.murzin@arm.com
- `b4 dig -a`: single revision (v1 only)
- Thread: ping for 7.3-rc5/rc6 splat; Paul offered to merge because the
WARN broke his tests; later merged and Linus pulled it
- No NAK. No reviewer asked for `Cc: stable`
- lore.kernel.org fetch returned 403; thread recovered via `b4 dig -m`
**Step 4.2: Recipients (`b4 dig -w`)**
Record: linux-usb, linux-arm-kernel, linux-mediatek, linux-kernel,
Chunfeng Yun, Greg KH, Steven Rostedt, Paul McKenney, Mark Rutland.
Right lists and maintainers.
**Step 4.3: Bug report**
Record: Reproduced by Paul, Mark, and Vladimir on 7.3-rc1+ (dummy-virt).
Independent earlier patch from Shixiong Ou describes the same WARN and
the same stale-pointer/UAF. Severity for **those** kernels is a boot
WARN whenever `CONFIG_USB_MTU3` is built. That WARN is **not** in
6.18.y.
**Step 4.4: Series**
Record: Standalone. Duplicate independently submitted by Shixiong Ou
(same approach, field named `gpd_dma`). Murzin’s version is what merged.
**Step 4.5: Stable list**
Record: No useful hit on lore stable for this subject. Not a documented
“do not backport.”
---
## Phase 5: Semantic / call graph
**Step 5.1: Functions**
Record: `mtu3_log_ep` class; events `mtu3_gadget_ep_enable`,
`mtu3_gadget_ep_disable`, `mtu3_gadget_ep_set_halt`.
**Step 5.2: Callers**
Record (this tree):
- `mtu3_gadget_ep_enable()` — `drivers/usb/mtu3/mtu3_gadget.c:202`
- `mtu3_gadget_ep_disable()` — line 214 (before `mtu3_ep_disable()` /
`mtu3_gpd_ring_free()`)
- `mtu3_gadget_ep_set_halt()` — line 404
These are USB gadget ep ops: enable/disable/halt from gadget drivers /
configfs. Common on MediaTek gadget/OTG, not a syscall of its own.
**Step 5.3: Callees**
Record: TRACE_EVENT assign/print only. No alloc/lock/I/O in the changed
code. `%pad` → `address_val()` → dereference `dma_addr_t *`.
**Step 5.4: Reachability**
Record: Recording: gadget ep enable/disable/halt with these events on.
Printing: reading the trace buffer. UAF: print after `mtu3_ep` is freed
(driver unbind). Boot WARN: only if `test_double_dereference()` exists
(it does not here). Unprivileged users normally cannot enable tracefs.
**Step 5.5: Similar patterns**
Record: Other mtu3 events print saved pointers with `%p` only (safe).
Same class already in this 6.18.y tree: `0b0d2f9db2406` (“eth: ice:
don't dereference pointers from TP_printk()”), also written against
`b5cc230af5e5`, and it **is** an ancestor of `v6.18.57`.
---
## Phase 6: This checkout only
**Step 6.1: Does the buggy code exist?**
Record: **Yes, in v6.18.57.** `git describe HEAD` →
`v6.18.57-155-gcdf239ca885b2`; `make kernelversion` → **6.18.57**.
v6.18.57 `mtu3_trace.h` still has `__entry->gpd_ring,
&__entry->gpd_ring->dma`. Introduced 2019. `git merge-base --is-ancestor
dff6c93cf7131 v6.18.57` failed (fix not in 6.18.57).
`test_double_dereference` is **absent** from `kernel/trace/`
(`b5cc230af5e5` is not an ancestor of HEAD).
**Step 6.2: Backport difficulty**
Record: **Clean apply.** `git diff v6.18.57 dff6c93cf7131 --
drivers/usb/mtu3/mtu3_trace.h` is exactly this 4-line change. Context
matches 6.18 (`__assign_str(name)` already present).
**Step 6.3: Related fix already here?**
Record: No other mtu3 `TP_printk` fix in `v6.18..v6.18.57`. The ice
analogue **is** already in 6.18.57. That does not replace this mtu3 bug.
---
## Phase 7: Subsystem context
**Step 7.1**
Record: **drivers/usb/mtu3** — MediaTek USB3 dual-role. Criticality:
**PERIPHERAL/IMPORTANT for MTK** (`CONFIG_USB_MTU3`, `depends on
ARCH_MEDIATEK || COMPILE_TEST`). Tracepoints compiled with the driver
when `CONFIG_TRACEPOINTS` is on.
**Step 7.2**
Record: Mature driver (tracepoints since 2019). Recent 6.18.y mtu3 fixes
include DMA unmap on queue failure and suspend-with-gadget. Not staging.
---
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
Record: MediaTek USB3 gadget users who enable these ftrace events and
later print the buffer. Distro kernels that build mtu3 for
`COMPILE_TEST` do **not** get the 7.3 boot WARN here, because that check
is missing.
**Step 8.2: Trigger**
Record: Not every boot on 6.18.y. Needs `CONFIG_USB_MTU3` + tracepoints
+ enable these events + later print. UAF additionally needs the
endpoint/device object to have been freed. Not unprivileged. The 7.3
boot WARN fires even on dummy-virt; **that path does not exist in this
tree**.
**Step 8.3: Failure mode**
Record:
- On 7.3+: boot `WARNING` — **does not apply to 6.18.57**
- On this tree: delayed deref → **garbage DMA address in traces**, or
**UAF/oops** if `mtu3_ep` was freed — severity **HIGH** when hit,
**MEDIUM** overall because the trigger is a debug path
**Step 8.4: Risk vs benefit**
Record: **Benefit:** closes a real stale-pointer/UAF in mtu3 gadget
traces; same class already taken for ice on this series. **Risk:** very
low (3 insertions, print-time only). Ratio favors backport.
---
## Phase 9: Synthesis
**Step 9.1: Evidence**
For:
- Real delayed dereference of a kernel pointer from the trace buffer
(`%pad` confirmed to dereference)
- Buggy code present in this 6.18.y tree since 2019
- Small, obviously correct, applies cleanly
- Reviewed by Rostedt; reported/tested by McKenney and Rutland
- Same class (`TP_printk` must not follow saved pointers) already in
v6.18.57 for ice
- No new API/feature; no series dependency
Against:
- The boot splat that drove the patch **cannot happen here**
(`test_double_dereference` / `b5cc230af5e5` not in 6.18.y)
- Debug/tracing path, MediaTek-specific, needs events enabled
- Failure is often wrong trace text rather than a production USB failure
- No `Cc: stable` in review (not a negative per the rules)
Unresolved: lore.kernel.org HTTP 403 (thread read from `b4` mbox
instead).
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** (Rostedt Reviewed-by, Mark
Tested-by, logic is local)
2. Real bug that affects users? **PASS** (stale pointer / UAF when
traces are printed)
3. Important (crash/security/corruption/deadlock)? **PASS** (UAF/oops
possible on print after free; garbage traces otherwise). The 7.3 boot
WARN is not the important part **for this tree**.
4. Small and contained? **PASS** (one header, 4 lines)
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** (clean vs v6.18.57)
**Step 9.3: Exception category**
Record: None (not a device ID/quirk/DT/build/docs exception). It is a
normal small bugfix.
**Step 9.4: Decision**
The 7.3 boot WARN is not a reason to take this on 6.18.y. The reason to
take it is the pre-existing `TP_printk` dereference, which **is** in
this tree, is a real UAF/garbage-print bug, is a 4-line no-brainer, and
matches a fix this series already accepted for ice.
---
## What this means for 6.18.y users
`mtu3_log_ep` stores `&mep->gpd_ring` and later does `%pad` on
`&gpd_ring->dma`. Print can happen long after disable/unbind. That is a
real bug in this tree. The patch only snapshots `gpd_ring.dma` at event
time. It does not change gadget behavior.
## Verification
- **[Phase 1]** Parsed tags: Reported-by Paul McKenney, Tested-by Mark
Rutland, Reviewed-by Steven Rostedt; no Fixes/Cc-stable
- **[Phase 2]** Diff: +`gpd_ring_dma` field, assign `mep->gpd_ring.dma`,
print `&__entry->gpd_ring_dma`
- **[Phase 2]** `%pad` in `lib/vsprintf.c` `address_val()`: `num =
*(const dma_addr_t *)addr`
- **[Phase 2]** `struct mtu3_ep` has embedded `struct mtu3_gpd_ring
gpd_ring`; `mtu3_gpd_ring_free()` memsets it
- **[Phase 3]** Blame: `83374e035b628` (2019) introduced the pattern;
ancestor of HEAD
- **[Phase 3]** `git merge-base --is-ancestor b5cc230af5e5 HEAD` failed;
no `test_double_dereference` in this tree
- **[Phase 3]** Author log on `drivers/usb/`: this commit plus unrelated
xhci work
- **[Phase 4]** `b4 dig -c cfb3293c4573`: msgid
`20260922103756.104846-1-vladimir.murzin@arm.com`; v1 only
- **[Phase 4]** `b4 dig -w`: USB/Mediatek lists, Greg KH, Chunfeng Yun,
Rostedt
- **[Phase 4]** mbox: Paul merged after 7.3-rc5/rc6 pings; no NAK; no
stable nomination
- **[Phase 4]** UNVERIFIED: live lore.kernel.org page (403)
- **[Phase 5]** Callers: `mtu3_gadget_ep_enable/disable/set_halt` in
`mtu3_gadget.c`
- **[Phase 6]** `git describe HEAD` = v6.18.57-155-gcdf239ca885b2;
kernelversion 6.18.57
- **[Phase 6]** v6.18.57 still has `&__entry->gpd_ring->dma`; fix not an
ancestor of v6.18.57
- **[Phase 6]** File diff vs v6.18.57 is exactly this patch (clean)
- **[Phase 6]** ice TP_printk analogue `0b0d2f9db2406` **is** in
v6.18.57
- **[Phase 8]** Boot WARN not reachable here; UAF/garbage on delayed
print is
The fix is small, correct, already matches this tree’s context, and
closes a real tracing UAF, not a 7.3-only WARN.
**YES**
drivers/usb/mtu3/mtu3_trace.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/mtu3/mtu3_trace.h b/drivers/usb/mtu3/mtu3_trace.h
index 89870175d6356..9aaa167d69c13 100644
--- a/drivers/usb/mtu3/mtu3_trace.h
+++ b/drivers/usb/mtu3/mtu3_trace.h
@@ -224,6 +224,7 @@ DECLARE_EVENT_CLASS(mtu3_log_ep,
__field(unsigned int, flags)
__field(unsigned int, direction)
__field(struct mtu3_gpd_ring *, gpd_ring)
+ __field(dma_addr_t, gpd_ring_dma)
),
TP_fast_assign(
__assign_str(name);
@@ -235,12 +236,13 @@ DECLARE_EVENT_CLASS(mtu3_log_ep,
__entry->flags = mep->flags;
__entry->direction = mep->is_in;
__entry->gpd_ring = &mep->gpd_ring;
+ __entry->gpd_ring_dma = mep->gpd_ring.dma
),
TP_printk("%s: type %s maxp %d slot %d mult %d burst %d ring %p/%pad flags %c:%c%c%c:%c",
__get_str(name), usb_ep_type_string(__entry->type),
__entry->maxp, __entry->slot,
__entry->mult, __entry->maxburst,
- __entry->gpd_ring, &__entry->gpd_ring->dma,
+ __entry->gpd_ring, &__entry->gpd_ring_dma,
__entry->flags & MTU3_EP_ENABLED ? 'E' : 'e',
__entry->flags & MTU3_EP_STALL ? 'S' : 's',
__entry->flags & MTU3_EP_WEDGE ? 'W' : 'w',
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] ksmbd: notify parent directory leases on child create
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (100 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] usb: mtu3: Fix double dereference in TP_printk Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: use vb2_video_unregister_device Sasha Levin
` (414 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable; +Cc: Namjae Jeon, Sasha Levin, linux-cifs, linux-kernel
From: Namjae Jeon <linkinjeon@kernel.org>
[ Upstream commit abe5acb34282206c2a6303d0e09b3165b1addf0e ]
BVT_DirectoryLeasing_ReadWriteHandleCaching requires a parent directory
lease break notification when another client creates a child in the
leased directory. A child CREATE without a lease context did not notify
the parent lease holders because the notification path expected a
non-NULL lease context.
Allow the parent lease notification helper to handle a NULL child lease
context and notify matching parent leases. Invoke it after a child is
created without a lease context while preserving the existing lease-key
filtering for requests that provide one.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111** (`pending-6.12`). Directory leasing is
already advertised here, and this patch fills a hole in that existing
notification path.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[ksmbd] [notify] parent directory leases on child create**
- Subsystem: `ksmbd` (kernel SMB3 server)
- Verb: “notify” — protocol-correctness / missing-event fix, not a
feature add
- Claimed intent: send a parent directory lease break when a child is
created
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Verified from `git log -1 --format='%B' abe5acb342822`:
- **Signed-off-by: Namjae Jeon** `<linkinjeon@kernel.org>` (author and
committer; ksmbd maintainer)
- **No Fixes:** tag (expected for this review pipeline)
- **No Cc: stable** (expected)
- **No Reported-by / Tested-by / Reviewed-by / Acked-by / Link**
- Ignore pipeline-added Sasha Levin SOB / `[Upstream commit …]` if
present on a candidate copy
Notable: maintainer-authored, no external review tags. The body cites
Microsoft BVT `BVT_DirectoryLeasing_ReadWriteHandleCaching`.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** A child CREATE with no lease context never notifies holders
of a parent directory lease, because
`smb_send_parent_lease_break_noti()` assumed `lctx` was non-NULL.
- **Symptom:** Windows BVT `BVT_DirectoryLeasing_ReadWriteHandleCaching`
fails; SMB3 clients with a directory lease keep a stale directory
cache after another client creates a child.
- **Version info:** None in the message. Introducing code is from
v6.7-rc6 (`d47d9886aeef7`).
- **Root cause:** Notification only ran on CREATE-with-lease-context;
the helper immediately used `lctx->version`.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a disguised cleanup.** This is an explicit protocol bug
fix: missing lease-break on a common CREATE path. Not a refactor or new
API.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `fs/smb/server/oplock.c`: +5/−4 in
`smb_send_parent_lease_break_noti()`
- `fs/smb/server/smb2pdu.c`: +3 in `smb2_open()`
- **Scope:** 8 insertions, 4 deletions; single-subsystem surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Verified against local `smb_send_parent_lease_break_noti()`
(`fs/smb/server/oplock.c` ~1214) and `smb2_open()` (~3521):
Hunk 1 (helper guard):
- **Before:** `if (lctx->version != 2) return;` — NULL `lctx` would
crash; callers never passed NULL.
- **After:** `if (lctx && lctx->version != 2) return;` — NULL means
“notify matching parent leases”.
Hunk 2 (filter condition):
- **Before:** Always used `lctx->flags` / `lctx->parent_lease_key` to
skip the same parent lease.
- **After:** `!lctx || (existing parent-key filter)` — NULL child
context breaks all active parent directory leases; lease-key filtering
is unchanged when `lctx` is present.
Hunk 3 (`smb2_open`):
- **Before:** Parent notify only inside `if (req_op_level ==
SMB2_OPLOCK_LEVEL_LEASE && lc)`.
- **After:** Also `if (created && !lc)
smb_send_parent_lease_break_noti(fp, NULL);` in the oplocks-enabled
branch.
`created` is set when `smb2_creat()` succeeds (`smb2pdu.c` ~3301–3313).
`lc` is only set when a lease create context is parsed (~3017, ~3061).
The two notify sites are mutually exclusive (`!lc` vs `lc`).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Logic / protocol correctness]** Directory leasing is
advertised (`SMB2_GLOBAL_CAP_DIRECTORY_LEASING` in `smb2ops.c`; docs say
“Directory leases(v2 lease) Supported”). CREATE without a lease context
never broke the parent directory lease. The helper change is a NULL-safe
call convention so that path can notify. Not UAF/leak/race/overflow by
itself; the failure mode is stale client directory cache.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: short-circuit `!lctx` avoids `lctx->flags` deref;
reuses the existing break helper.
- Minimal; no unrelated edits.
- Regression risk **low**: extra breaks only on real child create with
no lease context, which MS-SMB2 requires. Locking matches the existing
`smb_send_parent_lease_break_noti(fp, lc)` call a few lines later
(`p_ci->m_lock` then `oplock_break_drain_none()`).
- No public API / data-structure change.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Buggy helper and the lease-context-only call site: **`d47d9886aeef7`**
(“ksmbd: send v2 lease break notification for directory”, Namjae Jeon,
2023-12-08).
- First contained in **`v6.7-rc6`**. Present in this 6.12 tree (`git
merge-base --is-ancestor d47d9886aeef7 HEAD` → yes).
- Directory leasing capability: **`18dd1c367c31d`** (“ksmbd: set v2
lease capability”), also in this tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** The incomplete behavior was introduced by
`d47d9886aeef7`, which is in this tree.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Same class already in this tree: `3fc74c65b3674` “send lease break
notification on FILE_RENAME_INFORMATION” (smb2.lease.v2_epoch2);
`7f58458e9db92` “break RH leases before delete-on-close”.
- Later on `all-next`, `0e753899627b5` only changes
`oplock_break_drain_none(&brk_list)` → `(&brk_list, p_ci)` — **already
present locally** via `5de0527f78243`. Not a prerequisite of this
patch.
- `git log all-next -S 'created && !lc'` shows **only** `abe5acb342822`
— no follow-up rewrite of this call.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Namjae Jeon is listed as **KERNEL SMB3 SERVER (KSMBD)**
maintainer in `MAINTAINERS`. Recent local ksmbd lease work includes
lease lookup, RH lease break, lease context validation.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: **Standalone.** Uses existing
`smb_send_parent_lease_break_noti()`, `created`, and `lc`. `git show
abe5acb342822 | git apply --check` **succeeds** on this tree (oplock.c
offset −232, smb2pdu.c offset −1136).
Candidate SHA on `all-next`: **`abe5acb342822`** (in `ksmbd-
for-7.3-rc1`, described as `v7.3-rc1~77^2~20`). **Not** in HEAD.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c abe5acb342822`: lore search returned server errors; **no
thread URL**.
- lore.kernel.org WebFetch: **403**.
- Found via LKML: [GIT PULL] ksmbd server update for 7.3-rc1 (Namjae
Jeon, 2026-08-23) lists this commit and calls out **“parent directory
lease notifications”** among protocol-compatibility fixes.
- Linus merge `61a09cfc12147` uses the same wording.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: No Reviewed-by. Author is the maintainer and committed it to the
ksmbd tree. Recipients of the original mail **unverified** (lore 403 /
b4 failure).
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla. Trigger is Microsoft BVT
**BVT_DirectoryLeasing_ReadWriteHandleCaching** (Windows protocol test:
client A holds a directory RWH lease; client B creates a child without a
lease context; A must get a break).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Not labeled `N/M`. Adjacent commits are AppInstanceVersion
takeover / durable reconnect — unrelated. Independent.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** (lore 403). No evidence it was rejected for
stable. Absence of Cc: stable is expected here.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `smb_send_parent_lease_break_noti()`, `smb2_open()`.
**Step 5.2: TRACE CALLERS**
Record (this tree, `git grep`):
- `smb_send_parent_lease_break_noti` — only `smb2_open()`.
- After the patch: two sites in `smb2_open` (`created && !lc`, and
existing lease-context path).
- `smb2_open` is the SMB2 CREATE handler — authenticated SMB clients.
Related: `smb_lazy_parent_lease_break_close()` on close after write
(`reserve_lease_break`); not this CREATE gap.
**Step 5.3: TRACE CALLEES**
Record: `ksmbd_inode_lookup_lock(parent)`, `down_read(p_ci->m_lock)`,
walk `m_op_list`, `compare_guid_key()`, `oplock_break_add()`,
`oplock_break_drain_none()`, `ksmbd_inode_put()`. Same as today’s
helper.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace SMB2 CREATE → `smb2_open` → (new) parent lease break.
Reachable whenever ksmbd is running with leases/`smb2 leases` and a
client holds a directory lease. Windows 8+ SMB3 clients request
directory leases by default. **Yes, client-triggerable.**
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same missing-break pattern already fixed for rename
(`3fc74c65b3674`, in this tree). Unlink/close uses
`smb_lazy_parent_lease_break_close`. This patch is the CREATE-without-
lease counterpart.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.**
```1221:1236:fs/smb/server/oplock.c
if (lctx->version != 2)
return;
// ...
(!(lctx->flags &
SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) ||
!compare_guid_key(opinfo, fp->conn->ClientGUID,
lctx->parent_lease_key))) {
```
```3530:3541:fs/smb/server/smb2pdu.c
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && lc) {
// ...
smb_send_parent_lease_break_noti(fp, lc);
```
Bug introduced **v6.7** (`d47d9886aeef7`). Capability advertised in
`init_smb3_0_server()` / `init_smb3_02_server()`. Docs: “Directory
leases(v2 lease) Supported.”
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply with offset.** Local helper already has
`oplock_break_drain_none(&brk_list, p_ci)` from `5de0527f78243`; that
line is outside the candidate hunks. `git apply --check` succeeded.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Rename/delete-on-close lease-break fixes are here. **This
CREATE-without-lease notify is not.** Subject grep found no equivalent.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **[ksmbd / fs/smb/server] [IMPORTANT]** — in-kernel SMB3 server
for NAS/embedded. Not core VFS; not staging. Config `SMB_SERVER`,
default n.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: **Actively developed.** This pending 6.12 tree already carries
many ksmbd protocol and lease fixes (partial responses, RH lease break,
lease context validation, oplock UAF). Mature enough that directory
leasing has been “Supported” since ~6.7.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Config/driver-specific:** `CONFIG_SMB_SERVER` with SMB2 leases
and SMB3 directory leasing. Affects Windows/SMB3 clients that cache
directories against ksmbd.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Client A holds a v2 directory lease.
- Client B creates a child **without** a lease create context (`created
&& !lc`).
- Common for a second client or simple SMB CREATE; exactly the BVT
setup.
- Authenticated SMB client, not a local unprivileged syscall.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Stale directory cache / protocol violation.** Not
oops/deadlock/fs corruption. Clients can miss newly created names until
some other break. **Severity: MEDIUM** (interoperability / user-visible
wrong directory contents), same class as the rename lease-break fix
already in this tree.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** High for ksmbd+Windows SMB3: advertised directory leasing
actually invalidates on child create.
- **Risk:** Very low — ~8 lines, existing helper, applies cleanly, no
new locks/APIs.
- **Ratio:** Favor backport.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real protocol bug in **advertised** directory leasing (docs +
`SMB2_GLOBAL_CAP_DIRECTORY_LEASING`).
- User-visible: stale Windows directory cache; Microsoft BVT failure.
- Buggy code in this 6.12 tree since v6.7.
- Small, obviously correct, applies cleanly.
- Same class as `3fc74c65b3674` already in this tree.
- Maintainer-authored; in `ksmbd-for-7.3-rc1` as a protocol-
compatibility fix.
- No extra prerequisites.
**AGAINST:**
- Not a crash, UAF, or security issue.
- No Fixes:/Cc: stable (expected; not a negative).
- No public user bugzilla; test-suite driven.
- `SMB_SERVER` is optional.
**UNRESOLVED:** Original lore review thread (b4/lore 403). No NAK found
in the 7.3-rc1 pull.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — logic is clear; cited BVT;
maintainer committed it.
2. Fixes a real bug that affects users? **PASS** — missing required
lease break; stale listings.
3. Important issue? **PASS** at protocol-correctness / “oh, that's not
good” — not CRITICAL crash, but user-visible on an advertised file-
server feature. Matches other ksmbd lease-break backports in this
tree.
4. Small and contained? **PASS** — 2 files, ~8 lines.
5. No new features or APIs? **PASS** — completes existing notify helper;
no new uAPI.
6. Can apply to the local tree? **PASS** — `git apply --check`
succeeded.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None (not a device ID/quirk/DT/build/docs exception). Qualifies
as a normal contained bugfix.
**Step 9.4: MAKE YOUR DECISION**
This should be backported to **this 6.12 tree**. Directory leasing is
already on; CREATE without a lease context is a hole in the existing
break path; the fix is tiny and applies cleanly. Treating it as a new
feature would be wrong: the feature is already shipped and documented as
supported.
---
## What the commit solves (and why it matters here)
On 6.12, ksmbd advertises SMB3 directory leasing. Parent breaks were
only sent when the **child CREATE included a lease context**. A second
client creating a file the usual way (no lease context) left the
directory lease intact, so Windows clients could keep a cached listing
that omitted the new name. That fails
`BVT_DirectoryLeasing_ReadWriteHandleCaching` and breaks real SMB3
directory caching.
The patch (1) lets the existing helper accept `lctx == NULL` and break
active parent leases, and (2) calls it after a successful create when
`!lc`. Lease-key filtering for CREATE-with-lease is unchanged.
## Risk vs benefit
Benefit is correct directory invalidation for ksmbd users with
Windows/SMB3 clients. Risk is extra lease breaks only when a child is
actually created — required by the protocol. No new locking scheme; same
helper already used in `smb2_open`.
## Concerns
- Context offset vs mainline (`oplock_break_drain_none` already takes
`p_ci` here) — **does not block apply**.
- Remaining gap (pre-existing): CREATE with a **v1** lease still returns
early (`lctx->version != 2`). This patch correctly does not expand
that; it only adds the NULL-context path the BVT hits.
- Not a panic/UAF; still appropriate because this tree already backports
the same kind of ksmbd lease-break completeness fixes.
---
## Verification
- **[Phase 1]** `git log -1 --format='%B' abe5acb342822`: only Namjae
SOB; BVT named; no Fixes/Cc/Reported-by.
- **[Phase 1]** `git describe HEAD` / Makefile: **p-6.12-3 / 6.12.111**.
- **[Phase 2]** Read local `smb_send_parent_lease_break_noti` and
`smb2_open`; confirmed NULL deref assumption and lease-context-only
call.
- **[Phase 2]** Confirmed `created` set after `smb2_creat`; `lc` only
from `parse_lease_state`.
- **[Phase 3]** `git blame`: helper/call site from `d47d9886aeef7`
(2023-12-08); `git describe --contains` → **v6.7-rc6**.
- **[Phase 3]** `git merge-base --is-ancestor d47d9886aeef7 HEAD` → yes;
`abe5acb342822` → **not** in HEAD.
- **[Phase 3]** `git show abe5acb342822 | git apply --check --verbose` →
both files apply (offsets −232 / −1136).
- **[Phase 3]** `git log all-next -S 'created && !lc'` → only this
commit; no follow-up.
- **[Phase 4]** `b4 dig -c abe5acb342822` → lore errors, no match.
- **[Phase 4]** WebFetch lore.kernel.org → 403.
- **[Phase 4]** LKML GIT PULL 7.3-rc1 lists this commit; merge
`61a09cfc12147` mentions parent directory lease notifications.
- **[Phase 5]** `git grep smb_send_parent_lease_break_noti` → only
`smb2_open` + declaration.
- **[Phase 5]** `smb2ops.c`: `SMB2_GLOBAL_CAP_DIRECTORY_LEASING` set for
SMB3.0/3.02 when leases enabled.
- **[Phase 6]** Docs `ksmbd.rst`: “Directory leases(v2 lease)
Supported.”
- **[Phase 6]** Similar fix `3fc74c65b3674` is already an ancestor of
HEAD.
- **[Phase 7]** `MAINTAINERS`: Namjae Jeon is ksmbd maintainer.
- **[Phase 8]** Failure mode verified from code + BVT name: stale
directory lease, not a kernel oops.
- **UNVERIFIED:** Original lore review comments / NAKs (lore
unavailable). Not used to drive the verdict; maintainer merge is
verified.
The fix is small, applies to this tree, and closes a real hole in
advertised SMB3 directory leasing.
**YES**
fs/smb/server/oplock.c | 9 +++++----
fs/smb/server/smb2pdu.c | 3 +++
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index 08e3e4504b03f..7d78d4ae43acb 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -1271,7 +1271,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
struct ksmbd_inode *p_ci = NULL;
LIST_HEAD(brk_list);
- if (lctx->version != 2)
+ if (lctx && lctx->version != 2)
return;
p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);
@@ -1284,9 +1284,10 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
continue;
if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE &&
- (!(lctx->flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) ||
- !compare_guid_key(opinfo, fp->conn->ClientGUID,
- lctx->parent_lease_key))) {
+ (!lctx ||
+ (!(lctx->flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) ||
+ !compare_guid_key(opinfo, fp->conn->ClientGUID,
+ lctx->parent_lease_key)))) {
if (!atomic_inc_not_zero(&opinfo->refcount))
continue;
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index e7b1cab45ab2d..7d9c8246edfd6 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -3565,6 +3565,9 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
} else {
+ if (created && !lc)
+ smb_send_parent_lease_break_noti(fp, NULL);
+
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && lc) {
if (S_ISDIR(file_inode(filp)->i_mode)) {
lc->req_state &= ~SMB2_LEASE_WRITE_CACHING_LE;
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] media: em28xx: use vb2_video_unregister_device
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (101 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: notify parent directory leases on child create Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip Sasha Levin
` (413 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Hans Verkuil, Mauro Carvalho Chehab, Sasha Levin, mchehab,
linux-media, linux-kernel
From: Hans Verkuil <hverkuil+cisco@kernel.org>
[ Upstream commit 7c8bf63b79371f5b57da1bd1401bd420180ac6e6 ]
Use vb2_video_unregister_device instead of video_unregister_device
to ensure any streaming is correctly stopped at unregister time.
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
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: `[media: em28xx] [use] switch unregister to
vb2_video_unregister_device so streaming is stopped at unbind`
**Step 1.2: Tags**
Record:
- `Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (author;
V4L2/videobuf2 maintainer)
- `Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (author tested;
not an independent tester)
- `Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>`
(media maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable`, `Reviewed-by:`, or
`Acked-by:`
- Absence of `Fixes:` / `Cc: stable` is expected for this review and is
not treated as a negative
**Step 1.3: Body**
Record:
- Bug: `video_unregister_device()` does not stop an active vb2 queue, so
streaming can continue after the video node is unregistered.
- Symptom: capture still running across USB unbind / module unload /
probe rollback.
- Root cause (from message + helper docs): drivers that use
`_vb2_fop_release()` must use `vb2_video_unregister_device()` so the
queue is released at unregister time.
- No stack trace, reproducer, or version range in the message.
**Step 1.4: Hidden bug fix?**
Record: Yes. “Use helper X” is a correctness fix, not a feature. The
cover letter for the series is titled “fix lifecycle issues” and says
this patch “ensures all streaming is stopped when the video device is
unregistered.”
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/media/usb/em28xx/em28xx-video.c` (+6 / -6)
- Functions: `em28xx_v4l2_fini()`, `em28xx_v4l2_init()` error path
`unregister_dev`
- Six call sites: radio / VBI / video, in both fini and probe-error
teardown
- Scope: single-file surgical substitution
**Step 2.2: Code flow**
Record:
- Before: `video_unregister_device()` only removes the node; the vb2
queue can remain in STREAMING.
- After: `vb2_video_unregister_device()` unregisters, then
`vb2_queue_release()` (under the queue lock) which runs
`stop_streaming` and returns buffers.
- Paths: USB disconnect / module unload (`em28xx_v4l2_fini`) and init
failure (`unregister_dev`).
**Step 2.3: Bug mechanism**
Record: `[logic / lifecycle] [use-after-unbind]`
Verified disconnect order in this tree:
1. `em28xx_usb_disconnect()` sets `disconnected`, then
`em28xx_close_extension()` → `em28xx_v4l2_fini()`.
2. fini already calls `em28xx_uninit_usb_xfer()`, then unregisters
nodes.
3. Then `em28xx_release_resources()` unregisters I2C and
`usb_put_dev()`.
4. Userspace may still hold the fd. Close calls `em28xx_v4l2_close()` →
`_vb2_fop_release()` → `vb2_queue_release()` →
`em28xx_stop_streaming()`.
5. `em28xx_stop_streaming()` does `v4l2_device_call_all(..., video,
s_stream, 0)` and `em28xx_uninit_usb_xfer()`. That runs **after**
I2C/USB teardown if the queue was not stopped in fini.
Stopping the queue in fini keeps `stop_streaming` on the unbind side of
I2C/USB teardown.
**Step 2.4: Fix quality**
Record:
- For video and VBI this is the documented vb2 pattern
(`include/media/videobuf2-v4l2.h`: drivers using `_vb2_fop_release()`
should use this helper). `em28xx_v4l2_close()` does call
`_vb2_fop_release()`.
- Video/VBI set `vdev->queue` (`vb_vidq` / `vb_vbiq`).
- Radio never sets `vdev->queue`. The helper does
`WARN_ON(!vdev->queue)` then still calls `video_unregister_device()`.
Two boards have radio (`EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE`,
`EM2860_BOARD_KAIOMY_TVNPC_U2`).
- Probe error path: `vdev->queue` is assigned **before**
`em28xx_vb2_setup()` / `vb2_queue_init()`. `unregister_dev` after a
later `video_register_device()` or media-graph failure can call
`vb2_queue_release()` on a zeroed queue (`mutex_lock(&q->mmap_lock)`
in `vb2_core_queue_release()`). That is a real, but rare, teardown
hazard.
- No API/feature additions. Regression risk is low on the disconnect
path (queue is initialized); radio WARN_ON and probe-error queue
release are the main nits.
## Phase 3: Git history
**Step 3.1: Blame**
Record:
- `video_unregister_device()` on these nodes comes from the
embedded-`video_device` era (`d4352f3639d780`, 2015) and older Mauro
unregister paths (2008/2013).
- Bug is long-standing, not new in 7.3.
**Step 3.2: Fixes: tag**
Record: None. Helper introduced in `f729ef5796d82` (2020, around v5.10).
`git merge-base --is-ancestor f729ef5796d82 HEAD` succeeds.
**Step 3.3: File history**
Record: Same-day series on this file:
1. `288254383674b` media: em28xx: use v4l2_device release callback
2. `de626073dfcbb` media: em28xx: drop 'users' field
3. `7c8bf63b79371` **this commit**
4. Later: `c132b07f7e585` (use-after-free of `dev->intf` in free),
`67f87b104f4ef` (requeue on start_streaming failure)
This is standalone at the diff level (only a symbol change). Series
context: patch 1 deferred `v4l2_device_unregister()` until last close,
which makes a late `stop_streaming()` after I2C teardown more likely.
This tree already contains patches 1 and 2.
**Step 3.4: Author**
Record: Hans Verkuil is the V4L2/videobuf2 maintainer. He added the
helper in 2020 and converted au0828/usbtv/cxusb then (`24b5836dbd45b`).
em28xx was not in that conversion.
**Step 3.5: Prerequisites**
Record: Needs `vb2_video_unregister_device()` (present). Needs em28xx
vb2 video/VBI (present). `em28xx.h` already includes `videobuf2-v4l2.h`.
Can apply standalone. This tree already has the helper and the driver.
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
Record: `b4 dig -c 7c8bf63b79371` → https://patch.msgid.link/ad61b2c30cd
477599312e9d5c12045dcd05c8ecd.1779191683.git.hverkuil+cisco@kernel.org
Saved thread: `/tmp/em28xx-thread.mbox` (cover + 3 patches, **no
replies**).
`b4 dig -a`: **v1 only**. Cover: `[PATCH 0/3] media: em28xx: fix
lifecycle issues`. Quote: “the last patch switches
video_unregister_device to vb2_video_unregister_device: this ensures all
streaming is stopped when the video device is unregistered.” Also: “All
this still needs to be tested on real hardware” at send time; the merged
commit later has `Tested-by: Hans Verkuil`. No NAK, no `Cc: stable` in
review (there was no review mail).
WebFetch of lore returned 403. Thread content was recovered via `b4 dig
-m`.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: Hans Verkuil, `linux-media@vger.kernel.org`, Mauricio Faria de
Oliveira `<mfo@igalia.com>`. No review mail in the mbox. Mauro applied
it.
**Step 4.3: Bug report**
Record: No `Reported-by` / syzbot / bugzilla. No independent user report
found in the thread.
**Step 4.4: Series**
Record: Explicit 3/3 of a lifecycle series. This hunk does not need
patches 1–2 to compile. Those two are already in this tree.
**Step 4.5: Stable list**
Record: UNVERIFIED. lore.kernel.org/stable was blocked (Anubis bot-
check). No stable discussion in the captured media thread.
## Phase 5: Semantic / call graph
**Step 5.1: Functions**
Record: `em28xx_v4l2_fini`, `em28xx_v4l2_init` (`unregister_dev`).
Callee: `vb2_video_unregister_device` → `video_unregister_device` +
`vb2_queue_release` → `em28xx_stop_streaming` /
`em28xx_stop_vbi_streaming`.
**Step 5.2: Callers**
Record:
- `em28xx_v4l2_fini` ← `em28xx_close_extension()` (`em28xx-core.c`) ←
`em28xx_usb_disconnect()` (unplug) and `em28xx_unregister_extension()`
(module unload).
- `unregister_dev` ← probe/init failures after a node is registered.
**Step 5.3: Callees**
Record: queue release, `stop_streaming`, `em28xx_uninit_usb_xfer`,
`v4l2_device_call_all(..., s_stream, 0)`.
**Step 5.4: Reachability**
Record: Yes. Unplug or `rmmod` while an analog capture app is streaming
is a normal USB-TV / webcam path. Unprivileged userspace can hold the
device open; unplug is a physical event.
**Step 5.5: Similar patterns**
Record: Same helper is used across USB/PCI/platform V4L2 drivers (uvc,
au0828, usbtv, saa7134, vivid, …). em28xx was a leftover vs the 2020 USB
conversion.
semcode MCP tools: not available; used `git grep` / file reads.
## Phase 6: This tree
**Step 6.1: Local tree and buggy code**
Record:
- `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`
- `make kernelversion` / Makefile → **7.3.0-rc4** (mainline, not an LTS
branch)
- `git merge-base --is-ancestor 7c8bf63b79371 HEAD` → yes (already in
this checkout)
- Driver, helper, and `_vb2_fop_release()` close path all exist here
- Bug class (unregister without stopping vb2) has been in em28xx since
~2015; it was not introduced after this tree
**Step 6.2: Backport difficulty**
Record: Clean apply on this codebase (already applied). Helper and
includes are present. No conflicting refactor of these call sites beyond
the same series.
**Step 6.3: Related fixes already here**
Record: Lifetime callback + drop-`users` are already here. No alternate
fix of these six call sites. Follow-up `67f87b104f4ef` is a different
start_streaming WARN, not a replacement for this change.
## Phase 7: Subsystem
**Step 7.1**
Record: `[drivers/media/usb/em28xx] [IMPORTANT]` — USB analog capture,
not core mm/net, but a long-lived in-tree driver with real hardware
users (`CONFIG_VIDEO_EM28XX` / `VIDEO_EM28XX_V4L2`).
**Step 7.2**
Record: Mature driver; recent work is lifecycle/vb2 correctness from the
V4L2 maintainer, not a new subsystem.
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
Record: Users of em28xx USB capture sticks (Hauppauge, Empia, etc.),
analog video/VBI. Radio-only extra is two board entries.
**Step 8.2: Trigger**
Record: Unplug or unload while `/dev/video*` or VBI is streaming (or
open with a live queue). Common for USB TV/webcam. Unprivileged process
can keep the fd; disconnect is the trigger.
**Step 8.3: Failure mode**
Record: `stop_streaming` after I2C unregister / `usb_put_dev` → use of
torn-down USB/I2C, hung DQBUF, possible UAF. Severity **HIGH**. Not a
guaranteed panic on every unplug (URBs are already killed in fini), but
the decoder `s_stream(0)` and second uninit run too late.
**Step 8.4: Risk/benefit**
Record:
- Benefit: high for em28xx users who unplug while capturing; matches the
documented vb2 unbind contract.
- Risk: low on the disconnect path (6 substitutions, helper used since
2020). Medium-low on probe-error (uninitialized queue) and radio
(`WARN_ON`).
- Ratio: benefit of stopping the queue at unbind outweighs those edge
nits.
## Phase 9: Synthesis
**Step 9.1: Evidence**
FOR:
- Real unbind/lifecycle bug: vb2 stays STREAMING after node unregister;
`stop_streaming` can run after I2C/USB teardown.
- Driver already uses `_vb2_fop_release()`; helper is the required API.
- Small (6 lines), no new API, helper present in this tree since 2020.
- V4L2 maintainer authored and tested; media maintainer applied.
- USB unplug while capturing is a realistic user path.
- Same conversion already done for sibling USB drivers.
AGAINST:
- No user crash log / syzbot.
- Patch 3/3 of a lifecycle series (self-contained, but series-scoped).
- Radio `WARN_ON(!queue)` on two boards.
- Probe `unregister_dev` can `vb2_queue_release()` before
`vb2_queue_init()`.
- Cover letter originally said hardware testing was still pending (later
`Tested-by` is the author).
UNRESOLVED:
- lore.kernel.org HTTP 403 / stable list Anubis block; no independent
stable-thread confirmation beyond the mbox (which had no replies).
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** for video/VBI disconnect; nits
on radio/probe-error do not make the core change wrong. Tested-by
author.
2. Real bug affecting users? **PASS** — verified disconnect vs close
ordering.
3. Important (crash/UAF/unbind)? **PASS** — HIGH, use-after-unbind /
late `s_stream` on torn-down I2C/USB.
4. Small and contained? **PASS** — 6 lines, one file.
5. No new features/APIs? **PASS**.
6. Applies to this tree? **PASS** — helper, includes, and call sites
exist here.
**Step 9.3: Exception category**
Record: None (not an ID/quirk/DT/build/docs exception). It is a normal
small bugfix.
**Step 9.4: Decision**
This tree is 7.3-rc4 and already contains the helper and em28xx vb2
video. The change is a small, maintainer-tested fix for a real USB-
unbind lifecycle hole: without it, analog streaming is not stopped when
the node is unregistered, so `stop_streaming` can run after I2C/USB
teardown. That is in scope for this codebase and meets the stable bar.
Radio WARN_ON and a rare probe-error queue release are residual nits,
not reasons to keep the disconnect bug.
### What the commit solves for this tree
On em28xx analog capture, `em28xx_v4l2_fini()` (USB disconnect / module
unload) unregisters video/VBI with `video_unregister_device()` while the
vb2 queue can still be STREAMING. Close later stops the queue via
`_vb2_fop_release()`, but by then `em28xx_release_resources()` has
already dropped I2C and the USB device. Switching to
`vb2_video_unregister_device()` stops streaming during fini, while those
objects are still valid.
### Risk vs benefit
Benefit is a real unbind UAF/use-after-teardown hole on a commonly
unplugged USB capture driver. Risk is six call-site substitutions
through a helper that has been in this tree for years. Residual radio
WARN_ON and probe-error queue release are limited.
### Verification
- [Phase 1] Tags: author SOB + Tested-by Hans Verkuil, Mauro SOB; no
Fixes/Reported-by/Link/Cc:stable
- [Phase 2] Diff: 6 `video_unregister_device` →
`vb2_video_unregister_device` in `em28xx_v4l2_fini` and
`unregister_dev`
- [Phase 2] Helper: `vb2_video_unregister_device()` unregisters then
`vb2_queue_release()`; `WARN_ON(!vdev->queue)` confirmed
- [Phase 2] `radio_dev` never assigns `.queue`; video/VBI do (`em28xx-
video.c` init)
- [Phase 2] `em28xx_v4l2_close()` calls `_vb2_fop_release(filp, NULL)`
- [Phase 2] `em28xx_stop_streaming()` calls `s_stream(0)` and
`em28xx_uninit_usb_xfer()`
- [Phase 3] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37;
kernelversion 7.3.0-rc4
- [Phase 3] Commit `7c8bf63b79371` is ancestor of HEAD; helper
`f729ef5796d82` is ancestor
- [Phase 3] Series: `288254383674b`, `de626073dfcbb`, this commit; 2020
USB conversion `24b5836dbd45b` skipped em28xx
- [Phase 4] `b4 dig -c 7c8bf63b79371`: lore msgid
ad61b2c30cd477599312e9d5c12045dcd05c8ecd…; v1-only 3-patch “fix
lifecycle issues”
- [Phase 4] mbox: cover + 3 patches, zero replies; `b4 dig -w`: linux-
media + Mauricio Faria de Oliveira
- [Phase 4] WebFetch lore 403; stable lore Anubis-blocked — UNVERIFIED
beyond mbox
- [Phase 5] fini callers: `em28xx_close_extension` ←
`em28xx_usb_disconnect` / `em28xx_unregister_extension`
- [Phase 6] `em28xx.h` includes `videobuf2-v4l2.h`; radio boards Leadtek
Winfast USB II Deluxe, Kaiomy TVnPC U2
- [Phase 8] Disconnect then `em28xx_release_resources()` does
`em28xx_i2c_unregister` + `usb_put_dev` before last close
- UNVERIFIED: independent hardware test besides author’s Tested-by; any
stable@ thread
**YES**
drivers/media/usb/em28xx/em28xx-video.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index e0a69309687b0..e2907b56220b7 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -2243,17 +2243,17 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
if (video_is_registered(&v4l2->radio_dev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->radio_dev));
- video_unregister_device(&v4l2->radio_dev);
+ vb2_video_unregister_device(&v4l2->radio_dev);
}
if (video_is_registered(&v4l2->vbi_dev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->vbi_dev));
- video_unregister_device(&v4l2->vbi_dev);
+ vb2_video_unregister_device(&v4l2->vbi_dev);
}
if (video_is_registered(&v4l2->vdev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->vdev));
- video_unregister_device(&v4l2->vdev);
+ vb2_video_unregister_device(&v4l2->vdev);
}
v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
@@ -2901,19 +2901,19 @@ static int em28xx_v4l2_init(struct em28xx *dev)
dev_info(&dev->intf->dev,
"V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->radio_dev));
- video_unregister_device(&v4l2->radio_dev);
+ vb2_video_unregister_device(&v4l2->radio_dev);
}
if (video_is_registered(&v4l2->vbi_dev)) {
dev_info(&dev->intf->dev,
"V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->vbi_dev));
- video_unregister_device(&v4l2->vbi_dev);
+ vb2_video_unregister_device(&v4l2->vbi_dev);
}
if (video_is_registered(&v4l2->vdev)) {
dev_info(&dev->intf->dev,
"V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->vdev));
- video_unregister_device(&v4l2->vdev);
+ vb2_video_unregister_device(&v4l2->vdev);
}
v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (102 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: use vb2_video_unregister_device Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:27 ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] udf: bound lengthAllocDescs from unallocated space entry Sasha Levin
` (412 subsequent siblings)
516 siblings, 1 reply; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Maulik Shah, Sneh Mankad, Linus Walleij, Navya Malempati,
Bartosz Golaszewski, Sasha Levin, andersson, brgl, linux-arm-msm,
linux-gpio, linux-kernel
From: Maulik Shah <maulik.shah@oss.qualcomm.com>
[ Upstream commit 1860fb0be224dec0e4d170f46d1cbbc77e25e09e ]
MPM irqchip monitors the interrupts during SoC sleep state and after wakeup
replays the edge interrupt by making it pending at respective irqchip by
invoking irq_set_irqchip_state() API. The msm gpio irqchip however do not
implement this function making it impossible to replay the gpio interrupt
on any MPM irqchip based SoC.
Add the missing irq_get/set_irqchip_state() APIs. Implement only
IRQCHIP_STATE_PENDING case which MPM irqchip uses.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
Signed-off-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Acked-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Navya Malempati <navya.malempati@oss.qualcomm.com>
Link: https://patch.msgid.link/20260424-pinctrl_irqchip_states-v1-1-85286f078916@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4**. This commit fills in missing MSM GPIO
irqchip ops so MPM can replay edge GPIOs after deep sleep. That is a
real resume bug on Qualcomm MPM SoCs, and the change is small enough to
be a stable candidate.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[pinctrl/qcom] [Add] Implement missing
irq_get/set_irqchip_state() on the MSM GPIO irqchip`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Fixes:` — none (expected)
- `Reported-by:` — none
- `Tested-by:` — none
- `Reviewed-by: Navya Malempati <navya.malempati@oss.qualcomm.com>`
- `Acked-by: Linus Walleij <linusw@kernel.org>` (pinctrl maintainer)
- `Link: https://patch.msgid.link/20260424-pinctrl_irqchip_states-v1-1-
85286f078916@oss.qualcomm.com`
- `Cc: stable@vger.kernel.org` — none (expected)
- `Signed-off-by: Maulik Shah` (author)
- `Signed-off-by: Sneh Mankad` (submitter)
- `Signed-off-by: Bartosz Golaszewski` (Qualcomm pinctrl maintainer)
- Ignore pipeline `Signed-off-by: Sasha Levin`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** After SoC sleep, MPM replays edge IRQs with
`irq_set_irqchip_state(..., IRQCHIP_STATE_PENDING, true)`. The MSM
GPIO irqchip did not implement that op, so GPIO edges cannot be
replayed on MPM SoCs.
- **Symptom:** Lost GPIO edge interrupts after deep sleep / resume
(wakeup events never delivered to the GPIO irqchip).
- **Root cause:** Missing `irq_chip.irq_{get,set}_irqchip_state` on
`msmgpio`.
- **Versions:** None stated. MPM has called this API since it was added
(2022).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. Subject says “Add”, but the body
describes a real missing-op bug. Implementing existing irqchip callbacks
is a completeness/correctness fix, not a new userspace API.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pinctrl/qcom/pinctrl-msm.c` — **+39 / -0**
- New: `msm_gpio_irq_set_irqchip_state()`,
`msm_gpio_irq_get_irqchip_state()`
- Wired into `msm_gpio_irq_chip`
- Scope: single-file, surgical
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `irq_set_irqchip_state()` walks the hierarchy from
`msmgpio`. That chip had no callback, so it walked to MPM (also no
callback). GPIO-only MPM pins disconnect GIC, so the call returns
`-EINVAL` and the edge is never made pending.
- **After:** `msmgpio` writes/reads TLMM `intr_status` for
`IRQCHIP_STATE_PENDING`. Other states and `skip_wake_irqs` pins (PDC-
owned) return `-EINVAL`.
- Path: resume / MPM handler, not probe.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Logic / correctness (missing irqchip op)**, with a hardware-
wakeup workaround flavor.
Mechanism: MPM’s `qcom_mpm_handler()` does
`irq_set_irqchip_state(d->irq, IRQCHIP_STATE_PENDING, true)` for non-
level IRQs. Without the GPIO callback, replay is impossible. The fix
writes the GPIO status register (bit 0; `intr_status_bit` is 0 on all
GPIO pingroups).
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Quality: sufficient for the MPM case. Only `IRQCHIP_STATE_PENDING`;
PDC pins are rejected via `skip_wake_irqs`.
- Nits (not blockers): bool written as the full status register (OK
because status bit is 0); no `pctrl->lock` (single `writel`/`readl`);
redundant `g` assignment in get; get is unused by MPM but harmless.
- `intr_ack_high` platforms (msm8660/8960, ipq8064, …) would invert set
vs ack; those SoCs do not use MPM.
- For `skip_wake_irqs` (PDC), the walk now stops at `msmgpio` and
returns `-EINVAL` instead of forwarding to PDC/GIC. PDC SoCs do not
use MPM replay; this is conservative, not the MPM bug.
- Regression risk: **low–medium**. Writing pending can inject an IRQ;
that is the intended replay. Pinctrl maintainer initially called it
“super dangerous”, then acked after Qualcomm review.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: These callbacks are new. The irqchip struct dates to
`69b78b8de65b` (2014) / immutable chip `14dbe186b9d4` (2022).
`skip_wake_irqs` dates to `e35a6ae0eb3a` (2019). MPM (`a6199bb514d8`,
2022-03-11, ~v5.18) is what started calling `irq_set_irqchip_state()` on
wakeup.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Bug is omission vs MPM, not a regression from a
later commit.
**Step 3.3: CHECK FILE HISTORY**
Record: No prerequisite series. `v1-1` is standalone. No later commit in
this tree patches these new functions.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Maulik Shah is a regular Qualcomm pinctrl/irqchip contributor
(PDC, wakeup, irqchip flags). Related work is Qualcomm wakeup IRQ
handling, not a hard dependency of this patch.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Uses existing `msm_readl/writel_intr_status`, `skip_wake_irqs`,
and `irq_chip` ops. Can apply standalone to this file.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore: https://patch.msgid.link/20260424-pinctrl_irqchip_states-v1-1-
85286f078916@oss.qualcomm.com
- Single revision **v1** (no v2/v3).
- Linus Walleij (28 Apr 2026): “smart and also **super dangerous**” —
wanted Qualcomm ACK/test before merge.
- Navya Malempati (16 Jul 2026): `Reviewed-by`.
- Linus (25 Jul 2026): `Acked-by`; asked Bartosz to queue it.
- Bartosz (27 Jul 2026): Applied as `[1/1]`.
- No `Cc: stable`, no NAK after Qualcomm review.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: To/Cc: Bjorn Andersson, Linus Walleij, linux-arm-msm, linux-
gpio, linux-kernel, Maulik Shah. Right lists and maintainers.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot, bugzilla, or public user report. Qualcomm-internal
hardware knowledge. Severity from the message: **GPIO edges cannot be
replayed after sleep on any MPM SoC**.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone 1/1. Same 7.3 pinctrl-qcom pull also had PDC work;
this patch does not depend on those.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No stable@ discussion found. Merged via “Qualcomm pinctrl
updates for v7.3-rc1”.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
Record: `msm_gpio_irq_set_irqchip_state`,
`msm_gpio_irq_get_irqchip_state`; `msm_gpio_irq_chip` updated.
**Step 5.2: TRACE CALLERS**
Record:
- IRQ core: `irq_set_irqchip_state()` / `irq_get_irqchip_state()`
(`kernel/irq/manage.c`) start at the leaf chip (`msmgpio`).
- Primary caller: `qcom_mpm_handler()` in `drivers/irqchip/irq-qcom-
mpm.c` (RPM wakeup IRQ, resume).
- Also: `irq_inject_interrupt()` (debug), KVM vgic (unrelated host
IRQs).
**Step 5.3: TRACE CALLEES**
Record: `msm_writel_intr_status` / `msm_readl_intr_status` — MMIO to
TLMM per-pin status.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Sleep → MPM latches wakeup GPIO → resume → `qcom_mpm_handler` →
`irq_set_irqchip_state(PENDING)` → **now** TLMM status. Triggered by
hardware wakeup, not a raw syscall. User-visible: GPIO clients (keys,
modem, sensors) miss the edge after suspend.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: PDC already has `irq_chip_{get,set}_parent_state`. GIC
implements these ops. `skip_wake_irqs` is set only when parent is PDC
(`IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP`). MPM parent does **not** set that
flag, so TLMM keeps handling those GPIOs — which is why MSM GPIO must
implement the ops.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: **v7.3-rc4-27-gf0100363d8c37**, `VERSION=7 PATCHLEVEL=3
SUBLEVEL=0 EXTRAVERSION=-rc4`.
- Driver, MPM (`CONFIG_QCOM_MPM`), `skip_wake_irqs`, and accessors all
exist.
- Commit `1860fb0be224` **is already an ancestor of HEAD** (7.3 merge
window). Unfixed code is not on HEAD; the same files still need this
on any branch that predates 7.3.
- Bug present since MPM (v5.18), not introduced after 7.3 branched.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** onto this `pinctrl-msm.c`. One file, two new
functions, two irq_chip pointers. `skip_wake_irqs` and status accessors
are old.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No other fix for “MPM cannot replay GPIO pending”. No follow-up
on these functions after `1860fb0be224`.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: `drivers/pinctrl/qcom` + Qualcomm MPM irqchip. **IMPORTANT**
(platform GPIO/wakeup), not core mm/vfs. Affects Qualcomm MPM boards
(sdm660, sm6115/6125/6375, msm8996/8998, qcm2290, …), not PDC phones.
**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Actively maintained (Bartosz / Qualcomm). This is a targeted
irqchip-ops fill-in, not a refactor.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
Record: **Platform-specific** — `CONFIG_PINCTRL_MSM*` +
`CONFIG_QCOM_MPM`. Not universal. Still real products (older/mid
Qualcomm, IoT, embedded).
**Step 8.2: TRIGGER CONDITIONS**
Record: SoC deep sleep, then an edge GPIO that MPM monitored. Common on
suspend/resume. Not an unprivileged syscall exploit path.
**Step 8.3: FAILURE MODE SEVERITY**
Record: Lost GPIO edge after resume (keys, wake sources, peripherals).
Not oops/UAF/corruption. **MEDIUM–HIGH** functional/suspend-resume, not
CRITICAL crash.
**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit:** High for MPM Qualcomm users (resume GPIO actually fires).
- **Risk:** Low–medium (39 lines, pending-bit write). Mitigated by
PENDING-only and `skip_wake_irqs`. No lock/API/data-structure change.
- **Ratio:** Benefit outweighs risk for trees that still lack the ops.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Concrete bug: MPM cannot replay GPIO edges after sleep.
- User-visible resume failure on MPM SoCs.
- Small, one-file, existing irqchip API only.
- Prerequisites present here for years.
- Qualcomm `Reviewed-by`, Walleij `Acked-by`, Bartosz merged.
- No follow-up fix in this tree.
- Same class as hardware/suspend quirks that stable takes.
AGAINST:
- Worded as “Add”; implements new irqchip methods.
- Not crash/UAF/security.
- No public reporter / `Tested-by`.
- Walleij first called it “super dangerous”.
- Minor implementation nits.
UNRESOLVED:
- No public repro log (Qualcomm-described).
- lore HTTP 403; thread recovered via `b4 dig -m`.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — PENDING-only, skip PDC pins;
reviewed/acked. Initial “dangerous” concern addressed in review. No
`Tested-by`, but mechanism matches MPM code.
2. Fixes a real bug that affects users? **PASS** — lost GPIO IRQs after
sleep on MPM SoCs.
3. Important issue? **PASS** — suspend/resume IRQ loss (serious
functional), not oops/CVE.
4. Small and contained? **PASS** — +39 lines, one file.
5. No new features or APIs? **PASS** — no new uAPI; fills existing
`irq_chip` ops the core already calls.
6. Can apply to the local tree? **PASS** — same file/helpers; applies
cleanly.
**Step 9.3: EXCEPTION CATEGORIES**
Record: Not a device-ID/DT/build/doc exception. Closest: **hardware
wakeup workaround** (missing irqchip op so existing MPM hardware works
after sleep).
**Step 9.4: DECISION**
This tree has the MSM GPIO irqchip, MPM, and `skip_wake_irqs`. The bug
is missing ops, present since MPM (~v5.18), not a 7.3-only feature. The
patch is a small, review-vetted fix for lost edge GPIOs after deep
sleep. That meets stable rules for this checkout.
---
### What it solves for stable users
On Qualcomm MPM SoCs, an edge GPIO during sleep is latched in always-on
MPM. On resume, MPM marks the leaf irqchip pending. Without these ops,
`msmgpio` cannot accept that, so the edge is dropped. Users can miss
keys, modem/Wi-Fi wake, sensors, etc. after suspend.
### Stable rules
Small, obviously aimed at one hardware path, no new uAPI, real resume
bug. Risk is writing the GPIO pending bit; the patch limits that to
`IRQCHIP_STATE_PENDING` and non-PDC pins.
### Risk vs benefit
Benefit is real on MPM platforms. Risk is contained. Quality nits do not
break the MPM case (`intr_status_bit == 0`).
---
### Verification
- **[Phase 1]** Tags: Reviewed-by Navya, Acked-by Walleij, Link to
msgid; no Fixes/Reported-by/Cc:stable.
- **[Phase 2]** Diff: +39 in `pinctrl-msm.c`; two callbacks + irq_chip
pointers; `msm_writel_intr_status(val)` with bool; `intr_status_bit`
is 0 on GPIO groups (verified across pinctrl-qcom).
- **[Phase 2]** `qcom_mpm_handler` confirmed to call
`irq_set_irqchip_state(..., IRQCHIP_STATE_PENDING, true)` for non-
level IRQs.
- **[Phase 2]** `irq_set_irqchip_state()` in `kernel/irq/manage.c` walks
until a chip implements the op; `qcom_mpm_chip` does not.
- **[Phase 3]** MPM added `a6199bb514d8` (2022); `skip_wake_irqs` from
`e35a6ae0eb3a` (2019); no later fix to these functions.
- **[Phase 3]** `git merge-base --is-ancestor 1860fb0be224 HEAD` → yes
(commit is in this 7.3-rc4 history). Decision is on technical merit,
not “already selected”.
- **[Phase 4]** `b4 dig -c 1860fb0be224` → v1 only; Walleij “super
dangerous” then Acked-by; Bartosz applied 1/1.
- **[Phase 4]** `b4 dig -w`: linux-gpio, linux-arm-msm, Walleij,
Andersson.
- **[Phase 4]** lore.kernel.org WebFetch 403; thread read from
`/tmp/pinctrl-irqchip.mbox`.
- **[Phase 5]** PDC sets `IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP` →
`skip_wake_irqs`; MPM sets `IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP` and does
not skip TLMM.
- **[Phase 6]** `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`;
`make kernelversion` = `7.3.0-rc4`.
- **[Phase 8]** Failure: dropped GPIO edge after MPM wakeup; severity
MEDIUM–HIGH functional, not crash.
- **UNVERIFIED:** Public reproducer / which exact board Qualcomm used
(not in the thread).
The patch is a contained fix for a real resume IRQ-loss bug on hardware
this tree already supports.
**YES**
drivers/pinctrl/qcom/pinctrl-msm.c | 39 ++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 424b14bc29e96..015c9b2f086da 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1289,6 +1289,43 @@ static int msm_gpio_irq_set_affinity(struct irq_data *d,
return -EINVAL;
}
+static int msm_gpio_irq_set_irqchip_state(struct irq_data *d,
+ enum irqchip_irq_state which, bool val)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+ const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq];
+
+ if (which != IRQCHIP_STATE_PENDING)
+ return -EINVAL;
+
+ if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
+ return -EINVAL;
+
+ msm_writel_intr_status(val, pctrl, g);
+
+ return 0;
+}
+
+static int msm_gpio_irq_get_irqchip_state(struct irq_data *d,
+ enum irqchip_irq_state which, bool *val)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+ const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq];
+
+ if (which != IRQCHIP_STATE_PENDING)
+ return -EINVAL;
+
+ if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
+ return -EINVAL;
+
+ g = &pctrl->soc->groups[d->hwirq];
+ *val = msm_readl_intr_status(pctrl, g);
+
+ return 0;
+}
+
static int msm_gpio_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -1377,6 +1414,8 @@ static const struct irq_chip msm_gpio_irq_chip = {
.irq_request_resources = msm_gpio_irq_reqres,
.irq_release_resources = msm_gpio_irq_relres,
.irq_set_affinity = msm_gpio_irq_set_affinity,
+ .irq_set_irqchip_state = msm_gpio_irq_set_irqchip_state,
+ .irq_get_irqchip_state = msm_gpio_irq_get_irqchip_state,
.irq_set_vcpu_affinity = msm_gpio_irq_set_vcpu_affinity,
.flags = (IRQCHIP_MASK_ON_SUSPEND |
IRQCHIP_SET_TYPE_MASKED |
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] udf: bound lengthAllocDescs from unallocated space entry
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (103 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] ASoC: rt712-sdca: Pull high JD2 to prevent from entering TV mode Sasha Levin
` (411 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable; +Cc: Jay Vadayath, Jan Kara, Sasha Levin, jack, linux-kernel
From: Jay Vadayath <jay@artiphishell.com>
[ Upstream commit b8228f59dc58aea06dc024efd8f64c2d048c4578 ]
udf_read_inode() copies the on-disk lengthAllocDescs field of a USE
(unallocSpaceEntry) inode into iinfo->i_lenAlloc without checking that
it fits in the i_data buffer that is subsequently allocated for the
inode. udf_count_free_table(), called from udf_statfs(), then walks the
allocation descriptor array up to i_lenAlloc bytes, so a crafted UDF
image with lengthAllocDescs larger than (blocksize - sizeof(struct
unallocSpaceEntry)) causes udf_get_fileshortad() to read past the end
of the kmalloc'd i_data buffer.
KASAN report from mounting a crafted UDF image and calling statfs()
from an unprivileged process:
BUG: KASAN: slab-out-of-bounds in udf_get_fileshortad+0x126/0x130
Read of size 4 at addr ffff8880042137d8 by task poc/65
Call Trace:
dump_stack_lvl+0x53/0x70
print_report+0xce/0x610
kasan_report+0xce/0x100
udf_get_fileshortad+0x126/0x130
udf_current_aext+0x3c4/0xa10
udf_next_aext+0x241/0x440
udf_statfs+0xb7d/0x11c0
statfs_by_dentry+0x117/0x1e0
user_statfs+0xac/0x130
__do_sys_statfs+0x80/0xe0
do_syscall_64+0x102/0x5a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Reject USE inodes whose lengthAllocDescs would place descriptors past
the end of the i_data buffer, mirroring the checks the rest of the UDF
code performs on descriptor lengths.
This bug was discovered by Artiphishell's vTriage pipeline, which
generated a userspace reproducer that reliably triggers the KASAN
report on an unpatched kernel. The fix below was drafted with the
Claude coding assistant; a userspace reproducer (and the crafted UDF
image) is available on request.
Assisted-by: LLM
Signed-off-by: Jay Vadayath <jay@artiphishell.com>
Link: https://patch.msgid.link/20260717184021.13476-1-jay@artiphishell.com
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: this is a four-line UDF bounds check for a
KASAN out-of-bounds read on crafted images, and it applies to this tree.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[udf]** **[bound]** bound `lengthAllocDescs` from an
unallocated space entry (USE) inode so descriptor walking cannot run
past the `i_data` buffer.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Assisted-by:** LLM (drafted with Claude)
- **Signed-off-by:** Jay Vadayath \<jay@artiphishell.com\> (author)
- **Link:**
https://patch.msgid.link/20260717184021.13476-1-jay@artiphishell.com
- **Signed-off-by:** Jan Kara \<jack@suse.cz\> (UDF maintainer; applied
the patch)
- **No Fixes:** tag (expected for this review)
- **No Cc: stable** (expected; absence is not a negative)
- **No Reported-by / Tested-by / Reviewed-by / Acked-by**
- Ignored: any pipeline “already selected” markers (none on the real
commit)
Notable: no syzbot tag, but a concrete KASAN stack and a userspace
reproducer are in the body. A later independent patch (Baul Lee, Cc:
stable) reports the same bug.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `udf_read_inode()` copies on-disk `lengthAllocDescs` from a
USE inode into `iinfo->i_lenAlloc` with no check that it fits in the
later `i_data` allocation (`bs - sizeof(struct unallocSpaceEntry)`).
- **Symptom:** KASAN slab-out-of-bounds read in `udf_get_fileshortad()`
after mount + `statfs()`.
- **Failure path:** `statfs` → `udf_statfs` → `udf_count_free_table` →
`udf_next_aext` → `udf_current_aext` → `udf_get_fileshortad`.
- **Trigger:** crafted UDF image; `statfs()` from an unprivileged
process after the image is mounted.
- **Root cause:** USE branch returns before the FE/EFE
`lengthAllocDescs` sanity checks.
- **Fix:** reject USE inodes whose `lengthAllocDescs` would extend past
`i_data`.
- **Version info:** none in the message; the USE path dates to ~2008.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. Explicit KASAN OOB fix with a
reproducer.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `fs/udf/inode.c` — **+4 / −0**
- **Function:** `udf_read_inode()`
- **Scope:** single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record (USE branch in `udf_read_inode`):
- **Before:** set `i_lenAlloc` from on-disk `lengthAllocDescs`, allocate
`i_data` of size `bs - sizeof(struct unallocSpaceEntry)`, memcpy that
many bytes, return 0. Oversized `lengthAllocDescs` is trusted.
- **After:** if `i_lenAlloc > bs - sizeof(struct unallocSpaceEntry)`,
return `-EFSCORRUPTED` via `out:` (which `brelse`s `bh`). Check is
**before** `udf_alloc_i_data()`, so no `i_data` leak on the new error
path.
- **Path:** mount-time inode load for USE (unalloc space table), not a
hot write path.
Verified pre-fix code at `b8228f59dc58a^`:
```
iinfo->i_lenAlloc = le32_to_cpu(... lengthAllocDescs);
ret = udf_alloc_i_data(inode, bs - sizeof(struct unallocSpaceEntry));
```
No bound check. FE/EFE checks at lines 1588–1592 are after this early
`return 0`, so USE never hit them.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Memory safety — out-of-bounds read** of on-disk length.
Mechanism (verified in this tree):
1. `udf_count_free_table()` starts `epos.offset = sizeof(struct
unallocSpaceEntry)`, `epos.bh = NULL`.
2. `udf_current_aext()` (in-ICB) sets `alen =
udf_file_entry_alloc_offset(inode) + iinfo->i_lenAlloc`. For USE,
offset is `sizeof(struct unallocSpaceEntry)`.
3. `udf_get_fileshortad(ptr, alen, &offset, inc)` only checks `*offset +
sizeof(struct short_ad) > maxoffset` (`alen`). Inflated `i_lenAlloc`
makes that check pass while `ptr` walks off the kmalloc’d `i_data`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Quality:** Obviously correct. Same idea as the 2015 FE/EFE checks
(`udf_file_entry_alloc_offset() + i_lenAlloc > bs`). Equal length is
allowed (`>` not `>=`), matching a full-block descriptor array.
- **Jan Kara** changed the submitted `goto out` (ret still `-EIO`) to
`-EFSCORRUPTED`, consistent with other UDF corruption returns in this
tree.
- **Regression risk:** Low. Only crafted/corrupt USE inodes with
`lengthAllocDescs` larger than remaining block space fail to load;
mount then fails instead of later OOB. Valid images are unchanged.
- **No** public API / feature / locking change.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- USE branch and unvalidated `lengthAllocDescs` load: **Marcin Slusarz,
2008** (`48d6d8ff7dca80` / `4b11111aba6c80`), in **v2.6.25-rc1**.
- FE/EFE bounds checks that USE skips: **Jan Kara, 2015**
(`23b133bdc452aa` “udf: Check length of extended attributes and
allocation descriptors”), which itself had `CC: stable`.
- The four new lines: this commit (`b8228f59dc58ae`).
The hole is long-standing, not new-subsystem code.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Equivalent introduction is the 2008 USE caching
plus the 2015 checks that never ran for USE. Both are ancestors of this
HEAD.
A later duplicate patch used `Fixes: 23b133bdc452`. That commit is the
missed-check explanation, not the only origin of the OOB.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `3bd5e45c2ce30` (“fs: udf: fix OOB read in lengthAllocDescs handling”)
— different bug (AED `lengthAllocDescs` vs `bh->b_size` in
`udf_current_aext`). Already in this tree; not a substitute for the
USE `i_data` check.
- `d95094d4c0a62` (“udf: Fix bh leak for unallocated space entries”) —
**after** this commit; adds `brelse(bh)` on the USE success path.
Independent; this fix does not need it.
- Not a numbered series.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Jay Vadayath has this one UDF commit here. **Jan Kara** is the
UDF maintainer (`MAINTAINERS`: UDF FILESYSTEM) and applied it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. Uses existing `i_lenAlloc`, `bs`,
`unallocSpaceEntry`, `udf_alloc_i_data()`, `-EFSCORRUPTED`.
`EFSCORRUPTED` is used throughout `fs/udf/` in this tree
(`3d2d7e61553db` is an ancestor). No new helpers.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c b8228f59dc58ae`:
https://patch.msgid.link/20260717184021.13476-1-jay@artiphishell.com
- `b4 dig -a`: **v1 only** (no v2/v3).
- lore.kernel.org fetches returned **403**; original text verified via
Openwall: https://lists.openwall.net/linux-kernel/2026/07/17/2179
- Submitted 2026-07-17; applied by Jan Kara 2026-07-27.
- Submitted form: comment + `goto out` (ret `-EIO`). Committed form:
`-EFSCORRUPTED`, comment dropped. No NAK found.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): Jay Vadayath, **Jan Kara**, linux-kernel@. linux-
fsdevel was not on the original To/Cc; the maintainer still applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No public syzbot/bugzilla link. Author cites Artiphishell
vTriage + a reproducer. Independent report nine days later: Baul Lee /
XBOW, https://lists.openwall.net/linux-kernel/2026/07/26/145 — same USE
early-return hole, `Cc: stable@vger.kernel.org`.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Duplicate “udf: fix OOB read for a crafted unallocSpaceEntry” (2
lines, `udf_file_entry_alloc_offset() + i_lenAlloc > bs`). Jan Kara
replied that **this** commit already handles it (Spinics/stable thread
snippet). Equivalent fix, not a dependency.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: Duplicate was sent with `Cc: stable`. Jan pointed at
`b8228f59dc58`. Related AED OOB (`3bd5e45c2ce30`) was already backported
to 5.10/5.15. No NAK of *this* fix for stable. lore.kernel.org/stable
search: **403** (UNVERIFIED full stable archive).
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `udf_read_inode()` only. Related: `udf_count_free_table()`,
`udf_current_aext()`, `udf_get_fileshortad()`, `udf_statfs()`,
`__udf_iget()`.
**Step 5.2: TRACE CALLERS**
Record (grep in `fs/udf/`):
- `udf_read_inode()` ← `__udf_iget()`
- `__udf_iget()` ← `udf_iget()` / `udf_iget_special()`
- `udf_iget_special()` ← `udf_load_partition` path in `super.c` when
`unallocSpaceTable.extLength` is set (line ~1163)
- `udf_statfs` is `s_op->statfs` → `statfs(2)`
**Step 5.3: TRACE CALLEES**
Record: new path only assigns `ret` and `goto out` → `brelse(bh); return
ret`. No alloc/lock on the error path.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Mount UDF with a Type-1 partition unalloc space table →
`udf_iget_special` → `udf_read_inode` USE branch. If the inode loads,
unprivileged `statfs(2)` → `udf_count_free()` → `udf_count_free_table()`
when `UDF_PART_FLAG_UNALLOC_TABLE` is set. **Reachable from userspace**
after mount (optical/USB UDF, loop images, automount). After this fix,
corrupt USE fails at mount (`-EFSCORRUPTED`).
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: FE/EFE already checked (2015). AED `lengthAllocDescs` vs `bh`
size already checked (`3bd5e45c2ce30`). USE was the remaining hole
because of the early return.
semcode MCP: **not available**; used grep/read.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: **`v7.3-rc4-27-gf0100363d8c37`**, `VERSION=7 PATCHLEVEL=3
SUBLEVEL=0 EXTRAVERSION=-rc4` (mainline 7.3-rc4, not an LTS branch).
- UDF USE handling **is** in `fs/udf/inode.c`.
- Bug introduced ~**v2.6.25** (2008); FE/EFE checks since **2015**. Both
are ancestors of HEAD.
- The candidate commit **is** an ancestor of HEAD (`git merge-base --is-
ancestor b8228f59dc58a HEAD`). That is expected on mainline and is
**not** treated as “already selected for stable.”
- Without this check, the USE branch in this file is exactly the buggy
pattern.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** on this tree: four lines in a USE branch that
has been stable since 2008/2014. Later `brelse` on success
(`d95094d4c0a62`) does not conflict. `-EFSCORRUPTED` is already used in
`fs/udf/` here.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: AED OOB fix is present but **does not** cover USE `i_data`. No
earlier USE `lengthAllocDescs` bound. This is the USE-specific fix.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **fs/udf** — **IMPORTANT** (not mm/VFS core). UDF is used for
DVD/CD-RW and some USB disks (`fs/udf/Kconfig`). Corrupt-image bugs
still matter for automount and unprivileged `statfs`.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature but active under Jan Kara (writeback, extent, corruption
checks in 7.x). This is a missing validation hole, not a refactor of new
code.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Filesystem-specific** (`CONFIG_UDF_FS`): users who mount UDF
(optical, some USB, disk images).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Crafted/corrupt USE `lengthAllocDescs`; partition has unalloc
space **table** (not only bitmap). Walk happens on `statfs` if LVID
free-space is 0 and bitmap path doesn’t apply. **Unprivileged `statfs`
after mount.** Mount is usually privileged, but removable media is often
automounted. Two independent finders with a reliable KASAN repro.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **KASAN slab-out-of-bounds read** past `i_data`. Without KASAN:
unstable read of adjacent slab (crash and/or info leak). **Severity:
HIGH** (memory safety, local after mount). Not a guaranteed privilege
escalation by itself.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** High — stops a real, reproducible OOB on a user-reachable
`statfs` path.
- **Risk:** Very low — 4 lines, error path only, same check style as
existing UDF validation.
- **Ratio:** Strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR:**
- Real KASAN OOB with stack and reproducer
- Unprivileged `statfs` after mounting crafted UDF
- Two independent reports; duplicate explicitly `Cc: stable`
- UDF maintainer applied it
- 4-line bounds check; no new API
- Bug in USE code since ~2008; this tree has that code
- FE/EFE already had the same class of check; USE skipped it
- New error path is before allocation; `out:` already releases `bh`
**AGAINST:**
- Affects UDF only, and mainly malicious/corrupt images
- Original submission was LLM-assisted (mitigated: maintainer applied;
second reporter confirmed)
- No `Fixes:` / `Cc: stable` on the applied commit (not a negative under
these rules)
**UNRESOLVED:**
- lore.kernel.org 403; discussion taken from b4 + Openwall
- Full stable@ archive not fetched; duplicate + Jan’s “already in my
tree” reply was enough
- No public crafted image in-tree (author offered it on request)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — bound matches buffer size;
KASAN repro; maintainer applied; second independent patch.
2. Fixes a real bug that affects users? **PASS** — OOB on mount +
`statfs`.
3. Important issue? **PASS** — HIGH: slab OOB (crash / info leak), not a
style tweak.
4. Small and contained? **PASS** — +4 lines, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — USE path and `-EFSCORRUPTED`
exist; hunk is self-contained.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. It is a normal
**memory-safety bug fix**.
**Step 9.4: DECISION**
This tree (`v7.3-rc4`) contains the long-standing USE inode path. The
commit closes a real out-of-bounds read with a minimal check that
matches existing UDF validation. It should be backported to this tree’s
stable lineage.
### What the commit solves and why it matters
Unallocated-space (USE) inodes trusted on-disk `lengthAllocDescs` and
then walked that many bytes in a smaller `i_data` buffer. A crafted UDF
image mounts, then `statfs` hits KASAN OOB in `udf_get_fileshortad()`.
After the fix, those inodes fail load with `-EFSCORRUPTED` instead of
reading off the end of the slab.
### Stable rules / risk vs benefit
Surgical, maintainer-acked, no new ABI. Benefit is stopping a user-
reachable memory-safety bug; regression risk is limited to already-
invalid images.
### Concerns
None that block backport here. Optional follow-up `d95094d4c0a62` (bh
leak on the USE success path) is separate. `-EFSCORRUPTED` is already
used in this tree’s UDF code.
---
## Verification
- **[Phase 1]** Parsed commit
`b8228f59dc58aea06dc024efd8f64c2d048c4578`: Assisted-by LLM, Link
msgid, SOB Jay Vadayath + Jan Kara; no Fixes/Cc stable/Reported-by
- **[Phase 1]** Body includes KASAN stack: `udf_get_fileshortad` ←
`udf_current_aext` ← `udf_next_aext` ← `udf_statfs` ← `statfs`
- **[Phase 2]** `git show`: +4 lines in `udf_read_inode()` USE branch
only
- **[Phase 2]** Read `fs/udf/inode.c` USE path (~1475–1493) and FE/EFE
checks (~1588–1592); USE `return 0` skips those checks
- **[Phase 2]** Read `udf_count_free_table()` (`super.c` ~2508),
`udf_current_aext()` (`inode.c` ~2269), `udf_get_fileshortad()`
(`directory.c` ~500) — OOB mechanism confirmed
- **[Phase 2]** Error path is before `udf_alloc_i_data`; `out:` at 1666
does `brelse(bh); return ret`
- **[Phase 3]** `git blame`: USE `lengthAllocDescs` from 2008
(`48d6d8ff7dca80`); FE/EFE checks `23b133bdc452aa` (2015)
- **[Phase 3]** `git merge-base --is-ancestor` 48d6d8ff, 23b133bd,
3d2d7e61, b8228f59 → all ancestors of HEAD
- **[Phase 3]** Related `3bd5e45c2ce30` is AED/bh OOB, not this USE
`i_data` bug
- **[Phase 3]** Follow-up `d95094d4c0a62` only adds `brelse` on success;
not required for this fix
- **[Phase 4]** `b4 dig -c`: msgid
20260717184021.13476-1-jay@artiphishell.com; `-a` v1 only; `-w` Jan
Kara + LKML
- **[Phase 4]** Openwall original patch verified; committed version adds
`-EFSCORRUPTED`
- **[Phase 4]** Duplicate patch 2026-07-26 by Baul Lee, `Cc: stable`;
Jan: this commit already handles it
- **[Phase 4]** lore.kernel.org HTTP 403 — UNVERIFIED full lore thread
beyond b4/Openwall
- **[Phase 5]** Callers: `__udf_iget` → `udf_iget_special` at
`super.c:1163` for unalloc space table; `udf_statfs` is `.statfs`
- **[Phase 5]** semcode unavailable; used grep/read
- **[Phase 6]** `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` = 7.3.0-rc4
- **[Phase 6]** Pre-fix parent `b8228f59^` shows unvalidated
`i_lenAlloc` then `udf_alloc_i_data`
- **[Phase 6]** `-EFSCORRUPTED` used in fs/udf/inode.c, super.c,
namei.c, directory.c, balloc.c, symlink.c
- **[Phase 7]** MAINTAINERS: Jan Kara maintains `fs/udf/`
- **[Phase 8]** Failure mode: slab-OOB read, HIGH; trigger: crafted UDF
+ statfs
- **UNVERIFIED:** Public crafted ISO contents; complete
lore.kernel.org/stable mailbox beyond the duplicate-patch snippet
The patch is a small, correct bounds check for a real KASAN OOB that
this tree’s UDF USE path has had for years.
**YES**
fs/udf/inode.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 84b1a0b7b28d2..e50ecd6746104 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1488,6 +1488,10 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
iinfo->i_lenAlloc = le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)->
lengthAllocDescs);
+ if (iinfo->i_lenAlloc > bs - sizeof(struct unallocSpaceEntry)) {
+ ret = -EFSCORRUPTED;
+ goto out;
+ }
ret = udf_alloc_i_data(inode, bs -
sizeof(struct unallocSpaceEntry));
if (ret)
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ASoC: rt712-sdca: Pull high JD2 to prevent from entering TV mode
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (104 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] udf: bound lengthAllocDescs from unallocated space entry Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] uio: sercos3: add missing MODULE_DEVICE_TABLE() Sasha Levin
` (410 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Jack Yu, Mark Brown, Sasha Levin, oder_chiou, lgirdwood, perex,
tiwai, linux-sound, linux-kernel
From: Jack Yu <jack.yu@realtek.com>
[ Upstream commit dfb8bc1d286fd97b7cf47e3af5df84cfb068d214 ]
Add a patch setting to prevent ALC712 from entering TV mode which
may cause unexpected issues.
Signed-off-by: Jack Yu <jack.yu@realtek.com>
Link: https://patch.msgid.link/20260820092415.2979641-1-jack.yu@realtek.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Local tree is **6.12.111** (`p-6.12-3-gc504cf0baa3d8`). The candidate is
mainline `dfb8bc1d286fd97b7cf47e3af5df84cfb068d214`. It is not in this
checkout; the VB init path it patches is.
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
- Record: `[ASoC/rt712-sdca] [Pull high] Pull JD2 high so ALC712 does
not enter TV mode`
**Step 1.2 — Tags**
- Record:
- `Signed-off-by: Jack Yu <jack.yu@realtek.com>` (vendor author)
- `Link: https://patch.msgid.link/20260820092415.2979641-1-
jack.yu@realtek.com`
- `Signed-off-by: Mark Brown <broonie@kernel.org>` (ASoC maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence is expected for this review)
- Pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit ...]`
ignored
**Step 1.3 — Body**
- Record:
- Bug: ALC712 can enter **TV mode** if JD2 is not pulled high
- Symptom: “unexpected issues” only — no stack trace, no jack/audio
failure description, no machine name
- Root cause (author): missing vendor register write during VB I/O
init
- Version info: none in the message; change is only in
`rt712_sdca_vb_io_init()`, so version B only
**Step 1.4 — Hidden bug fix?**
- Record: Not disguised cleanup. It is a vendor hardware workaround
worded as “add a patch setting.” That matches HDA/ASoC codec init
quirks, not a refactor.
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
- Record:
- `sound/soc/codecs/rt712-sdca.c`: +1 (write in
`rt712_sdca_vb_io_init`)
- `sound/soc/codecs/rt712-sdca.h`: +1 (`#define RT712_JD_CTL3 0x0b`)
- Scope: single-driver, two-line surgical change
**Step 2.2 — Flow**
- Record: Before, VB init never programmed JD_CTL3. After, every
`rt712_sdca_vb_io_init()` call writes NID `RT712_VENDOR_REG` (0x20),
index 0x0b, value `0x7778` via existing `rt712_sdca_index_write()`.
The write is unconditional (not gated on
`FUNCTION_NEEDS_INITIALIZATION`), so it runs on first attach and later
re-init. Normal init path, not an error path.
**Step 2.3 — Bug mechanism**
- Record: **Hardware workaround / codec quirk.** Jack-detect pin JD2 is
pulled high so the analog frontend stays out of TV (CE) jack mode. The
driver already uses JD1 for HP detection (`rt712->jd_src = RT712_JD1`;
enum has no JD2). This is the same class of change as HDA Realtek
pin/coef quirks.
**Step 2.4 — Fix quality**
- Record: Minimal and matches surrounding vendor init writes. Regression
risk is low: one extra MBQ register write at SoundWire attach.
Theoretical risk is a board that needed JD2 floating/low; this driver
does not implement JD2 as a jack source, and Realtek submitted the
value for all VB parts. Magic `0x7778` is undocumented but typical for
this driver.
## Phase 3: Git history
**Step 3.1 — Blame**
- Record: Insertion point in this tree is after the `func_status` debug
print, blamed to `936abb09c1c7c` (“ASoC: rt712-sdca: add the function
for version B”, Shuming Fan, 2024-06-20). `RT712_JD_CTL1` came from
that same commit. Driver itself landed in `6c39710da75ca` (2023-02).
VB init has been in 6.12 since the branch.
**Step 3.2 — Fixes: tag**
- Record: None. Missing init is the “bug”; there is no later bisect
commit that introduced TV mode.
**Step 3.3 — File history**
- Record: Recent in this tree: `8ad30bd5c1088` (reset at io_init for
silent headphone, already backported; that is VA calibration, not this
JD2 write). No other JD_CTL3 work. Standalone, not patch X/Y.
**Step 3.4 — Author**
- Record: Jack Yu is a Realtek ASoC contributor (`jack.yu@realtek.com`).
Other codec work in this tree includes rt722/rt5682s/rt5645 fixes.
Recipients in the original mail include Shuming Fan and other Realtek
codec people.
**Step 3.5 — Dependencies**
- Record: Needs `rt712_sdca_index_write()`, `RT712_VENDOR_REG`, and
`rt712_sdca_vb_io_init()` — all present. No new helpers. Applies
standalone.
## Phase 4: Mailing list / external
**Step 4.1 — Original discussion**
- Record: `b4 dig -c dfb8bc1d286fd97b7cf47e3af5df84cfb068d214` →
https://patch.msgid.link/20260820092415.2979641-1-jack.yu@realtek.com
- `b4 dig -a`: **v1 only**, no later revision
- Thread (mbox): patch + Mark Brown “Applied to … for-7.3”. **No NAK, no
review comments, no Cc: stable in review**
- Takashi Iwai then included it in **sound fixes for 7.3-rc1** (LKML
pull, listed under “Codec fixes for … rt712 …”)
**Step 4.2 — Recipients (`b4 dig -w`)**
- Record: `broonie@kernel.org`, `lgirdwood@gmail.com`, `alsa-devel@alsa-
project.org`, Realtek codec engineers (`shumingf`, `flove`,
`oder_chiou`, `derek.fang`), MediaTek `Trevor.Wu`. ASoC maintainers
were on To.
**Step 4.3 — Bug report**
- Record: No bugzilla/syzbot/user report. Symptom stays vendor-stated
“unexpected issues.”
**Step 4.4 — Series**
- Record: Standalone 1/1. Later mainline `d56fe35` (“reconfigure PLL2 to
fix calibration time-out”) is a **different** Jack Yu fix, not a
prerequisite or revert of JD_CTL3.
**Step 4.5 — Stable list**
- Record: lore.kernel.org HTTP is 403 from this environment. No stable-
thread evidence found via b4. UNVERIFIED: whether anyone already asked
stable@ for this SHA.
## Phase 5: Semantic / call chain
**Step 5.1 — Functions**
- Record: `rt712_sdca_vb_io_init()` only (plus header define).
**Step 5.2 — Callers**
- Record: `rt712_sdca_io_init()` → if `version_id != RT712_VA` →
`rt712_sdca_vb_io_init()`. `rt712_sdca_io_init()` is called from
`rt712_sdca_update_status()` in `rt712-sdca-sdw.c` when the SoundWire
slave is `SDW_SLAVE_ATTACHED` and `hw_init` is false. That is
boot/resume enumeration, not a syscall hot path.
**Step 5.3 — Callees**
- Record: `rt712_sdca_index_write()` → `regmap_write()` on `mbq_regmap`.
Same helper used throughout this file.
**Step 5.4 — Reachability**
- Record: Yes, from userspace-visible audio: plugging/using headset on
Intel SoundWire laptops with RT712 VB (ACPI match tables exist for
MTL/TGL/LNL in this tree). Unprivileged users do not program the
register; they hit it by using audio after attach.
**Step 5.5 — Similar patterns**
- Record: Many sibling vendor `rt712_sdca_index_write()` calls in the
same function. No other `TV mode` / `JD_CTL3` in this tree. `0x7778`
appears in HDA `ALC256_FIXUP_ASUS_HPE` as an unrelated EAPD coef —
same number, different codec, not this bug.
## Phase 6: This tree (6.12.y)
**Step 6.1 — Buggy code present?**
- Record: Yes. `rt712_sdca_vb_io_init()` at
`sound/soc/codecs/rt712-sdca.c:1721` has the exact pre-patch context.
`RT712_JD_CTL3` is **not** defined. `git merge-base --is-ancestor
dfb8bc1d… HEAD` fails (commit not here). `936abb09c1c7c` **is** an
ancestor. Bug/missing workaround exists since VB support (v6.11-era,
in 6.12).
**Step 6.2 — Backport difficulty**
- Record: **Clean apply with line offset.** Mainline hunk is ~1779; here
the same lines are ~1734. Context strings match; `RT712_JD_CTL3` is
free in the header.
**Step 6.3 — Related fixes already here?**
- Record: `8ad30bd5c1088` resets the codec for VA silent headphones. It
does not pull JD2 / program JD_CTL3. No substitute for this
workaround.
## Phase 7: Subsystem
**Step 7.1**
- Record: ASoC codec driver (`sound/soc/codecs/`). Criticality:
**IMPORTANT** for SoundWire Intel laptops with RT712; not core mm/fs.
Peripheral relative to the whole kernel, but a shipping laptop codec.
**Step 7.2**
- Record: Driver is mature in 6.12 (added 2023, VB in 2024). This is a
late vendor init correction, not churn from a brand-new subsystem.
## Phase 8: Impact and risk
**Step 8.1 — Who**
- Record: Config `SND_SOC_RT712_SDCA_SDW` + RT712/713/716/717 **version
B** on SoundWire (Intel MTL/TGL/LNL match files in-tree). Not
universal.
**Step 8.2 — Trigger**
- Record: Device attach / `io_init`. Common for those machines. Not a
race. Not unprivileged memory-safety.
**Step 8.3 — Failure mode**
- Record: Author did not specify. For Realtek PC codecs, TV mode
typically means **wrong jack detect / headset routing / analog
misbehavior**, not an oops. Severity **MEDIUM** as described, **HIGH**
if it silences the jack on real VB laptops. Exact user symptom is
**not independently verified**.
**Step 8.4 — Benefit vs risk**
- Record: Benefit: hardware init correction from the vendor, 2 lines,
same class as HDA/USB quirks that stable takes. Risk: very low (one
init write, no locking/API change). Ratio favors backport.
## Phase 9: Synthesis
**Evidence FOR**
- Two-line vendor codec workaround; hardware-quirk exception in the
stable rules
- Target function and surrounding init sequence exist in 6.12
- Applies with offset only
- ASoC maintainer applied it; it went in **sound fixes for 7.3-rc1**
- RT712 is used on current Intel SoundWire laptops; this tree already
took a related headphone-init fix
- Driver defaults to JD1; pulling unused JD2 high is consistent with
PC/laptop use
**Evidence AGAINST**
- Commit text is vague (“may cause unexpected issues”); no reporter, no
machine, no crash
- Not a UAF/deadlock/corruption class bug
- Magic coef with no bit documentation
- VB-only (VA machines, e.g. some Lunar Lake ThinkPads, are unaffected)
**Unresolved**
- Exact user-visible TV-mode symptom (UNVERIFIED)
- Whether stable@ already discussed this SHA (lore HTTP 403)
**Stable rules checklist**
1. Obviously correct and tested? **PASS** — one existing helper write;
vendor + Mark Brown; no NAK
2. Real bug affecting users? **PASS** — missing hardware init that lets
the codec enter the wrong analog mode (vendor statement; typical
jack/headset breakage, not proven with a public report)
3. Important? **PASS** under the **audio codec quirk** exception
(headphone/JD misconfig), not as a panic/CVE
4. Small and contained? **PASS** — +2 lines, one driver
5. No new features/APIs? **PASS** — existing init path, existing write
helper
6. Can apply to this tree? **PASS** — context matches; JD_CTL3 unused
**Exception category:** Hardware workaround / audio codec quirk (JD pin
config), analogous to HDA Realtek coef/pin quirks.
This is a contained vendor register quirk for hardware that 6.12 already
supports. Benefit is correct analog/jack behavior on RT712 VB; risk is a
single init write. It should be backported to this tree.
Verification:
- [Phase 1] Parsed subject/tags/body from the provided message and
GitHub `dfb8bc1d286fd97b7cf47e3af5df84cfb068d214`
- [Phase 2] Diff is +1 write in `rt712_sdca_vb_io_init` and +1 `#define
RT712_JD_CTL3 0x0b`
- [Phase 3] `git blame` on this tree: insertion point from
`936abb09c1c7c` (2024-06-20); `git merge-base --is-ancestor
936abb09c1c7c HEAD` true
- [Phase 3] `git merge-base --is-ancestor
dfb8bc1d286fd97b7cf47e3af5df84cfb068d214 HEAD` false (not in 6.12)
- [Phase 3] `git log --oneline -20 -- sound/soc/codecs/rt712-sdca.c`:
related `8ad30bd5c1088` is a different VA reset fix
- [Phase 4] `b4 dig -c dfb8bc1d…` / `-a` / `-w` / `-m`: v1, alsa-devel,
applied by Mark Brown to for-7.3; no NAK
- [Phase 4] LKML: Takashi listed this under 7.3-rc1 sound fixes
- [Phase 4] lore.kernel.org WebFetch/curl: 403
- [Phase 5] Callers: `rt712_sdca_update_status` → `rt712_sdca_io_init` →
`rt712_sdca_vb_io_init`; intel ACPI match files reference rt712
- [Phase 6] `git describe HEAD` / `make kernelversion`: 6.12.111; hunk
context present; `RT712_JD_CTL3` absent
- [Phase 8] Failure mode: TV-mode analog/JD misbehavior (vendor); not a
kernel oops — UNVERIFIED exact symptom
- UNVERIFIED: datasheet meaning of `0x7778`; whether every VB board
needs it; stable@ discussion
**YES**
sound/soc/codecs/rt712-sdca.c | 1 +
sound/soc/codecs/rt712-sdca.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c
index d8b40663fa92f..a799b8aab73aa 100644
--- a/sound/soc/codecs/rt712-sdca.c
+++ b/sound/soc/codecs/rt712-sdca.c
@@ -1786,6 +1786,7 @@ static void rt712_sdca_vb_io_init(struct rt712_sdca_priv *rt712)
dev_dbg(dev, "%s jack/mic/amp func_status=0x%x, 0x%x, 0x%x\n",
__func__, jack_func_status, mic_func_status, amp_func_status);
+ rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_JD_CTL3, 0x7778);
/* DMIC */
if ((mic_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt712->first_hw_init)) {
rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_DMIC2_FU_IT_FLOAT_CTL, 0x1526);
diff --git a/sound/soc/codecs/rt712-sdca.h b/sound/soc/codecs/rt712-sdca.h
index 7ab7d5feb50a2..46740281a5c17 100644
--- a/sound/soc/codecs/rt712-sdca.h
+++ b/sound/soc/codecs/rt712-sdca.h
@@ -74,6 +74,7 @@ struct rt712_dmic_kctrl_priv {
#define RT712_JD_PRODUCT_NUM 0x00
#define RT712_ANALOG_BIAS_CTL3 0x04
#define RT712_JD_CTL1 0x09
+#define RT712_JD_CTL3 0x0b
#define RT712_IO_CTL 0x0c
#define RT712_LDO2_3_CTL1 0x0e
#define RT712_PARA_VERB_CTL 0x1a
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] uio: sercos3: add missing MODULE_DEVICE_TABLE()
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (105 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] ASoC: rt712-sdca: Pull high JD2 to prevent from entering TV mode Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: requeue buffers if start_streaming fails Sasha Levin
` (409 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Greg Kroah-Hartman, Sasha Levin, linux-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit a432f68c51fc6761658445e80a798b8425fdb3dc ]
The driver has a match table for the pci bus wired into its driver
structure, but the table is not exported with MODULE_DEVICE_TABLE().
Add the missing MODULE_DEVICE_TABLE() entry so module alias information
is generated for automatic module loading.
This is a source-level fix. It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the driver registration structure, and the missing module alias
publication.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260704152642.54769-1-pengpeng@iscas.ac.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Local tree is **v7.3-rc4** (mainline). The change is a one-line
`MODULE_DEVICE_TABLE()` so PCI aliases are generated; that is a real
autoload bug with no runtime risk.
## Phase 1: Commit message forensics
**Step 1.1: Subject**
Record: **[uio/sercos3] [add] [export the existing PCI ID table with
MODULE_DEVICE_TABLE()]**
**Step 1.2: Tags**
Record:
- `Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>` (author)
- `Link:
https://patch.msgid.link/20260704152642.54769-1-pengpeng@iscas.ac.cn`
- `Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>`
(UIO/char-misc maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence of the last two is expected for this
review)
**Step 1.3: Body**
Record:
- **Bug:** `sercos3_pci_ids` is wired into `sercos3_pci_driver.id_table`
but not published with `MODULE_DEVICE_TABLE()`.
- **Symptom:** depmod/modpost emit no PCI aliases, so udev/kmod will not
autoload `uio_sercos3` when a matching card appears.
- **Version info:** none in the message. The ID table has been in the
driver since 2008.
- **Root cause:** missing module-alias publication, not a wrong match
table.
**Step 1.4: Hidden bug fix?**
Record: **No disguise.** It is an explicit metadata-export fix. The
“source-level / no hardware reproduction” sentence is honesty about
evidence, not a cleanup-only change. Without the macro, modular autoload
is broken.
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record:
- File: `drivers/uio/uio_sercos3.c` — **+1 / −0**
- Function/data: `sercos3_pci_ids` (static PCI ID table), immediately
before `sercos3_pci_driver`
- Scope: **single-file surgical fix**
**Step 2.2: Code flow**
Record:
- **Before:** table exists and is used at runtime by PCI core *after*
the module is already loaded (or if built-in).
- **After:** same runtime matching, plus `MODULE_DEVICE_TABLE(pci,
sercos3_pci_ids)` so modpost/`file2alias.c` emits
`pci:v...d...sv...sd...` aliases into the module.
- Path affected: **build-time module metadata / userspace autoload**,
not probe/remove/IRQ.
**Step 2.3: Bug mechanism**
Record: **Hardware enablement / missing device-table export** (same
family as adding PCI IDs).
- Mechanism: `scripts/mod/file2alias.c` `do_pci_entry()` only walks
tables found via `MODULE_DEVICE_TABLE()`. No macro → no aliases → no
autoload.
- Runtime `id_table` is unchanged, so probe matching is not altered.
**Step 2.4: Fix quality**
Record: **Obviously correct, one line, no unrelated edits.** Regression
risk is **very low**: aliases match the same
vendor/device/subvendor/subdevice entries the driver already uses. No
locking, no API, no data-structure change.
## Phase 3: Git history
**Step 3.1: Blame**
Record: ID table and `pci_driver` come from **`a6030fcc608bd`** (“UIO:
add automata sercos3 pci card support”, John Ogness, 2008-09-18). That
commit never added `MODULE_DEVICE_TABLE()`. The table was later made
`const` in `511d7a35a438d` (2025). The missing export has been present
for the entire life of the driver.
**Step 3.2: Fixes: tag**
Record: **None.** Introduced by `a6030fcc608bd` (verified: parent of
this fix has no `MODULE_DEVICE_TABLE` in this file). `git grep` on
`a432f68c51fc6^ -- drivers/uio/uio_sercos3.c` returned no match.
**Step 3.3: File history**
Record: Recent commits on this file are constify, devm allocs, SPDX,
`module_pci_driver`. **No prerequisite series.** Standalone one-liner.
Same class of UIO fix already exists historically: **`912335c43bb10`**
(“UIO: fix specific device driver missing statement for depmod”, 2009)
added `MODULE_DEVICE_TABLE` to `uio_cif.c` for the same depmod/alias
reason.
**Step 3.4: Author**
Record: Pengpeng Hou is not the UIO maintainer. Same author has a batch
of “add missing MODULE_DEVICE_TABLE()” patches (rtc, vdpa, watchdog,
fbdev, soc, can, clk, power). Pattern is systematic and consistent.
Maintainer of record is Greg Kroah-Hartman, who applied it.
**Step 3.5: Dependencies**
Record: **None.** Uses the long-standing `MODULE_DEVICE_TABLE()` macro
in `include/linux/module.h`. Can apply standalone.
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
Record:
- `b4 dig -c a432f68c51fc6` →
https://patch.msgid.link/20260704152642.54769-1-pengpeng@iscas.ac.cn
- Openwall copy: https://lists.openwall.net/linux-kernel/2026/07/04/476
- `b4 dig -a`: **v1 only**, 2026-07-04. Applied version is that v1.
- No reviewer comments, NAKs, or `Cc: stable` suggestions found in the
retrieved thread.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: Pengpeng Hou, **Greg Kroah-Hartman**, `linux-
kernel@vger.kernel.org`. Correct maintainer was To:’d.
**Step 4.3: Bug report**
Record: **No user/syzbot/bugzilla report.** Author states source-level
evidence only.
**Step 4.4: Series**
Record: **Standalone**, not `N/M`.
**Step 4.5: Stable list**
Record: **UNVERIFIED.** `lore.kernel.org/stable` and git.kernel.org
fetches returned 403 (Anubis). Openwall search found the lkml submission
only, not a stable-thread discussion.
## Phase 5: Semantic / impact
**Step 5.1: Functions**
Record: No function body changed. Data: `sercos3_pci_ids`; consumer:
`sercos3_pci_driver`.
**Step 5.2: Callers**
Record:
- Runtime: PCI core uses `.id_table` from
`module_pci_driver(sercos3_pci_driver)` → `sercos3_pci_probe` on
match.
- Autoload: udev/kmod uses aliases generated from `MODULE_DEVICE_TABLE`.
- Not IRQ/hot path; module-load / device-enumeration path.
**Step 5.3: Callees**
Record: The new line expands to an alias symbol for modpost. No new
runtime calls.
**Step 5.4: Reachability**
Record: **Yes, from userspace + hardware.** Trigger is a matching PLX
9030 + Sercos subsystem ID (0x1971 / 0x3530, 0x3535, 0x3780) with
`CONFIG_UIO_SERCOS3=m`. Built-in (`=y`) never needed aliases.
**Step 5.5: Similar patterns**
Record: Sibling UIO PCI drivers already export tables: `uio_cif.c`,
`uio_netx.c`, `uio_mf624.c`, `uio_aec.c`. `uio_sercos3` was the outlier.
OF/vmbus/dfl UIO drivers also use `MODULE_DEVICE_TABLE`.
## Phase 6: This checkout
**Step 6.1: Does the buggy code exist here?**
Record:
- Tree: **`v7.3-rc4-27-gf0100363d8c37`**, `VERSION=7 PATCHLEVEL=3
SUBLEVEL=0 EXTRAVERSION=-rc4`, origin `torvalds/linux.git`.
- File and PCI ID table exist (`drivers/uio/uio_sercos3.c`).
- At **HEAD**, `MODULE_DEVICE_TABLE(pci, sercos3_pci_ids)` is already at
line 215 (`git merge-base --is-ancestor a432f68c51fc6 HEAD`
succeeded). That is expected: this checkout is mainline after 7.3-rc1,
i.e. the **source** of stable candidates, not a missing-driver stable
branch.
- Bug introduced: **2008** (`a6030fcc608bd`). Not a post-branch feature.
**Step 6.2: Backport difficulty**
Record: **Clean apply.** Surrounding table/`pci_driver` layout matches
the hunk. No refactor blocking a one-line insert.
**Step 6.3: Related fixes already here**
Record: This is the fix. No alternate alias-export for this driver.
Historical analogue is `uio_cif`’s 2009 `MODULE_DEVICE_TABLE` addition.
## Phase 7: Subsystem
**Step 7.1:**
Record: **UIO PCI driver** (`drivers/uio/`). Criticality: **PERIPHERAL**
— Automata Sercos III industrial card, `CONFIG_UIO_SERCOS3` tristate,
default n, `depends on PCI`.
**Step 7.2:**
Record: **Mature / low churn.** Driver added 2008; later commits are
cleanup (`module_pci_driver`, SPDX, devm, constify). Not a new
subsystem.
## Phase 8: Impact and risk
**Step 8.1: Who is affected**
Record: **Driver-specific / config-specific:** `CONFIG_UIO_SERCOS3=m`
and a matching PCI card. Built-in and systems without the card are
unaffected.
**Step 8.2: Trigger**
Record: PCI enumeration + udev module lookup. Common on modular distro
kernels **if the hardware is present**. Unprivileged users cannot
trigger it without the card. Not a race.
**Step 8.3: Failure mode**
Record: Module not autoloaded; card stays unbound until `modprobe
uio_sercos3`. **Severity: MEDIUM** (real functional break, not
oops/corruption/security). Workaround exists but is not how PCI drivers
are supposed to load.
**Step 8.4: Risk-benefit**
Record:
- **Benefit:** restores autoload for existing IDs (same user-visible
outcome as a device-ID addition).
- **Risk:** very low (one metadata line, no runtime change).
- **Ratio:** favorable.
## Phase 9: Synthesis
**Step 9.1: Evidence**
For:
- Real autoload bug: ID table registered, aliases never published.
- Same class as the stable “add a device ID” exception; IDs already
exist, they were just invisible to kmod.
- One line, obviously correct, no API/feature.
- Sibling UIO PCI drivers already do this; `uio_cif` got the same depmod
fix in 2009.
- Greg Kroah-Hartman applied v1 unchanged.
- Driver present since 2008; no missing prerequisites on this tree.
Against:
- Niche hardware; no `Reported-by` in ~18 years.
- Not a crash, deadlock, or security issue.
- Author did not reproduce on hardware (stated).
- Manual `modprobe` still works.
Unresolved:
- Stable mailing-list discussion (lore 403).
**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — one-line, standard macro;
Greg applied it. Hardware repro not required for alias generation.
2. Real bug affecting users? **PASS** — modular autoload fails for
matching PCI devices.
3. Important? **PASS** (device-ID / hardware-enablement class) — not a
panic, but it is the userspace half of PCI ID support; stable rules
explicitly allow device-ID additions.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features/APIs? **PASS** — publishes existing IDs.
6. Can apply to this tree? **PASS** — driver and table are here; hunk
matches.
**Step 9.3: Exception**
Record: **Device ID / hardware-enablement.** Closest documented
exception: “just add a device ID.” This exports IDs the driver already
matches.
**Step 9.4: Decision**
This tree has the driver and the ID table; the omission is a real
modular-load bug, the patch is a one-line metadata export with no
runtime risk, and it matches how other UIO PCI drivers (and stable’s
device-ID exception) already work. It should be selected for stable.
---
**What it solves for stable users:** With `CONFIG_UIO_SERCOS3=m`, a
Sercos III PLX 9030 card will not cause udev to load `uio_sercos3`
because `modules.alias` has no PCI entries. The line adds those aliases.
Distro/LTS kernels typically ship such drivers as modules.
**Rules:** Small, correct, no new API; equivalent to enabling existing
device IDs for autoload.
**Risk vs benefit:** Benefit is autoload on real hardware; risk is
essentially zero.
**Concerns:** Niche card and no crash report, but that does not outweigh
a zero-risk hardware-enablement one-liner that applies cleanly.
Verification:
- [Phase 1] Parsed tags: author SOB, Greg KH SOB, lore msgid Link; no
Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: +1 `MODULE_DEVICE_TABLE(pci, sercos3_pci_ids)` after
`sercos3_pci_ids[]` in `drivers/uio/uio_sercos3.c`
- [Phase 2] Confirmed `sercos3_pci_driver.id_table = sercos3_pci_ids`
and `module_pci_driver(sercos3_pci_driver)`
- [Phase 3] `git blame`: table from `a6030fcc608bd` (2008); this line
from `a432f68c51fc6`
- [Phase 3] `git grep` on parent: no `MODULE_DEVICE_TABLE` in this file;
HEAD has it at line 215
- [Phase 3] Historical analogue: `912335c43bb10` added the same macro to
`uio_cif.c` for depmod
- [Phase 4] `b4 dig -c a432f68c51fc6`: lore/msgid match; `-a`: v1 only;
`-w`: Greg KH + lkml
- [Phase 4] Openwall thread matches committed patch; no NAK found
- [Phase 4] lore.kernel.org WebFetch: 403 — stable-list discussion
UNVERIFIED
- [Phase 5] `MODULE_DEVICE_TABLE` in `include/linux/module.h`;
`do_pci_entry()` in `scripts/mod/file2alias.c`
- [Phase 5] Sibling UIO PCI drivers already have `MODULE_DEVICE_TABLE`
- [Phase 6] `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion` = 7.3.0-rc4
- [Phase 6] `git merge-base --is-ancestor a432f68c51fc6 HEAD` exit 0
(commit is in this mainline checkout)
- [Phase 6] Commit not in `v7.2`; is in `v7.3-rc1`
- [Phase 7] `CONFIG_UIO_SERCOS3` tristate, depends on PCI, module name
`uio_sercos3`
- [Phase 8] Failure mode: no PCI aliases → no autoload; severity MEDIUM;
risk very low
- UNVERIFIED: whether this hash was already applied on some older stable
branch (not this checkout; not used for the verdict)
**YES**
drivers/uio/uio_sercos3.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
index 12afc2fa1a0bb..80087897f9b86 100644
--- a/drivers/uio/uio_sercos3.c
+++ b/drivers/uio/uio_sercos3.c
@@ -212,6 +212,7 @@ static const struct pci_device_id sercos3_pci_ids[] = {
},
{ 0, }
};
+MODULE_DEVICE_TABLE(pci, sercos3_pci_ids);
static struct pci_driver sercos3_pci_driver = {
.name = "sercos3",
--
2.53.0
^ permalink raw reply related [flat|nested] 629+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] media: em28xx: requeue buffers if start_streaming fails
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
` (106 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] uio: sercos3: add missing MODULE_DEVICE_TABLE() Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] ksmbd: handle allocated range queries on dense files Sasha Levin
` (408 subsequent siblings)
516 siblings, 0 replies; 629+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Hans Verkuil, Mauro Carvalho Chehab, Sasha Levin, mchehab,
linux-media, linux-kernel
From: Hans Verkuil <hverkuil+cisco@kernel.org>
[ Upstream commit 67f87b104f4ef3108607ac9d8fa2075b13ed314d ]
If start_streaming fails, then all queued buffers must be
returned to vb2 in state QUEUED.
Otherwise it will trigger a WARN_ON.
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
candidate is a real videobuf2 `start_streaming` error-path bug in
`em28xx`: queued buffers were left driver-owned, which fires `WARN_ON`
and can leave stale entries on `dmaq->active`.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[media/em28xx] [requeue] [return queued vb2 buffers when
start_streaming fails]**
Subsystem `media: em28xx`. Action is “requeue” (correctness on failure,
not a feature).
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none
- **Tested-by:** Hans Verkuil \<hverkuil+cisco@kernel.org\> (author
tested it)
- **Reviewed-by / Acked-by:** none on the commit
- **Link:** none in the commit; lore found via `b4 dig` (Phase 4)
- **Cc: stable:** none (expected)
- **Signed-off-by:** Hans Verkuil (author); Mauro Carvalho Chehab (media
maintainer). Ignore any Sasha Levin SOB if present — none on this
commit.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** If `start_streaming` fails, buffers already given to the
driver via `buf_queue` are not returned to vb2 as
`VB2_BUF_STATE_QUEUED`.
- **Symptom:** vb2 `WARN_ON` in `vb2_start_streaming()` when
`owned_by_drv_count != 0`.
- **Version info:** none in the message.
- **Root cause (author):** driver violates the documented
`start_streaming` contract.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: **Not hidden.** Explicit contract fix. Cover letter (Phase 4)
also states this patch “correctly gives the vb2 buffers back … if
start_streaming fails.”
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/media/usb/em28xx/em28xx-video.c` — **+16 / −2**
- Function: `em28xx_start_analog_streaming()`
- Scope: **single-file surgical error-path fix**
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- **Before:** `res_get()` failure and `em28xx_init_usb_xfer()` failure
both `return rc` immediately. Buffers already on `vidq`/`vbiq`
`active` stay driver-owned.
- **After:** those paths `goto exit`, which under `dev->slock` walks
`dmaq->active`, `list_del`s each buffer, and calls
`vb2_buffer_done(..., VB2_BUF_STATE_QUEUED)`. Success still increments
`streaming_users` and returns 0.
- **Path affected:** STREAMON / qbuf-triggered `start_streaming`
**error** path only.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **[Logic / vb2 contract] + memory-safety follow-on**
- vb2 calls `__enqueue_in_driver()` → `buf_queue` **before**
`start_streaming` (`videobuf2-core.c`).
- `buffer_queue` / `vbi_buffer_queue` put buffers on `dev->vidq.active`
/ `dev->vbiq.active`.
- On failure the driver must `vb2_buffer_done(..., QUEUED)` (documented
in `videobuf2-core.h` `@start_streaming`).
- Without that, `vb2_start_streaming()` does
`WARN_ON(owned_by_drv_count)` and force-reclaims in vb2 **without**
unlinking the driver’s list, so `dmaq->active` can keep dangling
`em28xx_buffer` pointers. `get_next_buf()` later takes
`dma_q->active.next` — **UAF** on a later successful stream.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- **Quality:** Matches `em28xx_stop_streaming()` and the standard V4L2
pattern. Author is V4L2 maintainer; self-tested.
- **Minimal:** only the failure cleanup.
- **Regression risk:** low (error path, same lock as stop). Minor
incompleteness: `stop_streaming` also completes `usb_ctl.vid_buf`;
this path does not. `em28xx_alloc_urbs()` already NULLs those pointers
before submit, and failed `init_usb_xfer` calls
`em28xx_uninit_usb_xfer()`. Common failures (`res_get` -EBUSY,
alloc/submit fail with empty in-flight slot) are covered. Incomplete
vs. a rare in-flight URB does not make the patch wrong.
- **No API/feature changes.**
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- `em28xx_start_analog_streaming` comes from **d3829fadc461**
(“\[media\] em28xx: convert to videobuf2”, 2013-01-05), contained in
**v3.9-rc1**.
- Failure just `return rc` is that old. Bug is long-standing, not
new-7.3 code.
Step 3.2: FOLLOW THE FIXES: TAG
Record: **No Fixes: tag.** Closest related error-path change:
**cc20e81da6d99** (“fix missing res_free() on init_usb_xfer failure”,
2026-05) added `res_free()` before `return rc`. This commit turns that
`return` into `goto exit`. Complementary, not a substitute.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Same series (lifecycle): `288254383674b`, `de626073dfcbb`,
`7c8bf63b79371`, `c132b07f7e585` — device lifetime/UAF, **not
required** for this hunk.
- This is **standalone**: only the start_streaming returns change. Cover
letter lists it as 6/6, but the diff does not use symbols those
patches add.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Hans Verkuil is a V4L2 maintainer (not the em28xx MAINTAINERS
entry; that is Mauro Chehab, who signed this off). Same class of fix
historically: e.g. **80b0963e1698e** “\[media\] pwc: fix WARN_ON”
(QUEUED vs ERROR on start_streaming failure).
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: **No hard functional dependency.** Applies against the pre-fix
function in this tree’s parent. Older stables without `cc20e81` only
need a trivial context adjust (`return rc` vs `res_free`+`return rc`).
**Standalone.**
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 67f87b104f4ef`: **[PATCHv2 6/6]** https://patch.msgid.link/
141d43a4860c6007269e9725cc717a556d22d2a4.1781615432.git.hverkuil+cisco
@kernel.org
- `b4 dig -a`: v1 was a 3-patch lifecycle series (2026-05-19); v2 is
**[PATCHv2 0/6] media: em28xx: fix lifecycle issues** (2026-06-16).
Applied version is v2 patch 6.
- Cover letter: last patch returns buffers if start_streaming fails;
**tested on author’s em28xx device**.
- **No NAK** on patch 6. Sakari Ailus only discussed patch 1
(`v4l2-async`).
- **No reviewer Cc: stable.** WebFetch to lore returned **403**; thread
recovered via `b4 dig -m`.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc **linux-media**, Hans Verkuil, Mauricio
Faria de Oliveira, Sakari Ailus. Merged by Mauro Chehab. No separate
Reviewed-by on 6/6.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Author found it while testing the lifecycle
series. Mechanism is specified in vb2 (WARN_ON comment names this exact
driver bug class).
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Series 1–5 are separate lifecycle/UAF work. **6/6 is self-
contained** and does not need 1–5 in this tree.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No “stable” in the matched mbox. WebSearch did not find a
stable-list thread for this subject (lore HTML 403). **No evidence it
was rejected for stable.**
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: **`em28xx_start_analog_streaming`**. Helpers used: `res_get`,
`res_free`, `em28xx_init_usb_xfer`, `vb2_buffer_done`.
Step 5.2: TRACE CALLERS
Record: Wired as `.start_streaming` in:
- `em28xx_video_qops` (`em28xx-video.c`)
- `em28xx_vbi_qops` (`em28xx-vbi.c`)
Callers are vb2 (`vb2_start_streaming` ← `vb2_core_streamon` /
`vb2_core_qbuf`). **Userspace V4L2 STREAMON/QBUF.**
Step 5.3: TRACE CALLEES
Record: `res_get` can return **-EBUSY**. `em28xx_init_usb_xfer` can fail
on URB alloc, `usb_clear_halt`, or `usb_submit_urb` (and then
`em28xx_uninit_usb_xfer`). Those are realistic (disconnect, ENOMEM, USB
error).
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace ioctl → vb2 enqueues via `buf_queue` →
`start_streaming` → on failure, buffers must be returned. **Reachable
from userspace** with `CONFIG_VIDEO_EM28XX` / `CONFIG_VIDEO_EM28XX_V4L2`
and a device node.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Many drivers return `VB2_BUF_STATE_QUEUED` on start_streaming
failure (uvc, pwc, gspca, hackrf, platform capture drivers). em28xx was
missing that. Historical media commits: pwc, coda, cal, am437x-vpfe.
semcode MCP: **not available** in this session (only `cursor` dynamic
tools). Used grep/read instead.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes.** This checkout is **7.3.0-rc4**. Commit
**67f87b104f4ef** **is an ancestor of HEAD** (in since v7.3-rc1). Parent
of the commit still has the bare `return rc` paths. Driver and
`em28xx_start_analog_streaming` have been here since the vb2 conversion
(**v3.9**). The bug is not “new after this branch.”
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: For **this** tree the patch is already applied and matches
current `em28xx-video.c`. Against the pre-fix function it is a clean,
18-line change. No conflicting refactor in the start_streaming body
itself.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: `cc20e81da6d99` (res_free on USB-init failure) is in this tree.
It does **not** requeue buffers. No other equivalent fix for this
WARN_ON.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **drivers/media/usb/em28xx** — USB analog/VBI capture (Empia,
Hauppauge, etc.). **IMPORTANT** for users of that hardware,
**PERIPHERAL** vs core mm/net. Not staging.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Actively maintained (lifecycle series, device IDs, UAFs in
2026). Mature driver, old bug. MAINTAINERS: Mauro Chehab; linux-media.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific** (`CONFIG_VIDEO_EM28XX` / V4L2). Empia USB
capture sticks and several Hauppauge devices. Not universal, but real
hardware.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Trigger: `VIDIOC_STREAMON` (or qbuf that starts streaming) when
`res_get` fails or USB xfer init fails.
- Commonness: error path, not every boot. USB submit/alloc failure and
unplug-during-start are realistic.
- Unprivileged: yes if the user can open `/dev/video*` (typical `video`
group).
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- Immediate: **WARN_ON** in vb2 (`videobuf2-core.c` around the “driver
isn’t cleaning up properly after a failed start_streaming()” comment).
`panic_on_warn` → panic.
- Follow-on: leftover `dmaq->active` entries after vb2 force-reclaim →
**UAF** in `get_next_buf()` on retry.
- **Severity: HIGH** (WARN_ON + UAF on retry). Not a silent style issue.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** high for em28xx users (stops WARN_ON and dangling DMA
list).
- **Risk:** very low (~16 lines, error path, same locking as stop).
- **Ratio:** favorable.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
**FOR:**
- Real vb2 contract violation; documented WARN_ON.
- Dangling `active` list can UAF on the next STREAMON.
- Small, obviously correct, matches driver stop path and many other V4L2
drivers.
- V4L2 maintainer authored and tested on real em28xx hardware; media
maintainer merged it.
- Bug in code since ~v3.9; present in this tree’s pre-fix function.
- Standalone; no new API.
**AGAINST:**
- USB capture driver, not core; only hits failed STREAMON.
- No syzbot / external Reported-by.
- Patch 6/6 of a larger series (but this hunk does not depend on 1–5).
- Does not also complete `usb_ctl.vid_buf` (stop_streaming does); common
fail paths still fixed.
**UNRESOLVED:**
- lore.kernel.org HTTP 403 for WebFetch; thread read via `b4` mbox
instead.
- No stable@ discussion found.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — contract match + Tested-by
author on hardware.
2. Fixes a real bug that affects users? **PASS** — STREAMON failure on a
used USB capture driver.
3. Important issue? **PASS** — WARN_ON; UAF on retry. HIGH, not
cosmetic.
4. Small and contained? **PASS** — 16 insertions / 2 deletions, one
function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — code is this driver; patch
already applies here (it is in 7.3-rc1+). No missing prerequisites
for *this* hunk.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **None** (not an ID/quirk/DT/build/docs exception). It is a
normal small bugfix.
Step 9.4: MAKE YOUR DECISION
This tree has the em28xx analog/VBI vb2 path. The fix is a classic,
surgical start_streaming cleanup that prevents WARN_ON and leftover
driver-owned buffers. It meets stable rules for this checkout.
What it solves for users of this tree: failed `VIDIOC_STREAMON` no
longer trips vb2’s `WARN_ON` and no longer leaves capture buffers on
`dmaq->active` for a later UAF.
Risk vs benefit: error-path only, low regression risk, meaningful
correctness fix.
Concerns: none that block a backport here; series membership is
packaging, not a code dependency.
Verification:
- \[Phase 1\] Parsed tags: Tested-by Hans Verkuil; SOB Hans + Mauro; no
Fixes/Reported-by/Cc stable
- \[Phase 2\] Diff: +16/-2 in `em28xx_start_analog_streaming`; `return
rc` → `goto exit` + `vb2_buffer_done(QUEUED)`
- \[Phase 2\] Confirmed vb2 contract and WARN_ON in
`vb2_start_streaming()` (`videobuf2-core.c` ~1769–1815)
- \[Phase 2\] Confirmed `buf_queue` adds to `vidq`/`vbiq` active before
start_streaming
- \[Phase 2\] Confirmed `get_next_buf()` uses `dma_q->active.next` (UAF
if list not cleared)
- \[Phase 3\] `git blame`: function from d3829fadc461 (v3.9-rc1)
- \[Phase 3\] `git merge-base --is-ancestor 67f87b104f4ef HEAD` → yes
(exit 0)
- \[Phase 3\] `git describe HEAD` → v7.3-rc4-27-gf0100363d8c37; `make
kernelversion` → 7.3.0-rc4
- \[Phase 3\] Related: cc20e81da6d99 only adds res_free; does not
requeue
- \[Phase 4\] `b4 dig -c 67f87b104f4ef`: PATCHv2 6/6; cover letter
describes this exact fix; tested on em28xx
- \[Phase 4\] `b4 dig -a`: v1 3-patch → v2 6-patch lifecycle series; 6/6
standalone
- \[Phase 4\] `b4 dig -w`: linux-media, Sakari Ailus, Mauricio Faria de
Oliveira
- \[Phase 4\] WebFetch lore/msgid.link: 403; used mbox instead
- \[Phase 5\] Callers: `em28xx_video_qops` and `em28xx_vbi_qops`
`.start_streaming`
- \[Phase 5\] Failures: `res_get` -EBUSY; `em28xx_init_usb_xfer`
alloc/halt/submit
- \[Phase 6\] Pre-fix parent still has bare `return rc`; this tree
includes the fix
- \[Phase 7\] MAINTAINERS: EM28XX VIDEO4LINUX DRIVER, Mauro Chehab
- \[Phase 8\] Failure: WARN_ON + dangling list UAF; severity HIGH
- UNVERIFIED: stable@ mailing list (lore HTTP 403; no hit in matched
mbox)
The patch is small, correct, and fixes a real WARN_ON/UAF class bug in
code this tree carries.
**YES**
drivers/media/usb/em28xx/em28xx-video.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index c8514682bccda..e0a69309687b0 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1070,6 +1070,9 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
{
struct em28xx *dev = vb2_get_drv_priv(vq);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
+ struct em28xx_dmaqueue *dmaq = vq->type == V4L2_BUF_TYPE_VBI_CAPTURE ?
+ &dev->vbiq : &dev->vidq;
+ unsigned long flags = 0;
struct v4l2_frequency f;
struct v4l2_fh *owner;
int rc = 0;
@@ -1084,7 +1087,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
*/
rc = res_get(dev, vq->type);
if (rc)
- return rc;
+ goto exit;
if (v4l2->streaming_users == 0) {
/* First active streaming user, so allocate all the URBs */
@@ -1107,7 +1110,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
em28xx_urb_data_copy);
if (rc < 0) {
res_free(dev, vq->type);
- return rc;
+ goto exit;
}
/*
@@ -1132,7 +1135,18 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
}
v4l2->streaming_users++;
+ return 0;
+exit:
+ spin_lock_irqsave(&dev->slock