* [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: validate and share PSP fw_pri_buf copies via psp_copy_fw
[not found] <20260831133314.4125787-1-sashal@kernel.org>
@ 2026-08-31 13:21 ` Sasha Levin
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Check for sharpening case when calculating max vtaps for scaler Sasha Levin
` (36 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:21 UTC (permalink / raw)
To: patches, stable
Cc: Candice Li, Tao Zhou, Alex Deucher, Sasha Levin, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Candice Li <candice.li@amd.com>
[ Upstream commit d1f9f5839bd785a3a06335a01d53282e80f8e5fa ]
Change psp_copy_fw from void to int: return -ENODEV when drm_dev_enter
fails, and -EINVAL when the image size is zero or larger than the
1 MiB PSP private buffer.
Replace open-coded memset/memcpy into fw_pri_buf with psp_copy_fw.
Signed-off-by: Candice Li <candice.li@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:
# Stable Backport Analysis: `drm/amdgpu: validate and share PSP
fw_pri_buf copies via psp_copy_fw`
**Local tree:** `v6.18.44` (`stable/linux-6.18.y`)
**Upstream commit:** `d1f9f5839bd78` (not yet in this tree)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject Line
**Record:** `[drm/amdgpu]` `[validate]` — Add size validation and error
propagation to `psp_copy_fw`, consolidating open-coded `fw_pri_buf`
copies.
### Step 1.2: Tags
**Record:**
- `Signed-off-by: Candice Li <candice.li@amd.com>` (author)
- `Reviewed-by: Tao Zhou <tao.zhou1@amd.com>`
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (subsystem
maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`,
`Tested-by:`
Notable: AMD maintainer review and merge; no fuzzer or user bug report.
### Step 1.3: Body Analysis
**Record:**
- **Bug:** `psp_copy_fw()` silently returns on `drm_dev_enter()`
failure; `memcpy()` into `fw_pri_buf` has no bounds check against the
1 MiB (`PSP_1_MEG`) buffer.
- **Symptom:** Callers proceed as if the copy succeeded — PSP commands
may run with stale/empty buffer data, or a heap buffer overflow occurs
if `bin_size > PSP_1_MEG`.
- **Root cause:** `psp_copy_fw` was `void` with no size validation;
several PSP version files duplicated `memset`/`memcpy` without checks.
- **Fix:** Return `-ENODEV` / `-EINVAL`; propagate errors to all
callers; route all copies through `psp_copy_fw`.
### Step 1.4: Hidden Bug Fix?
**Record:** Yes. Despite "validate and share" wording, this is a real
memory-safety and error-handling bug fix, not cosmetic cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- 8 files: `amdgpu_psp.c` (+32/-7 net), `amdgpu_psp.h` (+1/-1),
`psp_v3_1.c`, `psp_v11_0.c`, `psp_v12_0.c`, `psp_v13_0.c`,
`psp_v13_0_4.c`, `psp_v14_0.c`
- Total: +62 / -38 lines
- Functions: `psp_copy_fw`, `psp_load_toc`, `psp_rl_load`,
`psp_ta_load`, plus bootloader load helpers in PSP version files
- **Scope:** Multi-file but mechanical; single-subsystem surgical fix
### Step 2.2: Code Flow Changes
**Record:**
| Hunk | Before | After |
|------|--------|-------|
| `psp_copy_fw` | `void`; silent return on `drm_dev_enter` fail;
unchecked `memcpy` | `int`; returns `-ENODEV`/`-EINVAL`; validates `0 <
bin_size <= PSP_1_MEG` |
| `psp_load_toc`, `psp_rl_load`, `psp_ta_load` | Ignored `psp_copy_fw`
result | Check return; release cmd buf and abort on error |
| `psp_v11_0`–`psp_v14_0` bootloader paths | Open-coded
`memset`/`memcpy` or ignored `psp_copy_fw` return | Use `psp_copy_fw`
with error propagation |
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Memory safety (buffer overflow) + logic bug (ignored
error path)
- **Mechanism:** `fw_pri_buf` is allocated at exactly `PSP_1_MEG`
(verified at `amdgpu_psp.c:508`). `is_psp_fw_valid()` only checks
`size_bytes != 0` (`amdgpu_psp.c:4179-4181`). `memcpy(psp->fw_pri_buf,
start_addr, bin_size)` with `bin_size > PSP_1_MEG` overflows the 1 MiB
kernel buffer. On `drm_dev_enter` failure, callers previously
submitted PSP commands believing the copy succeeded.
### Step 2.4: Fix Quality
**Record:** Obviously correct. Mirrors existing TA validation
(`ta_bin_len > PSP_1_MEG` in `amdgpu_psp_ta.c:169`). Minimal regression
risk; error paths properly release acquired resources.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `psp_copy_fw` introduced in `f89f8c6bafd06` (May 2021,
"Guard against write accesses after device removal"). `drm_dev_enter`
guard added then; silent `return` on failure is the latent bug. Code
present in 6.18.44.
### Step 3.2: Fixes Tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related File History
**Record:** Related prior fix `c99769bceab4e` ("Validate TA binary
size", 2023) is already in 6.18.44 — validates userspace TA loads
against `PSP_1_MEG`. This commit extends the same constraint to kernel
firmware copy paths. Standalone; not part of a multi-patch series.
### Step 3.4: Author Context
**Record:** Candice Li is an active AMD amdgpu contributor. Alex Deucher
(maintainer) committed the merge.
### Step 3.5: Dependencies
**Record:** No prerequisites. All touched files and `psp_copy_fw` exist
in 6.18.44. Cherry-pick test: applies cleanly (exit 0).
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Patch Discussion
**Record:** `b4 dig -c d1f9f5839bd78` — no lore match found. Patch
likely merged via GitLab/Freedesktop rather than public lore thread.
### Step 4.2: Reviewers
**Record:** `b4 dig -w` not run (no lore match). Commit message confirms
`Reviewed-by: Tao Zhou` and `Signed-off-by: Alex Deucher`.
### Step 4.3: Bug Report
**Record:** N/A — no `Reported-by:` or `Link:` tags. No syzbot report.
### Step 4.4: Related Patches
**Record:** `c99769bceab4e` (TA size validation) is the directly related
prior fix, already in this tree.
### Step 4.5: Stable List History
**Record:** lore.kernel.org search blocked (Anubis bot protection). No
stable-list discussion found.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key Functions
**Record:** `psp_copy_fw`, `psp_load_toc`, `psp_rl_load`, `psp_ta_load`,
`psp_v*_bootloader_load_*`
### Step 5.2: Callers
**Record:** `psp_copy_fw` called from PSP init/bootloader paths
(`psp_v3_1`, `psp_v11_0`, `psp_v12_0`, `psp_v13_0`, `psp_v13_0_4`,
`psp_v14_0`) and from `psp_load_toc`, `psp_ta_load` during GPU
probe/initialization. All AMD GPU users with PSP enabled hit these paths
at driver load.
### Step 5.3: Callees
**Record:** `drm_dev_enter/exit`, `memset`, `memcpy`, `dev_err` —
operates on `psp->fw_pri_buf` (1 MiB BO-mapped buffer).
### Step 5.4: Reachability
**Record:** Triggered during GPU probe/init (every boot with amdgpu).
Not a direct syscall path, but universal for amdgpu hardware. Overflow
requires `size_bytes > PSP_1_MEG` from firmware header parsing;
`drm_dev_enter` failure occurs during device teardown concurrent with
PSP operations.
### Step 5.5: Similar Patterns
**Record:** Userspace TA path already validates `ta_bin_len > PSP_1_MEG`
(`amdgpu_psp_ta.c:169`). Kernel paths in `psp_v13_0.c`, `psp_v14_0.c`,
`psp_v13_0_4.c`, and `psp_rl_load` still use unchecked `memcpy` —
exactly what this fix addresses.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE
### Step 6.1: Buggy Code Present?
**Record:** Yes. In 6.18.44, `psp_copy_fw` is still `void` with
unchecked `memcpy` (`amdgpu_psp.c:4157-4168`). Open-coded unchecked
copies exist in `psp_v13_0.c:268-271`, `psp_v14_0.c:143-146`,
`psp_v13_0_4.c`, and `psp_rl_load` (`amdgpu_psp.c:1162-1163`). Bug
present since 2021.
### Step 6.2: Backport Complications
**Record:** Clean apply confirmed via test cherry-pick. No conflicts
expected.
### Step 6.3: Related Fixes Already Present?
**Record:** TA userspace validation (`c99769bceab4e`) is in tree. The
kernel-path validation this commit adds is not.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem
**Record:** `drivers/gpu/drm/amd/amdgpu` — GPU driver (IMPORTANT).
Affects all AMD GPU users with PSP firmware loading.
### Step 7.2: Activity
**Record:** Actively maintained; PSP v13/v14 support added in recent
6.18 development.
---
## PHASE 8: IMPACT AND RISK
### Step 8.1: Who Is Affected
**Record:** All amdgpu users during GPU initialization (driver-specific,
but broad within AMD GPU deployments).
### Step 8.2: Trigger Conditions
**Record:**
- **Overflow:** Corrupt/malformed firmware header with `size_bytes >
0x100000`, or internal bug setting oversized `size_bytes`.
Unprivileged users cannot directly trigger kernel firmware path;
requires bad firmware on disk.
- **drm_dev_enter failure:** Device removal/teardown racing with PSP
firmware load (uncommon but realistic).
### Step 8.3: Failure Mode Severity
**Record:**
- Buffer overflow → heap corruption, kernel oops/panic — **CRITICAL**
- Silent copy failure → PSP commands with stale data, init failure or
hardware hang — **HIGH**
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH — closes a real overflow window; consistent with
existing TA validation; proper error propagation
- **Risk:** LOW — small, mechanical, reviewed by AMD maintainer, applies
cleanly
- **Ratio:** Strongly favors backport
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence Summary
**FOR:**
- Fixes potential heap buffer overflow (memory safety)
- Fixes silent error on `drm_dev_enter` failure
- Extends validation already applied to userspace TA path
(`c99769bceab4e`, in tree)
- Small (+62/-38), obviously correct, AMD-reviewed
- Applies cleanly to 6.18.44
- All affected code exists in this tree
**AGAINST:**
- No user report, syzbot, or CVE
- Normal AMD firmware sizes are well under 1 MiB; overflow requires
corrupt firmware or parsing bug
- Primarily defense-in-depth on init path
**UNRESOLVED:**
- No public lore discussion found
- No production crash report documented
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — simple bounds check; AMD
internal review
2. Fixes a real bug? **PASS** — unchecked `memcpy` into fixed 1 MiB
buffer
3. Important issue? **PASS** — buffer overflow (CRITICAL class)
4. Small and contained? **PASS** — 8 files, ~100 lines, single subsystem
5. No new features/APIs? **PASS** — validation and error propagation
only
6. Can apply to local tree? **PASS** — clean cherry-pick confirmed
### Step 9.3: Exception Category
**Record:** None of the automatic exception categories apply; this is a
standard memory-safety bug fix.
### Step 9.4: Decision Rationale
This commit closes a genuine memory-safety hole: `fw_pri_buf` is exactly
1 MiB, but multiple kernel firmware copy paths perform unchecked
`memcpy` based on `size_bytes` from firmware headers, with
`is_psp_fw_valid()` only rejecting zero size. The driver already
validates the same 1 MiB limit for userspace-loaded TA binaries — this
brings kernel paths to the same standard. The `drm_dev_enter` error
propagation fix prevents PSP command submission after a failed copy
during device teardown.
While no crash has been reported, buffer overflow fixes are explicitly
stable-worthy, the change is small and low-risk, and it applies cleanly
to 6.18.44.
---
## Verification
- [Phase 1] Parsed commit `d1f9f5839bd78` message and tags from `git
show`
- [Phase 2] Analyzed full diff; confirmed `PSP_1_MEG = 0x100000` in
`amdgpu_psp.h:37`
- [Phase 2] Verified `fw_pri_buf` allocated at `PSP_1_MEG`
(`amdgpu_psp.c:508-513`)
- [Phase 2] Verified `is_psp_fw_valid()` only checks non-zero
(`amdgpu_psp.c:4179-4181`)
- [Phase 2] Found unchecked `memcpy` in `psp_v13_0.c:271`,
`psp_v14_0.c:146`, `psp_rl_load` (`amdgpu_psp.c:1162-1163`)
- [Phase 3] `git blame`: `psp_copy_fw` from `f89f8c6bafd06` (May 2021)
- [Phase 3] Related fix `c99769bceab4e` confirmed in tree via `git
merge-base --is-ancestor`
- [Phase 3] Cherry-pick test: `git cherry-pick --no-commit
d1f9f5839bd78` — clean apply (exit 0)
- [Phase 4] `b4 dig -c d1f9f5839bd78` — no lore match
- [Phase 4] lore.kernel.org fetch — blocked by Anubis
- [Phase 5] `grep psp_copy_fw`: 14 call sites across 7 files in tree
- [Phase 5] TA validation at `amdgpu_psp_ta.c:169` confirmed
- [Phase 6] `git describe HEAD` → `v6.18.44`
- [Phase 6] Buggy `void psp_copy_fw` confirmed present at
`amdgpu_psp.c:4157`
- [Phase 6] Commit not in tree: present on `origin/master`, absent from
`stable/linux-6.18.y`
- [Phase 8] Failure modes assessed from code flow analysis
**YES**The background `git log` search for `psp_copy_fw` and "validate
and share PSP fw_pri_buf" finished with no matches in this tree —
expected, since `d1f9f5839bd78` is on mainline but not in `v6.18.44`
yet.
That lines up with the earlier analysis: the unchecked `memcpy` paths
are still present here, and the fix applies cleanly. Verdict remains
**YES** for backport.
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 32 ++++++++++++++++++------
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 2 +-
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 8 ++++--
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 8 ++++--
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 14 +++++------
drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c | 14 +++++------
drivers/gpu/drm/amd/amdgpu/psp_v14_0.c | 14 +++++------
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 8 ++++--
8 files changed, 62 insertions(+), 38 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 5f7aa840b2151..9f3581ce492f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -832,7 +832,11 @@ static int psp_load_toc(struct psp_context *psp,
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
/* Copy toc to psp firmware private buffer */
- psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes);
+ ret = psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes);
+ if (ret) {
+ release_psp_cmd_buf(psp);
+ return ret;
+ }
psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc.size_bytes);
@@ -1159,8 +1163,11 @@ static int psp_rl_load(struct amdgpu_device *adev)
cmd = acquire_psp_cmd_buf(psp);
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
- memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes);
+ ret = psp_copy_fw(psp, psp->rl.start_addr, psp->rl.size_bytes);
+ if (ret) {
+ release_psp_cmd_buf(psp);
+ return ret;
+ }
cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr);
@@ -1383,8 +1390,12 @@ int psp_ta_load(struct psp_context *psp, struct ta_context *context)
cmd = acquire_psp_cmd_buf(psp);
- psp_copy_fw(psp, context->bin_desc.start_addr,
- context->bin_desc.size_bytes);
+ ret = psp_copy_fw(psp, context->bin_desc.start_addr,
+ context->bin_desc.size_bytes);
+ if (ret) {
+ release_psp_cmd_buf(psp);
+ return ret;
+ }
if (amdgpu_virt_xgmi_migrate_enabled(psp->adev) &&
context->mem_context.shared_bo)
@@ -4154,17 +4165,24 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
return count;
}
-void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size)
+int psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size)
{
int idx;
if (!drm_dev_enter(adev_to_drm(psp->adev), &idx))
- return;
+ return -ENODEV;
+
+ if (!bin_size || bin_size > PSP_1_MEG) {
+ dev_err(psp->adev->dev, "PSP firmware is invalid\n");
+ drm_dev_exit(idx);
+ return -EINVAL;
+ }
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
memcpy(psp->fw_pri_buf, start_addr, bin_size);
drm_dev_exit(idx);
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 237b624aa51ca..c3a5940e311aa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -605,7 +605,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
int psp_update_fw_reservation(struct psp_context *psp);
int psp_load_fw_list(struct psp_context *psp,
struct amdgpu_firmware_info **ucode_list, int ucode_count);
-void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
+int psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
int psp_spatial_partition(struct psp_context *psp, int mode);
int psp_memory_partition(struct psp_context *psp, int mode);
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index 27d883fda5fa9..6f131f4b81134 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -217,7 +217,9 @@ static int psp_v11_0_bootloader_load_component(struct psp_context *psp,
return ret;
/* Copy PSP System Driver binary to memory */
- psp_copy_fw(psp, bin_desc->start_addr, bin_desc->size_bytes);
+ ret = psp_copy_fw(psp, bin_desc->start_addr, bin_desc->size_bytes);
+ if (ret)
+ return ret;
/* Provide the sys driver to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -263,7 +265,9 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
return ret;
/* Copy Secure OS binary to PSP memory */
- psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ ret = psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
index 4c6450d62299a..80ba57cce3916 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
@@ -87,7 +87,9 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)
return ret;
/* Copy PSP System Driver binary to memory */
- psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
+ ret = psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
+ if (ret)
+ return ret;
/* Provide the sys driver to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -123,7 +125,9 @@ static int psp_v12_0_bootloader_load_sos(struct psp_context *psp)
return ret;
/* Copy Secure OS binary to PSP memory */
- psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ ret = psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index af4a7d7c4abd8..8100930e47eb1 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -265,10 +265,9 @@ static int psp_v13_0_bootloader_load_component(struct psp_context *psp,
if (ret)
return ret;
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
- /* Copy PSP KDB binary to memory */
- memcpy(psp->fw_pri_buf, bin_desc->start_addr, bin_desc->size_bytes);
+ ret = psp_copy_fw(psp, bin_desc->start_addr, bin_desc->size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP KDB to bootloader */
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
@@ -347,10 +346,9 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
if (ret)
return ret;
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
- /* Copy Secure OS binary to PSP memory */
- memcpy(psp->fw_pri_buf, psp->sos.start_addr, psp->sos.size_bytes);
+ ret = psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
index 5f39a2edcc956..3d5e26b3fa00a 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
@@ -105,10 +105,9 @@ static int psp_v13_0_4_bootloader_load_component(struct psp_context *psp,
if (ret)
return ret;
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
- /* Copy PSP KDB binary to memory */
- memcpy(psp->fw_pri_buf, bin_desc->start_addr, bin_desc->size_bytes);
+ ret = psp_copy_fw(psp, bin_desc->start_addr, bin_desc->size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP KDB to bootloader */
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
@@ -168,10 +167,9 @@ static int psp_v13_0_4_bootloader_load_sos(struct psp_context *psp)
if (ret)
return ret;
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
- /* Copy Secure OS binary to PSP memory */
- memcpy(psp->fw_pri_buf, psp->sos.start_addr, psp->sos.size_bytes);
+ ret = psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c
index 38dfc5c19f2a7..040a61aefa866 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c
@@ -140,10 +140,9 @@ static int psp_v14_0_bootloader_load_component(struct psp_context *psp,
if (ret)
return ret;
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
- /* Copy PSP KDB binary to memory */
- memcpy(psp->fw_pri_buf, bin_desc->start_addr, bin_desc->size_bytes);
+ ret = psp_copy_fw(psp, bin_desc->start_addr, bin_desc->size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP KDB to bootloader */
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_36,
@@ -214,10 +213,9 @@ static int psp_v14_0_bootloader_load_sos(struct psp_context *psp)
if (ret)
return ret;
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
- /* Copy Secure OS binary to PSP memory */
- memcpy(psp->fw_pri_buf, psp->sos.start_addr, psp->sos.size_bytes);
+ ret = psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_36,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
index 833830bc3e2e3..409f097f4c524 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
@@ -96,7 +96,9 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
return ret;
/* Copy PSP System Driver binary to memory */
- psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
+ ret = psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
+ if (ret)
+ return ret;
/* Provide the sys driver to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -135,7 +137,9 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
return ret;
/* Copy Secure OS binary to PSP memory */
- psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ ret = psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
+ if (ret)
+ return ret;
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Check for sharpening case when calculating max vtaps for scaler
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: validate and share PSP fw_pri_buf copies via psp_copy_fw Sasha Levin
@ 2026-08-31 13:21 ` Sasha Levin
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18] drm/amdgpu: validate RAS EEPROM tbl_size before record count Sasha Levin
` (35 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:21 UTC (permalink / raw)
To: patches, stable
Cc: Samson Tam, Charlene Liu, Ray Wu, Daniel Wheeler, Alex Deucher,
Sasha Levin, harry.wentland, sunpeng.li, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Samson Tam <Samson.Tam@amd.com>
[ Upstream commit 4d8cfd570386eb0b6cb8aa0ca9e9db60a0404337 ]
[Why & How]
- calc_lb_num_partitions has check when scaler is not enabled to use
larger LB in calculations for max vtaps based on viewport being 1:1
- however, scaler is forced on when sharpening is enabled, so need
to consider this in check
- taps is predetermined in spl_get_optimal_number_of_taps prior to
calc_lb_num_partitions. Add check for taps not 1 to handle
sharpening case
Reviewed-by: Charlene Liu <charlene.liu@amd.com>
Signed-off-by: Samson Tam <Samson.Tam@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Tested-by: Daniel 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:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
Record: `[drm/amd/display]` `[Check]` — verify sharpening when computing
max vertical taps for the DCN401 scaler line-buffer partition
calculation.
**Step 1.2 — Tags**
Record:
- `Reviewed-by: Charlene Liu <charlene.liu@amd.com>`
- `Signed-off-by: Samson Tam <Samson.Tam@amd.com>`
- `Signed-off-by: Ray Wu <ray.wu@amd.com>`
- `Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>`
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>`
- No `Fixes:`, `Reported-by:`, `Link:`, or `Cc: stable@vger.kernel.org`
(expected for manual review)
- Notable: AMD internal review + `Tested-by` from AMD QA; no syzbot or
public bug report
**Step 1.3 — Body analysis**
Record:
- **Bug:** `dscl401_spl_calc_lb_num_partitions()` treats a 1:1 viewport
as “scaler disabled” and uses an inflated line-buffer (LB) size for
max-vtap math, but sharpening forces the scaler on at 1:1.
- **Symptom:** Overestimated max vertical taps → scaler programmed
beyond real LB capacity → display corruption/underflow risk on DCN401
with sharpening at native resolution.
- **Root cause:** `spl_get_optimal_number_of_taps()` sets `taps > 1`
before calling `spl_calc_lb_num_partitions()`, but the LB-size branch
only checked viewport 1:1, not taps.
- **Version info:** None in the message.
**Step 1.4 — Hidden bug fix?**
Record: Yes. Despite no “fix” in the subject, this is a hardware-
programming correctness bug in the display scaler path, not a cleanup.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
Record:
- 1 file: `drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c` (+6 /
−2)
- Function: `dscl401_spl_calc_lb_num_partitions()`
- Scope: single-file, surgical (two conditionals in two `lb_config`
branches)
**Step 2.2 — Code flow change**
Record:
- **Before:** `viewport.width == h_active && viewport.height ==
v_active` → use enlarged LB constants (e.g. `970+1290+1170` vs
`970+1290+484`).
- **After:** Same enlarged LB only when viewport is 1:1 **and** `h_taps
== 1 && v_taps == 1` (scaler truly off).
- **Path:** `spl_get_optimal_number_of_taps()` →
`spl_calc_lb_num_partitions()` →
`dscl401_spl_calc_lb_num_partitions()` during mode/plane setup on
DCN401.
**Step 2.3 — Bug mechanism**
Record: **Logic / hardware correctness fix.**
When sharpening is enabled at 1:1, taps are already 6 (EASF path) before
LB calculation, but the old code still assumed scaler-off and inflated
LB size by ~25% (RGB) or ~55% (YUV420), inflating `num_part_y` and
`max_taps_y`.
**Step 2.4 — Fix quality**
Record: Obviously correct and minimal. Uses taps already set before the
LB call as the scaler-enabled indicator. Low regression risk; only
narrows the enlarged-LB fast path.
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
Record: Buggy viewport-only check introduced in `70839da636050` (“Add
new DCN401 sources”, 2024-04-26). Present in v6.18.44.
**Step 3.2 — Fixes: tag**
Record: N/A — no `Fixes:` tag.
**Step 3.3 — Related file history**
Record: DCN401 added in `70839da636050`; ISHARP for DCN401 in
`2998bccfa4197` (2024-05-29). Related DCN401 corruption fix:
`5d74be8c3a941` (YUV color corruption). Standalone one-commit fix.
**Step 3.4 — Author context**
Record: Samson Tam is an active AMD display contributor; same author as
`5d74be8c3a941`.
**Step 3.5 — Dependencies**
Record: None. Only needs `scl_data->taps` fields already used in this
tree. `git apply --check` on mainline commit `4d8cfd570386e` succeeds
cleanly.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
Record: `b4 dig -c 4d8cfd570386e` found no lore.kernel.org match (likely
direct AMD/DRM tree path). lore.kernel.org search blocked by Anubis.
**Step 4.2 — Reviewers**
Record: `b4 dig -w` also found nothing. Commit has `Reviewed-by`
(Charlene Liu), `Tested-by` (Daniel Wheeler), and Alex Deucher as
committer.
**Step 4.3 — Bug report**
Record: N/A — no `Reported-by:` or `Link:` tags.
**Step 4.4 — Series context**
Record: Standalone; not part of a multi-patch series.
**Step 4.5 — Stable list history**
Record: Not searched successfully on lore (bot protection). No evidence
of prior stable rejection.
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
Record: `dscl401_spl_calc_lb_num_partitions()`, called via SPL callbacks
from `spl_get_optimal_number_of_taps()`.
**Step 5.2 — Callers**
Record:
- `spl_get_optimal_number_of_taps()` (dc_spl.c:1033)
- `spl_calculate_number_of_taps()` → `spl_calculate_scaler_params()` —
display mode/plane configuration on DCN401
**Step 5.3 — Callees**
Record: Arithmetic on LB memory constants; sets `num_part_y` /
`num_part_c` used to derive `max_taps_y` / `max_taps_c`.
**Step 5.4 — Reachability**
Record: Reachable on normal display use when DCN401 + adaptive
sharpening (ISHARP) at 1:1 scaling. Userspace can enable sharpening via
amdgpu display stack; not an obscure debug-only path.
**Step 5.5 — Similar patterns**
Record: `dscl32_spl_calc_lb_num_partitions()` has the same viewport-only
check without taps check, but this commit targets DCN401 only.
`dscl401_calc_lb_num_partitions()` (non-SPL) unchanged; SPL path is the
sharpening path (`use_spl`).
---
## Phase 6: Cross-Reference Against Local Tree (v6.18.44)
**Step 6.1 — Buggy code present?**
Record: **Yes.**
`drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c` lines 391–406
lack the taps check. Fix commit `4d8cfd570386e` is **not** in this tree
(`git merge-base --is-ancestor` fails).
**Step 6.2 — Backport complications**
Record: Clean apply verified (`git show 4d8cfd570386e | git apply
--check`). No conflicts expected.
**Step 6.3 — Related fixes already present?**
Record: No equivalent taps check. DCN401 and ISHARP support are both
present.
---
## Phase 7: Subsystem and Maintainer Context
**Step 7.1 — Subsystem**
Record: `drivers/gpu/drm/amd/display` — AMDGPU display (DCN401 DPP
scaler). Criticality: **IMPORTANT** (display output for DCN401 hardware
users).
**Step 7.2 — Activity**
Record: Actively maintained; multiple DCN401 fixes in this tree (NULL
deref, color corruption, signal checks).
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
Record: Users of DCN401-based AMD GPUs (discrete/APU) on 6.18.y with
adaptive sharpening at native (1:1) resolution. Driver-specific, not
universal.
**Step 8.2 — Trigger conditions**
Record: DCN401 + sharpening enabled + 1:1 viewport. Common for desktop
use at native panel resolution with sharpening on. Unprivileged users
can trigger via normal display configuration.
**Step 8.3 — Failure mode severity**
Record: Incorrect max-vtap calculation → scaler programmed beyond LB
capacity → **display corruption / underflow** (MEDIUM–HIGH for affected
hardware; not a kernel oops, but user-visible and similar to accepted
DCN401 corruption fixes).
**Step 8.4 — Risk/benefit**
Record:
- **Benefit:** MEDIUM–HIGH for DCN401 + sharpening users
- **Risk:** VERY LOW (8-line logic fix, tested, reviewed)
- **Ratio:** Favorable for backport
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence**
*For backport:*
- Real bug in v6.18.44 DCN401 SPL scaler LB calculation
- Causes overestimated max vtaps when sharpening forces scaler at 1:1
- Small, reviewed, tested, applies cleanly
- Precedent: `5d74be8c3a941` (DCN401 display corruption) is already in
this tree
- DCN401 + ISHARP both present since 2024
*Against backport:*
- No public bug report or syzbot finding
- Narrow hardware/feature scope (DCN401 + sharpening at 1:1)
- Display corruption, not documented kernel crash
- No lore discussion found
*Unresolved:*
- No public user reports found
- Exact visual failure modes not documented in the commit message
**Step 9.2 — Stable rules checklist**
1. Obviously correct and tested? **PASS** — logic matches commit
explanation; `Tested-by` + `Reviewed-by`
2. Fixes a real user-affecting bug? **PASS** — incorrect HW scaler
config on reachable path
3. Important issue? **PASS** — display corruption on affected hardware
(same class as prior DCN401 stable fix)
4. Small and contained? **PASS** — 8 lines, one function, one file
5. No new features/APIs? **PASS** — correctness fix only
6. Can apply to local tree? **PASS** — verified clean apply
**Step 9.3 — Exception category**
Record: Hardware workaround / driver correctness fix for existing DCN401
hardware support (not a new device ID).
**Step 9.4 — Decision rationale**
For **linux-6.18.y (v6.18.44)**: the buggy code exists, prerequisites
(DCN401, ISHARP, SPL) are present, the fix is minimal and low-risk, and
it prevents display corruption on a real use case (sharpening at native
resolution). This matches the class of AMDGPU display corruption fixes
already carried in this stable tree.
---
## Verification
- [Phase 1] Parsed commit `4d8cfd570386e` message and tags from `git
show`
- [Phase 2] Read diff and current `dcn401_dpp.c` lines 357–428;
confirmed missing taps check
- [Phase 2] Traced `spl_get_optimal_number_of_taps()` at
dc_spl.c:1006–1034 — taps set before LB calc
- [Phase 2] Read sharpening logic at dc_spl.c:1121–1140 and
dml21_translation_helper.c:558–563
- [Phase 3] `git blame` lines 390–416 → `70839da636050` (2024-04-26)
- [Phase 3] `git log -S "use increased LB size..."` → introduced with
DCN401
- [Phase 3] `2998bccfa4197` ISHARP support confirmed ancestor of HEAD
- [Phase 3] `git show 4d8cfd570386e | git apply --check` → clean apply
- [Phase 4] `b4 dig -c 4d8cfd570386e` → no lore match
- [Phase 4] `b4 dig -c 4d8cfd570386e -w` and `-a` → no results
- [Phase 4] lore.kernel.org WebFetch → blocked by Anubis
- [Phase 5] Grep callers: `spl_get_optimal_number_of_taps` →
`spl_calculate_number_of_taps` → display setup
- [Phase 6] `git describe HEAD` → v6.18.44
- [Phase 6] `git merge-base --is-ancestor 4d8cfd570386e HEAD` → fix NOT
in tree
- [Phase 6] Buggy viewport-only conditions confirmed at lines 391–392
and 405–406
- [Phase 7] `git log --grep=dcn401` shows active DCN401 maintenance
including `5d74be8c3a941`
- [Phase 8] Quantified LB overestimate: 3430 vs 2744 (RGB), 5770 vs 3712
(YUV420)
**YES**
drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c
index b62bbadb0d440..029f59a58c780 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c
@@ -389,9 +389,11 @@ void dscl401_spl_calc_lb_num_partitions(
lb_memory_size_a = 1290;
} else if (lb_config == LB_MEMORY_CONFIG_3) {
if (scl_data->viewport.width == scl_data->h_active &&
- scl_data->viewport.height == scl_data->v_active) {
+ scl_data->viewport.height == scl_data->v_active &&
+ scl_data->taps.h_taps == 1 && scl_data->taps.v_taps == 1) {
/* 420 mode: luma using all 3 mem from Y, plus 3rd mem from Cr and Cb */
/* use increased LB size for calculation only if Scaler not enabled */
+ /* Scaler is forced on when sharpening is on. Add check for taps = 1 */
lb_memory_size = 970 + 1290 + 1170 + 1170 + 1170;
lb_memory_size_c = 970 + 1290;
lb_memory_size_a = 970 + 1290 + 1170;
@@ -403,8 +405,10 @@ void dscl401_spl_calc_lb_num_partitions(
}
} else {
if (scl_data->viewport.width == scl_data->h_active &&
- scl_data->viewport.height == scl_data->v_active) {
+ scl_data->viewport.height == scl_data->v_active &&
+ scl_data->taps.h_taps == 1 && scl_data->taps.v_taps == 1) {
/* use increased LB size for calculation only if Scaler not enabled */
+ /* Scaler is forced on when sharpening is on. Add check for taps = 1 */
lb_memory_size = 970 + 1290 + 1170;
lb_memory_size_c = 970 + 1290 + 1170;
lb_memory_size_a = 970 + 1290 + 1170;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: validate RAS EEPROM tbl_size before record count
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: validate and share PSP fw_pri_buf copies via psp_copy_fw Sasha Levin
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Check for sharpening case when calculating max vtaps for scaler Sasha Levin
@ 2026-08-31 13:21 ` Sasha Levin
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18] drm/amd/ras: Fix CPER ring debugfs read overflow Sasha Levin
` (34 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:21 UTC (permalink / raw)
To: patches, stable
Cc: Candice Li, Hawking Zhang, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Candice Li <candice.li@amd.com>
[ Upstream commit c83e4a45ff9a0b7aa1c48246102009a99ccef11b ]
Corrupt EEPROM data can set tbl_size below the table header size.
Guard the RAS_NUM_RECS macros against undersized tbl_size and reset
the table during init when tbl_size is below the minimum for the table
version instead of trusting the header.
Signed-off-by: Candice Li <candice.li@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:
## Phase 1: Commit Message Forensics
### Step 1.1: Subject Line
**Record:** `[drm/amdgpu]` `[validate]` — Validate RAS EEPROM `tbl_size`
before computing record count from the EEPROM table header.
### Step 1.2: Commit Message Tags
**Record:**
- **Signed-off-by:** Candice Li `<candice.li@amd.com>` (author)
- **Reviewed-by:** Hawking Zhang `<Hawking.Zhang@amd.com>`
- **Signed-off-by:** Alex Deucher `<alexander.deucher@amd.com>`
(drm/amdgpu maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`,
`Tested-by:`, or syzbot tags
- Notable absence: no fuzzer or user bug report; maintainer-reviewed
driver fix only
### Step 1.3: Commit Body Analysis
**Record:**
- **Bug:** Corrupt EEPROM can set `tbl_size` below the minimum size for
the table version (20 bytes for V1, 276 bytes for V2.1/V3).
- **Symptom:** `RAS_NUM_RECS` / `RAS_NUM_RECS_V2_1` perform unsigned
subtraction on undersized `tbl_size`, producing incorrect record
counts; driver should not trust the header.
- **Fix approach:** Guard macros to return 0 on undersized `tbl_size`;
during `amdgpu_ras_eeprom_init()`, detect undersized `tbl_size` and
reset the table via `amdgpu_ras_eeprom_reset_table()` instead of
proceeding.
- **Root cause:** Missing minimum-size validation before using
`tbl_size` in record-count arithmetic.
### Step 1.4: Hidden Bug Fix Detection
**Record:** Yes — described as validation, but it is a real correctness
bug fix. Undersized `tbl_size` causes unsigned underflow in
`RAS_NUM_RECS*` macros. The init-path change converts a permanent init
failure (`-EINVAL`, EEPROM marked invalid) into self-healing table
reset, matching the existing invalid-header recovery pattern.
---
## Phase 2: Diff Analysis
### Step 2.1: Change Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c` only
- **Scope:** ~20 lines changed (macro guards + two init checks)
- **Functions/macros modified:** `RAS_NUM_RECS`, `RAS_NUM_RECS_V2_1`,
`amdgpu_ras_eeprom_init()`
- **Classification:** Single-file surgical fix
### Step 2.2: Code Flow Change
**Record:**
- **Macro hunks:** Before — unconditional `(tbl_size - header_size) /
record_size` (unsigned underflow when `tbl_size` too small). After —
return `0u` if below minimum, else compute normally.
- **V2.1/V3 init hunk:** Before — compute `ras_num_recs` immediately.
After — if `tbl_size < 276`, log error and reset table.
- **V1 init hunk:** Before — compute immediately. After — if `tbl_size <
20`, log error and reset table.
- **Path affected:** Driver init on GPUs with RAS EEPROM support (probe-
time `amdgpu_ras_eeprom_init()`).
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Memory safety / logic correctness (unsigned arithmetic
on corrupt data)
- **Mechanism:** `tbl_size` is `uint32_t`. When `tbl_size <
RAS_TABLE_HEADER_SIZE` (V1) or `< RAS_TABLE_HEADER_SIZE +
RAS_TABLE_V2_1_INFO_SIZE` (V2.1/V3), subtraction wraps to a very large
value. Commit 5df0d6addb7e9’s `ras_num_recs > ras_max_record_count`
check catches this and returns `-EINVAL`, but EEPROM stays permanently
disabled. This commit adds explicit minimum-size validation and auto-
recovery.
### Step 2.4: Fix Quality
**Record:** Obviously correct and minimal. Mirrors `6ffc6e056febb`
(“Reset RAS table if header is invalid”). Low regression risk: only
triggers on already-corrupt EEPROM headers; reset path is well-tested.
No API changes.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame
**Record:**
- `RAS_NUM_RECS` introduced in `63d4c081a556a` (2021-04-06, “Optimize
EEPROM RAS table I/O”)
- `RAS_NUM_RECS_V2_1` introduced in `65183faec89f3e` (2023-05-30, “Add
RAS table v2.1 macro definition”)
- Buggy unsigned arithmetic present since those commits; this tree is
**v6.18.44**
### Step 3.2: Fixes: Tag
**Record:** N/A — no `Fixes:` tag in commit message.
### Step 3.3: Related File History
**Record:** Related validation commits already in this tree:
- `5df0d6addb7e9` — “Add basic validation for RAS header” (max record
count check)
- `6ffc6e056febb` — “Reset RAS table if header is invalid”
- `660261df61fb7` — “refine eeprom data check” (checksum on unload)
- `89232d0db3ca9` — “return when ras table checksum is error”
Standalone fix; not part of a numbered series.
### Step 3.4: Author Context
**Record:** Candice Li is an AMD contributor. Related validation work by
Lijo Lazar and ganglxie in the same file. Alex Deucher (maintainer)
signed off.
### Step 3.5: Dependencies
**Record:** Requires `RAS_NUM_RECS_V2_1`,
`amdgpu_ras_eeprom_reset_table()`, and the version switch in init — all
present in v6.18.44. User diff shows HBM3E context from newer mainline;
that block is **not** in this tree and is **not** part of the patch
hunks. Applies standalone to 6.18.44 init switch.
---
## Phase 4: Mailing List and External Research
### Step 4.1: Original Discussion
**Record:** Commit hash not in this checkout; `b4 dig -c` could not
match. Lore search blocked by Anubis bot protection. **UNVERIFIED:**
full mailing-list review thread.
### Step 4.2: Reviewers
**Record:** **UNVERIFIED** via b4. Commit message shows Reviewed-by
Hawking Zhang (AMD) and Signed-off-by Alex Deucher (maintainer).
### Step 4.3: Bug Reports
**Record:** N/A — no `Reported-by:` or `Link:` tags.
### Step 4.4: Related Patches
**Record:** Part of ongoing amdgpu RAS EEPROM validation hardening;
prior related commits are already in v6.18.44.
### Step 4.5: Stable List History
**Record:** **UNVERIFIED** — could not search lore stable archive.
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `RAS_NUM_RECS`, `RAS_NUM_RECS_V2_1`,
`amdgpu_ras_eeprom_init()`
### Step 5.2: Callers
**Record:** `amdgpu_ras_eeprom_init()` called from
`amdgpu_ras_init_badpage_info()` in `amdgpu_ras.c:3590`, which runs
during GPU RAS initialization at probe. Affects VEGA20, Arcturus, Sienna
Cichlid, Aldebaran, and other RAS-EEPROM-capable dGPUs per
`__is_ras_eeprom_supported()`.
### Step 5.3: Callees
**Record:** On undersized `tbl_size`, calls
`amdgpu_ras_eeprom_reset_table()` which rewrites a valid header to
EEPROM via I2C.
### Step 5.4: Reachability
**Record:** Triggered at every boot on affected hardware when EEPROM
`tbl_size` is corrupt. Not userspace-triggerable directly, but affects
all boots on affected systems. Corrupt EEPROM is a realistic
hardware/partial-write scenario on datacenter GPUs.
### Step 5.5: Similar Patterns
**Record:** Same recovery pattern as `6ffc6e056febb` for invalid header
magic. Complements `5df0d6addb7e9` max-record validation.
---
## Phase 6: Cross-Reference Against Local Tree (v6.18.44)
### Step 6.1: Buggy Code Present?
**Record:** **Yes.** Current tree at lines 145–150 has unguarded
`RAS_NUM_RECS` macros; `amdgpu_ras_eeprom_init()` at lines 1415–1432
lacks `tbl_size` minimum checks. Bug present since 2021/2023; partial
mitigation since `5df0d6addb7e9` (Mar 2025).
### Step 6.2: Backport Complications
**Record:** Expected **clean apply** — init switch structure matches; no
HBM3E block in 6.18.44 that would conflict. Only line-number offset
differs; context-based apply should work.
### Step 6.3: Related Fixes Already Present?
**Record:** Max record count validation (`5df0d6addb7e9`) and invalid-
header reset (`6ffc6e056febb`) are present. **This specific `tbl_size`
minimum validation is NOT present.**
---
## Phase 7: Subsystem Context
### Step 7.1: Subsystem and Criticality
**Record:** `drivers/gpu/drm/amd/amdgpu` — **IMPORTANT** (AMD
datacenter/enterprise GPU RAS reliability; not universal but critical
for affected hardware).
### Step 7.2: Subsystem Activity
**Record:** Actively maintained — 4 EEPROM-related commits in recent
file history on this tree.
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** Users of AMD GPUs with RAS EEPROM support (VEGA20, Arcturus,
MI-series, RDNA/CDNA dGPUs with HBM RAS). Config: `CONFIG_DRM_AMDGPU`
with supported ASICs.
### Step 8.2: Trigger Conditions
**Record:** Corrupt EEPROM `tbl_size` field on boot. Uncommon but
realistic (wear, partial write, hardware glitch). Not unprivileged-
triggerable; hardware/firmware corruption path.
### Step 8.3: Failure Mode Severity
**Record:**
- **Without fix:** Undersized `tbl_size` → unsigned underflow →
`ras_num_recs > ras_max_record_count` → `-EINVAL` → `is_eeprom_valid =
false` every boot. GPU runs but RAS EEPROM bad-page tracking is
permanently disabled until manual intervention. Verified: all
`tbl_size < 20` (V1) and `tbl_size < 276` (V2.1) underflow cases
produce record counts above max (Python verification).
- **With fix:** Table auto-reset; RAS EEPROM functionality restored.
- **Severity:** **MEDIUM-HIGH** for affected datacenter hardware
(operational RAS degradation, not kernel crash). No OOM path because
`amdgpu_ras_load_bad_pages()` is gated on `is_eeprom_valid` (line
3600).
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** Self-healing corrupt EEPROM; defense-in-depth on macros;
consistent with existing reset-on-corruption policy.
- **Risk:** Very low — ~20 lines, only error/corruption path, uses
existing reset function.
- **Ratio:** Moderate benefit, very low risk. Worth backporting given
prior similar fixes already in 6.18.y.
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Summary
**FOR backport:**
- Fixes real corrupt-EEPROM bug (unsigned underflow + incorrect trust of
header)
- Auto-recovery instead of permanent EEPROM disable on every boot
- Small, surgical, maintainer-reviewed
- Prerequisites present in v6.18.44
- Consistent with already-backported validation series (`5df0d6`,
`6ffc6e`, `660261`, `89232d`)
- Affects production RAS-capable AMD GPUs
**AGAINST backport:**
- Existing max-record check already prevents huge `kcalloc` / OOM (since
Mar 2025)
- No crash, deadlock, or security exploit demonstrated
- No user/syzbot report
- Primary improvement is operational recovery, not crash prevention
- Lore review unverified
**UNRESOLVED:** Mailing-list discussion and stable-list nomination
history.
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — logic is straightforward;
reviewed by AMD engineer and maintainer (no runtime test tag).
2. Fixes real bug affecting users? **PASS** — corrupt EEPROM leaves RAS
tracking disabled on every boot on affected hardware.
3. Important issue? **PASS (MEDIUM-HIGH)** — datacenter RAS reliability
degradation on supported GPUs; not a kernel crash but materially
impacts production GPU health tracking.
4. Small and contained? **PASS** — one file, ~20 lines.
5. No new features/APIs? **PASS** — validation and recovery only.
6. Can apply to local tree? **PASS** — code exists; patch should apply
cleanly to v6.18.44.
### Step 9.3: Exception Categories
**Record:** Hardware workaround for corrupt EEPROM data on existing RAS-
EEPROM driver — analogous to quirk/validation exception category.
### Step 9.4: Decision Rationale
This commit completes the RAS EEPROM validation work already present in
v6.18.44. While the max-record check added in `5df0d6addb7e9` prevents
the worst outcome (huge allocation), corrupt undersized `tbl_size` still
causes permanent EEPROM init failure on every boot. The fix follows the
established pattern of resetting corrupt tables rather than leaving the
driver in a degraded state. It is small, obviously correct, low-risk,
and relevant to this tree’s existing amdgpu RAS EEPROM code.
---
## Verification
- **[Phase 1]** Parsed commit message: subject, tags (SOB, Reviewed-by,
no Fixes/Reported-by/Link)
- **[Phase 2]** Diff analysis: 1 file, macro guards + 2 init checks in
`amdgpu_ras_eeprom_init()`
- **[Phase 3]** `git describe HEAD`: v6.18.44
- **[Phase 3]** `git blame` lines 145–150: macros from 63d4c081a556a
(2021), 65183faec89f3e (2023)
- **[Phase 3]** `git log -15 -- amdgpu_ras_eeprom.c`: related validation
commits present
- **[Phase 3]** `git show 5df0d6addb7e9`: added max record count
validation
- **[Phase 3]** `git show 6ffc6e056febb`: reset on invalid header magic
- **[Phase 3]** `git merge-base --is-ancestor`: 5df0d6 and 65183fa both
in tree
- **[Phase 4]** `b4 dig`: no commit hash available in tree — no match
- **[Phase 4]** lore.kernel.org fetch: blocked by Anubis —
**UNVERIFIED**
- **[Phase 5]** `grep amdgpu_ras_eeprom_init`: caller at
`amdgpu_ras.c:3590`
- **[Phase 5]** `grep RAS_NUM_RECS`: only used in
`amdgpu_ras_eeprom_init()`
- **[Phase 5]** `grep is_eeprom_valid`: gates
`amdgpu_ras_load_bad_pages` at line 3600
- **[Phase 6]** Read current `amdgpu_ras_eeprom.c` lines 145–150,
1415–1444: buggy code confirmed present
- **[Phase 6]** Python verification: all `tbl_size < 20` (V1) and
`tbl_size < 276` (V2.1) underflow cases produce record counts > max —
existing check returns `-EINVAL`
- **[Phase 8]** Read `amdgpu_ras_init_badpage_info()`: `is_eeprom_valid
= !ret`; load gated on validity
- **[Phase 8]** `tbl_size` type confirmed `uint32_t` in
`amdgpu_ras_eeprom.h:51`
**YES**
.../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 26 +++++++++++++++----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 652aa085b6263..51382d604b1f0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -142,12 +142,15 @@
#define RAS_RI_TO_AI(_C, _I) (((_I) + (_C)->ras_fri) % \
(_C)->ras_max_record_count)
-#define RAS_NUM_RECS(_tbl_hdr) (((_tbl_hdr)->tbl_size - \
- RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE)
+#define RAS_NUM_RECS(_tbl_hdr) \
+ (((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE) ? 0u : \
+ (((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE))
-#define RAS_NUM_RECS_V2_1(_tbl_hdr) (((_tbl_hdr)->tbl_size - \
- RAS_TABLE_HEADER_SIZE - \
- RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE)
+#define RAS_NUM_RECS_V2_1(_tbl_hdr) \
+ (((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE + \
+ RAS_TABLE_V2_1_INFO_SIZE) ? 0u : \
+ (((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE - \
+ RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE))
#define to_amdgpu_device(x) ((container_of(x, struct amdgpu_ras, eeprom_control))->adev)
@@ -1415,11 +1418,24 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
switch (hdr->version) {
case RAS_TABLE_VER_V2_1:
case RAS_TABLE_VER_V3:
+ if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE) {
+ dev_err(adev->dev,
+ "RAS header invalid, tbl_size %u smaller than minimum %u, resetting table\n",
+ hdr->tbl_size,
+ RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE);
+ return amdgpu_ras_eeprom_reset_table(control);
+ }
control->ras_num_recs = RAS_NUM_RECS_V2_1(hdr);
control->ras_record_offset = RAS_RECORD_START_V2_1;
control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
break;
case RAS_TABLE_VER_V1:
+ if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE) {
+ dev_err(adev->dev,
+ "RAS header invalid, tbl_size %u smaller than minimum %u, resetting table\n",
+ hdr->tbl_size, RAS_TABLE_HEADER_SIZE);
+ return amdgpu_ras_eeprom_reset_table(control);
+ }
control->ras_num_recs = RAS_NUM_RECS(hdr);
control->ras_record_offset = RAS_RECORD_START;
control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amd/ras: Fix CPER ring debugfs read overflow
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (2 preceding siblings ...)
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18] drm/amdgpu: validate RAS EEPROM tbl_size before record count Sasha Levin
@ 2026-08-31 13:22 ` Sasha Levin
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18] drm/amd/display: Avoid DPMS-on for phantom stream Sasha Levin
` (33 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:22 UTC (permalink / raw)
To: patches, stable
Cc: Xiang Liu, Tao Zhou, Alex Deucher, Sasha Levin, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Xiang Liu <xiang.liu@amd.com>
[ Upstream commit 1e40ef87ffdc291e05ccdade8b9170cc9c1c4249 ]
The legacy CPER debugfs reader can reach the payload path without a
valid pointer snapshot. The remaining user byte count is also treated as
the ring occupancy in dwords, so reads past the header can copy more than
requested.
Take the CPER lock before sampling pointers. Resample rptr/wptr for
payload reads, bound the payload copy by available dwords and the
remaining user size, and advance the file position for each dword copied.
Signed-off-by: Xiang Liu <xiang.liu@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:
# Stable Backport Analysis: drm/amd/ras: Fix CPER ring debugfs read
overflow
**Local tree:** Linux 6.18.43 (`git describe HEAD` →
`v6.18.43-1-gc7f0dac02d232`, Makefile `6.18.43`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1 — Subject line**
Record: `[drm/amd/ras]` `[Fix]` — fixes a buffer-overflow / bounds bug
in the legacy CPER ring debugfs reader (`amdgpu_debugfs_ring_read`).
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Xiang Liu <xiang.liu@amd.com>` (author)
- `Reviewed-by: Tao Zhou <tao.zhou1@amd.com>`
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (drm/amdgpu
maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`,
`Tested-by:`
- Cherry-pick object in repo notes `(cherry picked from commit
1e40ef87ffdc291e05ccdade8b9170cc9c1c4249)`
**Step 1.3 — Body analysis**
Record:
- **Bug:** Legacy CPER debugfs reader can enter the payload path without
a valid rptr/wptr snapshot; user byte count (`size`) is overwritten
with ring occupancy in dwords, so reads past the 12-byte header can
copy more data than the user requested.
- **Symptom:** User buffer overflow on `read()` of
`/sys/kernel/debug/dri/*/amdgpu_ring_cper`; also uninitialized pointer
use and missing lock coverage on payload-only reads (`*pos >= 12`).
- **Root cause (author):** Lock taken only inside `if (*pos < 12)`;
`early[]` not populated when skipping header; `size` repurposed as
dword count; wrong wrap size (`ring_size` bytes vs dword indices);
`*pos` not advanced in CPER payload loop.
**Step 1.4 — Hidden bug fix?**
Record: No — explicitly labeled and described as an overflow fix.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1 — Inventory**
Record:
- 1 file: `drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c` (+21 / −8 in the
cherry-pick object `6bbede02dc62`)
- Function modified: `amdgpu_debugfs_ring_read()`
- Scope: single-file surgical fix (the user-provided diff also shows
`amdgpu_ras_cper_debugfs_read` changes, but those are **not** in
commit `6bbede02dc62` nor in this tree)
**Step 2.2 — Code flow changes**
| Hunk | Before | After |
|------|--------|-------|
| Lock scope | `mutex_lock` only inside `if (*pos < 12)` | Lock held for
entire CPER read path |
| Payload entry with `*pos >= 12` | `early[0/1]` never set; unlock
without lock | Resample rptr/wptr under lock |
| Copy bound | `size = ring occupancy` (dwords), ignoring user request |
`read_dw = min(avail_dw, size >> 2)` |
| Wrap calc | `ring->ring_size` (bytes) | `ring->buf_mask + 1` (dwords)
|
| Position | `*pos` not updated in CPER payload loop | `*pos += 4` per
dword |
**Step 2.3 — Bug mechanism**
Record: **Buffer overflow / out-of-bounds user copy** + **uninitialized
stack data** + **mutex imbalance** + **logic error** (wrong units,
missing file position advance).
Verified in current HEAD (`amdgpu_ring.c` lines 511–568):
```511:568:drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
if (*pos < 12) {
if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
mutex_lock(&ring->adev->cper.ring_lock);
// early[0..2] populated here only
...
}
...
} else {
p = early[0]; // uninitialized if *pos >= 12 at entry
...
size = (early[1] - early[0]); // overwrites
user's byte count
...
while (size) { // may copy far more than user
requested
...
size--;
// *pos not advanced
}
}
out:
if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
mutex_unlock(...); // unlock even when lock was never
taken
```
**Step 2.4 — Fix quality**
Record: Obviously correct, minimal, no API changes. Low regression risk
— only affects CPER ring debugfs reads. Reviewed by AMD RAS engineer and
merged by amdgpu maintainer.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1 — Blame**
Record: Current buggy function attributed to merge `5d324e5159d9e`
(6.18-rc8 era). Shallow stable history prevents tracing the original
CPER introduction commit; `amdgpu_cper.c` and CPER ring debugfs support
are present in this tree.
**Step 3.2 — Fixes: tag**
Record: N/A — no `Fixes:` tag.
**Step 3.3 — Related file history**
Record: `git log --oneline -20 --
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c` shows only merge commit in
this shallow tree. AUTOSel nomination exists: `[PATCH AUTOSEL 7.0-6.18]
drm/amd/ras: Fix CPER ring debugfs read overflow`.
**Step 3.4 — Author context**
Record: Xiang Liu (AMD). Reviewed by Tao Zhou (AMD RAS). Acked by Alex
Deucher (amdgpu maintainer).
**Step 3.5 — Dependencies**
Record: Standalone. `git cherry-pick --no-commit 6bbede02dc62` auto-
merges cleanly on HEAD (21 insertions, 8 deletions, 1 file only). No
prerequisite commits required.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1 — Original discussion**
Record: `b4 dig -c 6bbede02dc62` →
https://patch.msgid.link/20260507140004.244348-1-xiang.liu@amd.com
Single v1 patch, no NAKs found. Tao Zhou replied with `Reviewed-by`.
**Step 4.2 — Reviewers**
Record: `b4 dig -w`: To/Cc included `amd-gfx@lists.freedesktop.org`,
Hawking Zhang, Tao Zhou (AMD).
**Step 4.3 — Bug reports**
Record: No syzbot, bugzilla, or user crash reports. Issue identified by
code review / internal analysis.
**Step 4.4 — Series context**
Record: Standalone 1-patch series. AUTOSel 6.18 nomination confirms
stable relevance for this series.
**Step 4.5 — Stable list**
Record: AUTOSel 7.0-6.18 patch explicitly targets this stable series
(web search confirmed).
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1 — Key functions**
Record: `amdgpu_debugfs_ring_read()`, called from debugfs
`file_operations.read`.
**Step 5.2 — Callers**
Record: `amdgpu_debugfs_ring_fops.read` → debugfs file
`amdgpu_ring_<name>` created in `amdgpu_debugfs_ring_init()`. CPER ring
named `"cper"` → `/sys/kernel/debug/dri/<card>/amdgpu_ring_cper`.
**Step 5.3 — Callees**
Record: `mutex_lock/unlock`, `amdgpu_ring_get_rptr/wptr`, `put_user`,
ring buffer indexing.
**Step 5.4 — Reachability**
Record: Reachable via `read()` syscall on debugfs (requires
`CONFIG_DEBUG_FS`, debugfs mounted, typically `CAP_SYS_ADMIN`).
Triggered on any CPER ring read where `*pos >= 12` (normal after first
12-byte header) or partial reads.
**Step 5.5 — Similar patterns**
Record: Non-CPER ring path in same function correctly bounds by
`ring->ring_size + 12` and advances `*pos`; CPER path was the outlier.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE
**Step 6.1 — Buggy code present?**
Record: **YES** — verified in HEAD at `amdgpu_ring.c:497–576`. CPER
subsystem present (`amdgpu_cper.c`, `amdgpu_cper_init()` in
`amdgpu_device.c:3310`). Fix commit `6bbede02dc62` is **not** an
ancestor of HEAD.
**Step 6.2 — Backport complications**
Record: **Clean apply** — cherry-pick test succeeded with no conflicts.
**Step 6.3 — Related fixes already present?**
Record: **No** — `git diff HEAD 6bbede02dc62 --
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c` shows only the intended fix
hunks when cherry-picked; HEAD still has buggy code.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1 — Subsystem**
Record: `drivers/gpu/drm/amd/amdgpu` — GPU driver, RAS/CPER debug path.
Criticality: **PERIPHERAL** (AMD GPU + debugfs + CPER/RAS enabled).
**Step 7.2 — Activity**
Record: Active development; CPER support is relatively recent (mainline
~6.15+ per external references).
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1 — Who is affected**
Record: Systems with AMDGPU, `CONFIG_DEBUG_FS`, CPER ring initialized
(ACA or SR-IOV RAS CPER enabled), and a privileged user reading the CPER
ring debugfs file.
**Step 8.2 — Trigger conditions**
Record: Common on second/subsequent `read()` calls (after 12-byte
header). Requires debugfs access (typically root). Not triggerable by
unprivileged users under default permissions (debugfs `0444` but debugfs
mount is root-only on most distros).
**Step 8.3 — Failure mode severity**
Record:
- User buffer overflow via `put_user` beyond requested `size` → **HIGH**
(memory safety)
- `mutex_unlock` without `mutex_lock` when `*pos >= 12` → **HIGH**
(lockdep WARN / potential corruption in debug builds)
- Uninitialized `early[]` → **MEDIUM-HIGH** (undefined behavior,
possible kernel data leak to userspace)
- Overall: **HIGH** for memory safety; practical exploitability reduced
by privileged-only access
**Step 8.4 — Risk vs benefit**
Record:
- **Benefit:** Prevents user buffer overflow, fixes mutex imbalance,
corrects CPER debugfs semantics — **moderate** (narrow audience but
real bugs)
- **Risk:** Very low — 21-line surgical change, reviewed, clean apply
- **Ratio:** Benefit outweighs risk
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1 — Evidence summary**
| FOR | AGAINST |
|-----|---------|
| Real user buffer overflow | Debugfs-only path |
| Mutex unlock-without-lock bug | Requires `CONFIG_DEBUG_FS` |
| Uninitialized stack variable use | Admin/privileged access typically
required |
| Small, reviewed, maintainer-acked fix | No syzbot/user crash reports |
| Applies cleanly to 6.18.43 | Affects narrow hardware/config subset |
| AUTOSel nominated for 6.18.y | |
| Buggy code confirmed in this tree | |
**Step 9.2 — Stable rules checklist**
1. Obviously correct and tested? **PASS** — reviewed by AMD engineer +
amdgpu maintainer; logic verified against buggy code
2. Fixes a real bug? **PASS** — confirmed overflow, mutex bug,
uninitialized data
3. Important issue? **PASS** — memory safety / buffer overflow (severity
tempered by privileged-only access)
4. Small and contained? **PASS** — 1 file, ~29 lines
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** — cherry-pick tested clean
**Step 9.3 — Exception category**
Record: N/A (not device ID, quirk, DT, build, or docs fix — standard bug
fix).
**Step 9.4 — Decision rationale**
This fix addresses a genuine memory-safety bug in the CPER ring debugfs
reader that exists in Linux 6.18.43. The overflow is reachable on
ordinary multi-read patterns once the 12-byte header has been consumed.
While the path requires debugfs and typically root access, stable trees
routinely accept such fixes when they prevent kernel-to-userspace buffer
overruns and mutex imbalances. The patch is minimal, reviewed, applies
cleanly, and has been AUTOSel-nominated for 6.18.y.
---
## Verification
- [Phase 1] Parsed subject, tags (Reviewed-by Tao Zhou, SOB Alex
Deucher); no Fixes/Reported-by/Link
- [Phase 1] Identified overflow, uninitialized pointers, lock scope as
described bugs
- [Phase 2] Read `amdgpu_ring.c:497–576` — confirmed all four bug
mechanisms in HEAD
- [Phase 2] Cherry-pick object `6bbede02dc62` changes only
`amdgpu_debugfs_ring_read` (+21/−8)
- [Phase 3] `git describe HEAD` → v6.18.43; `make kernelversion`
equivalent → 6.18.43
- [Phase 3] `git merge-base --is-ancestor 6bbede02dc62 HEAD` → NOT
ancestor (fix not yet applied)
- [Phase 3] `git cherry-pick --no-commit 6bbede02dc62` → clean auto-
merge on `amdgpu_ring.c`
- [Phase 3] `git show 5d324e5159d9e:...amdgpu_ring.c` lines 545–575 →
buggy CPER path present at 6.18 base
- [Phase 4] `b4 dig -c 6bbede02dc62` →
https://patch.msgid.link/20260507140004.244348-1-xiang.liu@amd.com
- [Phase 4] `b4 dig -a` → single v1 revision only
- [Phase 4] `b4 dig -w` → amd-gfx list, Hawking Zhang, Tao Zhou CC'd
- [Phase 4] Freedesktop archive — Tao Zhou Reviewed-by, no NAKs
- [Phase 4] Web search — AUTOSel 7.0-6.18 nomination found
- [Phase 5] `grep amdgpu_debugfs_ring_fops` → debugfs read entry point
at `amdgpu_ring.c:592–595`
- [Phase 5] `amdgpu_debugfs_ring_init()` creates `amdgpu_ring_cper`
debugfs file at line 648–656
- [Phase 6] `amdgpu_cper_init` present in `amdgpu_device.c:3310`;
`amdgpu_cper.c` exists
- [Phase 6] No `amdgpu_uniras_enabled` or `amdgpu_ras_cper_debugfs_read`
in this tree (not needed for fix)
- [Phase 8] Failure modes verified by code inspection: overflow, mutex
imbalance, uninitialized `early[]`
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 29 +++++++++++++++++-------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 304564ec2f59a..431cc39ea0178 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -498,8 +498,9 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
size_t size, loff_t *pos)
{
struct amdgpu_ring *ring = file_inode(f)->i_private;
- uint32_t value, result, early[3];
+ u32 value, result, early[3] = { 0 };
uint64_t p;
+ u32 avail_dw, start_dw, read_dw;
loff_t i;
int r;
@@ -508,10 +509,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
result = 0;
- if (*pos < 12) {
- if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
- mutex_lock(&ring->adev->cper.ring_lock);
+ if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
+ mutex_lock(&ring->adev->cper.ring_lock);
+ if (*pos < 12) {
early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;
early[2] = ring->wptr & ring->buf_mask;
@@ -543,13 +544,24 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
*pos += 4;
}
} else {
+ early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
+ early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;
+
p = early[0];
if (early[0] <= early[1])
- size = (early[1] - early[0]);
+ avail_dw = early[1] - early[0];
else
- size = ring->ring_size - (early[0] - early[1]);
+ avail_dw = ring->buf_mask + 1 - (early[0] - early[1]);
- while (size) {
+ start_dw = (*pos > 12) ? ((*pos - 12) >> 2) : 0;
+ if (start_dw >= avail_dw)
+ goto out;
+
+ p = (p + start_dw) & ring->ptr_mask;
+ avail_dw -= start_dw;
+ read_dw = min_t(u32, avail_dw, size >> 2);
+
+ while (read_dw) {
if (p == early[1])
goto out;
@@ -562,9 +574,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
buf += 4;
result += 4;
- size--;
+ read_dw--;
p++;
p &= ring->ptr_mask;
+ *pos += 4;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amd/display: Avoid DPMS-on for phantom stream
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (3 preceding siblings ...)
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18] drm/amd/ras: Fix CPER ring debugfs read overflow Sasha Levin
@ 2026-08-31 13:22 ` Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Let driver decide buffer size at AMDKFD_IOC_GET_DMABUF_INFO ioctl Sasha Levin
` (32 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:22 UTC (permalink / raw)
To: patches, stable
Cc: Ilya Bakoulin, Alvin Lee, Ray Wu, Daniel Wheeler, Alex Deucher,
Sasha Levin, harry.wentland, sunpeng.li, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
[ Upstream commit 10f5f9c0ef32d08b228bfee3684b62f36f395852 ]
[Why & How]
Calling dc_update_planes_and_stream separately for stream and its
phantom stream causes a NULL pointer dereference, since the phantom is
destroyed on the first call.
Skip the call for phantom streams.
Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Tested-by: Daniel 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:
# Stable Backport Analysis: `drm/amd/display: Avoid DPMS-on for phantom
stream`
**Local tree:** `stable/linux-6.18.y` at **v6.18.44** (`git describe
HEAD` / `make kernelversion` → 6.18.44)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amd/display]` `[Avoid]` — Skip DPMS-on stream updates
for phantom (SubVP) streams during DP link-training automation to
prevent a NULL pointer dereference.
### Step 1.2: Tags
**Record:**
- **Reviewed-by:** Alvin Lee \<alvin.lee2@amd.com\>
- **Tested-by:** Daniel Wheeler \<daniel.wheeler@amd.com\>
- **Signed-off-by:** Ilya Bakoulin, Ray Wu, Alex Deucher (maintainer)
- **No** Fixes:, Reported-by:, Link:, Cc: stable@vger.kernel.org
- Notable: Reviewed and tested by AMD display engineers; Alex Deucher
acked (subsystem maintainer).
### Step 1.3: Body analysis
**Record:**
- **Bug:** Calling `dc_update_planes_and_stream()` separately for a real
stream and its paired phantom stream causes a NULL pointer
dereference.
- **Symptom:** Kernel oops / crash in the display driver during DP link
retrain automation.
- **Root cause (author):** The phantom stream is destroyed on the first
`dc_update_planes_and_stream()` call; a second call uses a stale/freed
pointer.
- **Fix:** Skip phantom streams when building the list of streams to
update with DPMS-on.
### Step 1.4: Hidden bug fix?
**Record:** No — this is an explicit NULL-deref fix, not disguised
cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:**
`drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c` (+2
lines)
- **Function:** `dp_retrain_link_dp_test()`
- **Scope:** Single-file, surgical fix (2 lines added)
### Step 2.2: Code flow change
**Record:**
- **Before:** Loop over `state->streams[i]` on the link caches every
stream (including phantoms), then calls
`dc_update_planes_and_stream()` for each.
- **After:** Streams with `is_phantom == true` are skipped during
caching; only real streams get DPMS-on updates.
- **Path affected:** DP link retrain / compliance-test automation error
path in `dp_retrain_link_dp_test()`.
### Step 2.3: Bug mechanism
**Record:**
- **Category:** NULL pointer dereference (memory safety)
- **Mechanism:** `dc_update_planes_and_stream()` with
`stream_update->dpms_off` forces `UPDATE_TYPE_FULL` (verified in
`check_update_surfaces_for_stream()` at lines 2966–2996 of `dc.c`).
Full updates call `dc_state_remove_phantom_streams_and_planes()` and
`dc_state_release_phantom_streams_and_planes()` (lines 3529–3530 of
`dc.c`), freeing phantom streams. The second loop iteration still
holds a cached phantom pointer → NULL deref.
### Step 2.4: Fix quality
**Record:**
- Fix is obviously correct and minimal.
- Matches existing convention: `resource_log_pipe_topology_update()`
already skips `is_phantom` streams (`dc_resource.c:2419`).
- Regression risk: very low — phantom streams should not receive
independent DPMS-on updates.
- No API or structural changes.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:**
- Buggy loop introduced by **f5b69101f956f** (2025-07-17): "Cache
streams targeting link when performing LT automation"
- That commit is an ancestor of v6.18.0 and of current HEAD.
- `is_phantom` on `struct dc_stream_state` dates to **012a04b1d6af6**
(2023-11-21).
### Step 3.2: Fixes: tag
**Record:** N/A — no Fixes: tag in commit message.
### Step 3.3: Related file history
**Record:**
- **f5b69101f956f** — introduced stream caching loop (root of this bug
pattern)
- **89939cf252d80** (2025-09-29) — different NULL-deref fix in same
function: cache `dc` from `link->dc` instead of stale
`state->clk_mgr->ctx->dc` after first stream update. Already in
6.18.44 but does **not** fix the phantom-stream issue.
- Fix commit **10f5f9c0ef32d** (upstream) / **56337aae2421b** (stable
candidate) is **not** in 6.18.44.
- Standalone fix; not part of a multi-patch series.
### Step 3.4: Author context
**Record:** Ilya Bakoulin is an active AMD display contributor (link/DP
fixes). Alex Deucher is amdgpu/drm maintainer.
### Step 3.5: Dependencies
**Record:**
- Requires `is_phantom` field — present in this tree
(`dc_stream.h:313`).
- Requires stream-caching loop from f5b69101 — present in this tree.
- Cherry-pick of upstream **10f5f9c0ef32d** auto-merges cleanly against
6.18.44 (verified).
- **Standalone:** PASS.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1–4.5
**Record:**
- `b4 dig -c 10f5f9c0ef32d`: no lore match found.
- lore.kernel.org fetch: 403 Forbidden (bot protection).
- **UNVERIFIED:** No mailing-list thread or stable-list discussion
retrieved.
- Tags show AMD internal review (Reviewed-by, Tested-by) and maintainer
sign-off.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `dp_retrain_link_dp_test()` modified; calls
`dc_update_planes_and_stream()`.
### Step 5.2: Callers
**Record:**
- `dp_test_send_link_training()` → `dp_handle_automated_test()` (DP
compliance test / link-training automation)
- `dp_set_preferred_training_settings()` path at line 991 (preferred
link settings retrain during normal DP operation)
### Step 5.3: Callees
**Record:** `dc_update_planes_and_stream()` →
`update_planes_and_stream_v3/v2()` → phantom removal on FULL updates.
### Step 5.4: Reachability
**Record:**
- Trigger requires SubVP/MALL phantom streams on a DP link (`is_phantom
== true`).
- Triggered during DP link retrain (compliance testing or preferred-
settings retrain).
- Not a direct unprivileged syscall path, but reachable during normal
display hotplug/link-rate changes on AMD GPUs with SubVP enabled.
- Config: `CONFIG_DRM_AMD_DC` (common on AMD systems).
### Step 5.5: Similar patterns
**Record:** `dc_resource.c:2419` skips phantom streams in topology
logging — same semantic rule applied here.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE (6.18.44)
### Step 6.1: Buggy code present?
**Record:** **YES.** Lines 145–148 of `link_dp_cts.c` cache all link
streams without phantom skip. Bug present since v6.18.0 (f5b69101 is
ancestor of v6.18).
### Step 6.2: Backport complications
**Record:** Clean apply — cherry-pick test succeeded with auto-merge.
Only contextual difference from upstream is the already-applied `struct
dc *dc = link->dc` from 89939cf; phantom skip is independent.
### Step 6.3: Related fixes already present?
**Record:** 89939cf fixes a **different** NULL deref in the same
function (stale `dc` context). Phantom-stream NULL deref remains unfixed
in 6.18.44.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem / criticality
**Record:** `drivers/gpu/drm/amd/display` — **IMPORTANT** (AMD GPU
display driver; crash on affected hardware configs).
### Step 7.2: Activity
**Record:** Actively maintained; multiple recent fixes in
`link_dp_cts.c` on this branch.
---
## PHASE 8: IMPACT AND RISK
### Step 8.1: Who is affected
**Record:** AMD GPU users with SubVP/MALL phantom streams on a
DisplayPort link during link retrain or DP compliance-test automation.
### Step 8.2: Trigger conditions
**Record:**
- SubVP phantom stream active on the DP link
- DP link retrain via `dp_retrain_link_dp_test()`
- Moderately rare compared to general kernel paths, but real on modern
AMD APUs/laptops with power-saving display features
### Step 8.3: Failure mode
**Record:** NULL pointer dereference → kernel oops. **Severity: HIGH**
(system crash when triggered).
### Step 8.4: Risk vs benefit
**Record:**
- **Benefit:** Prevents kernel crash on a real, reproducible code path;
2-line fix.
- **Risk:** Very low — aligns with existing phantom-skip patterns
elsewhere.
- **Ratio:** Favorable for stable backport.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Fixes verified NULL pointer dereference
- Small (2 lines), obviously correct
- Buggy code confirmed in 6.18.44 since v6.18.0
- Applies cleanly
- Reviewed, tested, maintainer-signed
- Complements but does not duplicate existing 89939cf fix
**AGAINST backport:**
- Narrow trigger (SubVP + DP link retrain)
- No public bug report or syzbot trace in commit message
**UNRESOLVED:**
- Mailing-list discussion (b4/lore unavailable)
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** (code review + Tested-by)
2. Fixes real bug affecting users? **PASS** (NULL deref on real path)
3. Important issue? **PASS** (kernel crash — HIGH severity when
triggered)
4. Small and contained? **PASS** (2 lines, 1 file)
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** (verified cherry-pick)
### Step 9.3: Exception categories
**Record:** None — standard bug fix.
### Step 9.4: Decision rationale
This commit fixes a real NULL pointer dereference in the 6.18.y tree.
The buggy stream-caching loop has been present since v6.18.0; the fix is
not yet in 6.18.44. The existing 89939cf fix addresses a separate stale-
context NULL deref in the same function. The phantom-stream skip is
minimal, follows established conventions, applies cleanly, and prevents
a kernel oops on AMD systems using SubVP during DP link retrain.
---
## Verification
- **[Phase 1]** Parsed commit message and tags from user-provided diff
and `git show 10f5f9c0ef32d`
- **[Phase 2]** Read `link_dp_cts.c:65-157`, `dc.c:2927-2996`,
`dc.c:3526-3530`, `dc_state.c:916-956`
- **[Phase 3]** `git blame -L 145,148 link_dp_cts.c` → f5b69101f956f
- **[Phase 3]** `git log --oneline` on `link_dp_cts.c` → f5b69101,
89939cf present; phantom fix absent
- **[Phase 3]** `git merge-base --is-ancestor f5b69101 HEAD` → in tree;
`10f5f9c0ef32d` → NOT in tree
- **[Phase 3]** `git merge-base --is-ancestor f5b69101 v6.18` → buggy
code in v6.18.0
- **[Phase 4]** `b4 dig -c 10f5f9c0ef32d` → no match; lore fetch → 403
- **[Phase 5]** `grep dp_retrain_link_dp_test` → callers at lines 185,
601, 991
- **[Phase 5]** `grep is_phantom` → field exists in `dc_stream.h:313`;
skip pattern in `dc_resource.c:2419`
- **[Phase 6]** `git describe HEAD` → v6.18.44; buggy code confirmed at
lines 145-148 without phantom skip
- **[Phase 6]** Cherry-pick test of 10f5f9c0ef32d → auto-merge success
- **[Phase 8]** Failure mode: NULL deref on second
`dc_update_planes_and_stream()` call after phantom freed
**YES**
drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
index 2676ae9f6fe83..5f70793b8372e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
@@ -143,6 +143,8 @@ static void dp_retrain_link_dp_test(struct dc_link *link,
// Set DPMS on with stream update
// Cache all streams on current link since dc_update_planes_and_stream might kill current_state
for (i = 0; i < MAX_PIPES; i++) {
+ if (state->streams[i] && state->streams[i]->is_phantom)
+ continue;
if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link)
streams_on_link[num_streams_on_link++] = state->streams[i];
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Let driver decide buffer size at AMDKFD_IOC_GET_DMABUF_INFO ioctl
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (4 preceding siblings ...)
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18] drm/amd/display: Avoid DPMS-on for phantom stream Sasha Levin
@ 2026-08-31 13:23 ` Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Initialize dsc_caps to 0 Sasha Levin
` (31 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:23 UTC (permalink / raw)
To: patches, stable
Cc: Xiaogang Chen, Alex Deucher, Sasha Levin, Felix.Kuehling,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Xiaogang Chen <xiaogang.chen@amd.com>
[ Upstream commit 8242a8d9d7194d5ef8a8b38a5621ca0966a3ec15 ]
amdkfd driver needs allocate buffer to return bo metadata to user space. The
buffer size is controlled by user currently. It is a potential security issue
that hostile value (e.g. 2 GiB) lets any render-group user trigger order-MAX
allocation/OOM in kernel context.
This patch first finds bo metadata size. If the size is smaller than user
provided value drive can safely allocate buffer in kernel space and copy to
user space buffer. If not, driver will let user know, not allocate and copy.
User will redo with new buffer in user space.
This patch lets driver decide buffer allocation size to avoid potential hostile
size from user space.
Signed-off-by: Xiaogang Chen <xiaogang.chen@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit f54ce9e8cbd3abe0eda3a285f54dc4f572fe589a)
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/amdkfd]` `[Let driver decide]` — ioctl security hardening
for `AMDKFD_IOC_GET_DMABUF_INFO` so the kernel no longer allocates based
on user-supplied buffer size.
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Xiaogang Chen <xiaogang.chen@amd.com>` (author)
- `Reviewed-by: Alex Deucher <alexander.deucher@amd.com>` (AMD DRM
maintainer)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (committer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`,
`Tested-by:`, or `Acked-by:`
Notable: maintainer review only; no fuzzer or user bug report cited.
**Step 1.3 — Body analysis**
Record:
- **Bug:** `kfd_ioctl_get_dmabuf_info()` allocates a kernel buffer with
`kzalloc(args->metadata_size, GFP_KERNEL)` where `metadata_size` is
fully user-controlled.
- **Symptom:** A render-group user can pass a hostile size (e.g. 2 GiB)
and force large kernel allocations → OOM / denial of service.
- **Root cause:** Allocation size is driven by userspace, not by actual
BO metadata size.
- **Fix approach:** Query actual metadata size first via
`amdgpu_bo_get_metadata()` with `buffer=NULL`; allocate only
`*metadata_size` bytes (bounded by driver data); reject with `-EINVAL`
if user buffer is too small.
- **Version info:** None in message.
**Step 1.4 — Hidden bug fix?**
Record: **Yes.** Although not labeled “fix”, this is a classic user-
controlled kernel allocation / DoS hardening pattern, same class as
other KFD ioctl validation fixes already in stable.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
Record:
- `drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c`: +15 / -3
- `drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h`: signature change (1
line)
- `drivers/gpu/drm/amd/amdkfd/kfd_chardev.c`: +2 / -8
- **Functions:** `amdgpu_amdkfd_get_dmabuf_info()`,
`kfd_ioctl_get_dmabuf_info()`
- **Scope:** Single-subsystem, 3-file surgical fix (~22 insertions, ~13
deletions)
**Step 2.2 — Code flow per hunk**
Record:
1. **`kfd_chardev.c`:** Before → `kzalloc(args->metadata_size)` when
`metadata_ptr` set. After → no user-size allocation; passes
`&metadata_buffer` to helper; copies only if both kernel buffer and
`metadata_ptr` are set.
2. **`amdgpu_amdkfd.c`:** Before → passes user buffer directly to
`amdgpu_bo_get_metadata()`. After → queries size with `buffer=NULL`,
allocates `kzalloc(*metadata_size)` only when `*metadata_size <=
buffer_size`, else `-EINVAL`.
3. **`amdgpu_amdkfd.h`:** `metadata_buffer` parameter becomes `void **`
so callee can allocate and return buffer pointer.
**Step 2.3 — Bug mechanism**
Record: **Memory safety / DoS via user-controlled allocation size.**
Category: unvalidated userspace size passed to `kzalloc()` in ioctl
handler. Fix caps kernel allocation to actual BO metadata size (small,
driver-controlled).
**Step 2.4 — Fix quality**
Record: **Obviously correct** for the stated problem. Minimal, focused
change. Minor concern: on `kzalloc()` failure the fix returns `-ENOMEM`
directly without `goto out_put`, leaking a `dma_buf` reference — rare
path, does not undermine the security fix. No API or UAPI structure
changes.
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
Record: Vulnerable `kzalloc(args->metadata_size, ...)` introduced in
`1dde0ea95b782` (Felix Kuehling, 2018-11-20) — “drm/amdkfd: Add DMABuf
import functionality”. Bug present since v4.20 era; definitely present
in this 6.18.44 tree.
**Step 3.2 — Fixes: tag**
Record: N/A — no `Fixes:` tag.
**Step 3.3 — Related file history**
Record: Related stable-style KFD ioctl hardening already in this tree:
- `db9530a9873a7` — “drm/amdkfd: validate SVM ioctl nattr against buffer
size” (cherry-picked to stable by Greg K-H)
- `9e52212aff8ed` — missing authorization check fix
- `6156c101e5f08` — `memdup_user` replacing `kzalloc` + `copy_from_user`
Standalone fix; not part of a multi-patch series.
**Step 3.4 — Author context**
Record: Xiaogang Chen is an AMD contributor (recent KFD/amdgpu commits).
Alex Deucher reviewed and committed — strong subsystem credibility.
**Step 3.5 — Dependencies**
Record: **None.** Uses existing `amdgpu_bo_get_metadata()` NULL-buffer
query path (supported since that function was written). Only caller of
`amdgpu_amdkfd_get_dmabuf_info()` is `kfd_ioctl_get_dmabuf_info()`. `git
apply --check` passes cleanly on this tree.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
Record: `b4 dig -c f54ce9e8cbd3` — **no match found** on
lore.kernel.org. Manual lore search blocked (Anubis bot protection).
Phase partially N/A.
**Step 4.2 — Reviewers from b4 -w**
Record: N/A (b4 found nothing).
**Step 4.3 — Bug report**
Record: N/A — no `Reported-by:` or `Link:` tags.
**Step 4.4 — Related patches**
Record: Same subsystem pattern as `db9530a9873a7` (user-controlled ioctl
sizing). No series dependency.
**Step 4.5 — Stable list**
Record: Could not search lore stable archive (bot protection). However,
analogous KFD ioctl validation was already accepted into this 6.18.y
tree (`db9530a9873a7`).
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
Record: `kfd_ioctl_get_dmabuf_info()`,
`amdgpu_amdkfd_get_dmabuf_info()`, `amdgpu_bo_get_metadata()`.
**Step 5.2 — Callers**
Record: `kfd_ioctl_get_dmabuf_info()` registered as
`AMDKFD_IOC_GET_DMABUF_INFO` ioctl handler (render-node accessible).
`amdgpu_amdkfd_get_dmabuf_info()` called only from that ioctl path.
**Step 5.3 — Callees**
Record: `dma_buf_get/put`, `amdgpu_bo_get_metadata()`, `kzalloc/kfree`,
`copy_to_user`, `kfd_devcgroup_check_permission()`.
**Step 5.4 — Reachability**
Record: **Userspace-reachable** via `/dev/kfd` ioctl from processes with
render-node access (`kfd_devcgroup_check_permission()` checks
`DEVCG_ACC_READ|WRITE` on DRM render minor). Attacker needs render-group
membership and a valid amdgpu dmabuf fd — realistic on desktop/container
ROCm/GPU compute setups.
**Step 5.5 — Similar patterns**
Record: Same anti-pattern fixed elsewhere in KFD (`db9530a9873a7` for
SVM ioctl). Confirms subsystem maintainers treat user-controlled ioctl
allocation sizes as security issues.
---
## Phase 6: Cross-Reference Against Local Tree
**Step 6.1 — Buggy code present?**
Record: **Yes.** Local tree is **Linux 6.18.44** (`git describe HEAD` →
`v6.18.44-1-g2736c32da98b9`). Commit `f54ce9e8cbd3` is **not** an
ancestor of HEAD. Vulnerable code confirmed at
`kfd_chardev.c:1527-1530`:
```1527:1531:drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
if (args->metadata_ptr) {
metadata_buffer = kzalloc(args->metadata_size,
GFP_KERNEL);
if (!metadata_buffer)
return -ENOMEM;
}
```
**Step 6.2 — Backport complications**
Record: **Clean apply** — `git show f54ce9e8cbd3 | git apply --check`
succeeds with no conflicts.
**Step 6.3 — Related fixes already present?**
Record: No duplicate fix for this ioctl. Related KFD ioctl validation
fixes exist (`db9530a9873a7`) but not for `GET_DMABUF_INFO`.
---
## Phase 7: Subsystem and Maintainer Context
**Step 7.1 — Subsystem criticality**
Record: `drivers/gpu/drm/amd/amdkfd` — **IMPORTANT** (AMD GPU compute /
ROCm users; not universal core kernel, but widely deployed on AMD
systems with `CONFIG_DRM_AMDGPU`).
**Step 7.2 — Activity**
Record: Actively maintained — 20 recent commits on `kfd_chardev.c`
including multiple security/validation fixes in 2026.
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
Record: Users of AMD KFD/ROCm with amdgpu (`CONFIG_DRM_AMDGPU=y/m`). Any
process in the GPU render group on multi-user or containerized systems.
**Step 8.2 — Trigger conditions**
Record: Call `AMDKFD_IOC_GET_DMABUF_INFO` with `metadata_ptr != 0` and
large `metadata_size` (e.g. 2 GiB). **Likelihood:** trivial for
authorized render-group users. **Unprivileged:** requires render-node
access (not fully unprivileged, but local DoS from less-privileged GPU
users is a recognized security concern).
**Step 8.3 — Failure mode severity**
Record: **Kernel OOM / memory exhaustion DoS** — **HIGH** severity
(system-wide impact possible). Not data corruption or privilege
escalation, but a reproducible resource exhaustion attack from userspace
ioctl.
**Step 8.4 — Risk vs benefit**
Record:
- **Benefit:** HIGH — closes long-standing (since 2018) user-controlled
kernel allocation hole
- **Risk:** LOW — ~35-line change, reviewed by maintainer, applies
cleanly, no UAPI changes
- **Ratio:** Strong benefit, low risk
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence summary**
**FOR backport:**
- Real security issue: user-controlled `kzalloc()` size in ioctl
- DoS / OOM impact on systems with AMD GPU compute
- Bug present in this 6.18.44 tree since 2018
- Small, surgical, maintainer-reviewed fix
- Applies cleanly
- Same class of fix already accepted in this tree (`db9530a9873a7`)
- `amdgpu_bo_get_metadata()` already supports size-only query with
`buffer=NULL`
**AGAINST backport:**
- Requires render-group access (not arbitrary unprivileged user) —
reduces universality but not severity for multi-tenant GPU systems
- Minor `dma_buf` leak on `ENOMEM` in the fix itself (rare)
- No external bug report or syzbot confirmation
**Unresolved:** Lore discussion and stable-list nomination could not be
retrieved.
**Step 9.2 — Stable rules checklist**
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — logic is clear;
Reviewed-by maintainer; no Tested-by |
| 2. Fixes real bug affecting users? | **PASS** — user-controlled kernel
allocation DoS |
| 3. Important issue? | **PASS** — HIGH (OOM DoS from ioctl) |
| 4. Small and contained? | **PASS** — 3 files, ~35 lines |
| 5. No new features/APIs? | **PASS** — same ioctl, hardened allocation
|
| 6. Can apply to local tree? | **PASS** — clean `git apply --check` |
**Step 9.3 — Exception category**
Record: Security hardening of existing ioctl (not device ID, quirk, DT,
build, or docs exception — standard security bug fix).
**Step 9.4 — Decision rationale**
This commit fixes a long-standing vulnerability where any render-group
user can force arbitrarily large kernel allocations via
`AMDKFD_IOC_GET_DMABUF_INFO`. The buggy code exists in the local 6.18.44
tree, the fix is small and maintainer-reviewed, it applies cleanly, and
the same subsystem has already accepted analogous ioctl validation fixes
for stable. The fix bounds kernel allocation to actual BO metadata size
(driver-controlled, typically small), eliminating the OOM attack vector.
---
## Verification
- [Phase 1] Parsed commit `f54ce9e8cbd3` message: security issue, user-
controlled allocation, Reviewed-by Alex Deucher
- [Phase 2] Full diff reviewed: 3 files, `kzalloc` moved from user size
to `*metadata_size`
- [Phase 2] Read `amdgpu_bo_get_metadata()`: supports `buffer=NULL` +
`metadata_size` out-param (`amdgpu_object.c:1227-1233`)
- [Phase 3] `git blame` lines 1527-1531 → `1dde0ea95b782` (2018-11-20)
- [Phase 3] `git log -S kfd_ioctl_get_dmabuf_info` → introduced in
`1dde0ea95b782`
- [Phase 3] `git log --oneline -20 -- kfd_chardev.c` → related stable
fix `db9530a9873a7` present
- [Phase 3] `grep amdgpu_amdkfd_get_dmabuf_info` → single caller in
`kfd_chardev.c`
- [Phase 3] `git apply --check` → patch applies cleanly
- [Phase 4] `b4 dig -c f54ce9e8cbd3` → no lore match
- [Phase 4] lore.kernel.org manual fetch → blocked by Anubis (UNVERIFIED
for list discussion)
- [Phase 5] Read `kfd_devcgroup_check_permission()` → render-node cgroup
check (`kfd_priv.h:1564-1576`)
- [Phase 5] Confirmed ioctl registration at `kfd_chardev.c:3232-3233`
- [Phase 6] `git describe HEAD` → v6.18.44; `make kernelversion` →
6.18.44
- [Phase 6] `git merge-base --is-ancestor f54ce9e8cbd3 HEAD` → commit
NOT in tree
- [Phase 6] Read current `kfd_chardev.c:1527-1530` → vulnerable code
present
- [Phase 8] Assessed failure mode: OOM DoS, HIGH severity for GPU multi-
tenant scenarios
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 23 ++++++++++++++++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 2 +-
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 ++--------
3 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 1ec26be82f30e..5e8d0d6b55ab6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -528,7 +528,7 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev)
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
- uint64_t *bo_size, void *metadata_buffer,
+ uint64_t *bo_size, void **metadata_buffer,
size_t buffer_size, uint32_t *metadata_size,
uint32_t *flags, int8_t *xcp_id)
{
@@ -563,9 +563,24 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
*dmabuf_adev = adev;
if (bo_size)
*bo_size = amdgpu_bo_size(bo);
- if (metadata_buffer)
- r = amdgpu_bo_get_metadata(bo, metadata_buffer, buffer_size,
- metadata_size, &metadata_flags);
+ if (metadata_buffer) {
+ /* first get metadata_size by buffer = NULL */
+ r = amdgpu_bo_get_metadata(bo, NULL, 0,
+ metadata_size, NULL);
+
+ /* user buf_size is bigger than bo metadata_size
+ * allocate a buf at kernel space and copy */
+ if (*metadata_size <= buffer_size) {
+ *metadata_buffer = kzalloc(*metadata_size, GFP_KERNEL);
+
+ if (!*metadata_buffer)
+ return -ENOMEM;
+
+ r = amdgpu_bo_get_metadata(bo, *metadata_buffer, *metadata_size,
+ NULL, &metadata_flags);
+ } else
+ r = -EINVAL;
+ }
if (flags) {
*flags = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
KFD_IOC_ALLOC_MEM_FLAGS_VRAM
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 9e120c934cc17..c59b5d9cd36b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -255,7 +255,7 @@ uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
- uint64_t *bo_size, void *metadata_buffer,
+ uint64_t *bo_size, void **metadata_buffer,
size_t buffer_size, uint32_t *metadata_size,
uint32_t *flags, int8_t *xcp_id);
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index d3190c3bb1aee..d220cf60375ba 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1524,16 +1524,10 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
if (!dev)
return -EINVAL;
- if (args->metadata_ptr) {
- metadata_buffer = kzalloc(args->metadata_size, GFP_KERNEL);
- if (!metadata_buffer)
- return -ENOMEM;
- }
-
/* Get dmabuf info from KGD */
r = amdgpu_amdkfd_get_dmabuf_info(dev->adev, args->dmabuf_fd,
&dmabuf_adev, &args->size,
- metadata_buffer, args->metadata_size,
+ &metadata_buffer, args->metadata_size,
&args->metadata_size, &flags, &xcp_id);
if (r)
goto exit;
@@ -1545,7 +1539,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
args->flags = flags;
/* Copy metadata buffer to user mode */
- if (metadata_buffer) {
+ if (metadata_buffer && args->metadata_ptr) {
r = copy_to_user((void __user *)args->metadata_ptr,
metadata_buffer, args->metadata_size);
if (r != 0)
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Initialize dsc_caps to 0
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (5 preceding siblings ...)
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Let driver decide buffer size at AMDKFD_IOC_GET_DMABUF_INFO ioctl Sasha Levin
@ 2026-08-31 13:23 ` Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] drm/amdkfd: Properly acquire queue buffers in CRIU restore Sasha Levin
` (30 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:23 UTC (permalink / raw)
To: patches, stable
Cc: Ivan Lipski, Harry Wentland, Alex Deucher, Sasha Levin,
sunpeng.li, christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Ivan Lipski <ivan.lipski@amd.com>
[ Upstream commit d18ecfee5187e3b2dbff7e67dda8b2f54ff5231c ]
[Why&How]
If we don't do that we make DSC decisions based on random
inputs, which might result in disallowing DSC when the
monitor and HW support it.
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@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 background searches finished and matched the earlier analysis:
- **Fix not in this tree:** `git log` for `Initialize dsc_caps` /
`dsc_caps = {0}` returned nothing — the patch isn’t in v6.18.44 yet,
but the bug is still there (`struct dsc_dec_dpcd_caps dsc_caps;` at
line 7168).
- **b4 dig:** No result, since the commit isn’t present locally to look
up.
**Verdict stands: YES** for backport to this 6.18.y tree — one-line
zero-init fix for uninitialized DSC caps used during mode setup on
AMDGPU.
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4f53297786623..8445b13549c17 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7165,7 +7165,7 @@ create_stream_for_sink(struct drm_connector *connector,
int preferred_refresh = 0;
enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN;
#if defined(CONFIG_DRM_AMD_DC_FP)
- struct dsc_dec_dpcd_caps dsc_caps;
+ struct dsc_dec_dpcd_caps dsc_caps = {0};
#endif
struct dc_link *link = NULL;
struct dc_sink *sink = NULL;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] drm/amdkfd: Properly acquire queue buffers in CRIU restore
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (6 preceding siblings ...)
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Initialize dsc_caps to 0 Sasha Levin
@ 2026-08-31 13:23 ` Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: flush pending RCU callbacks on module unload Sasha Levin
` (29 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:23 UTC (permalink / raw)
To: patches, stable
Cc: David Francis, Kent Russell, Alex Deucher, Sasha Levin,
Felix.Kuehling, christian.koenig, airlied, simona, amd-gfx,
dri-devel, linux-kernel
From: David Francis <David.Francis@amd.com>
[ Upstream commit 20a5e7ffdfecddc34c60a6b4483f42acf3d8731d ]
When kfd_queue_acquire_buffers() was split off from
set_queue_properties_from_user(), set_queue_properties_from_criu()
was missed. Thus, set_queue_properties_from_criu() is not
filling out the buffer fields of queue_properties, which
can come up when subsequent code expects them to be non-null.
Add the proper call to kfd_queue_acquire_buffers(), and also
use the right cast types in set_queue_properties_from_criu()
(which were missed at the same time)
Signed-off-by: David Francis <David.Francis@amd.com>
Reviewed-by: Kent Russell <kent.russell@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 88ed96abbbe27b70193544fbc1ee06448c274714)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The background check finished: neither `git log --grep="CRIU restore
queue buffers"` nor a search for the fix’s debug string (`"failed to
acquire user queue buffers for CRIU"`) turned up anything on HEAD. That
confirms the fix isn’t already in v6.18.44 under another commit.
The earlier analysis stands: this is a real NULL-deref regression in the
KFD CRIU restore path, and it should be backported.
**YES**
.../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index e96488f6b02d2..912c4ebd30405 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -974,8 +974,8 @@ static void set_queue_properties_from_criu(struct queue_properties *qp,
qp->priority = q_data->priority;
qp->queue_address = q_data->q_address;
qp->queue_size = q_data->q_size;
- qp->read_ptr = (uint32_t *) q_data->read_ptr_addr;
- qp->write_ptr = (uint32_t *) q_data->write_ptr_addr;
+ qp->read_ptr = (void __user *)q_data->read_ptr_addr;
+ qp->write_ptr = (void __user *)q_data->write_ptr_addr;
qp->eop_ring_buffer_address = q_data->eop_ring_buffer_address;
qp->eop_ring_buffer_size = q_data->eop_ring_buffer_size;
qp->ctx_save_restore_area_address = q_data->ctx_save_restore_area_address;
@@ -1064,10 +1064,18 @@ int kfd_criu_restore_queue(struct kfd_process *p,
memset(&qp, 0, sizeof(qp));
set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->adev->gfx.xcc_mask));
+ ret = kfd_queue_acquire_buffers(pdd, &qp);
+ if (ret) {
+ pr_debug("failed to acquire user queue buffers for CRIU\n");
+ goto exit;
+ }
+
print_queue_properties(&qp);
ret = pqm_create_queue(&p->pqm, pdd->dev, &qp, &queue_id, q_data, mqd, ctl_stack, NULL);
if (ret) {
+ kfd_queue_unref_bo_vas(pdd, &qp);
+ kfd_queue_release_buffers(pdd, &qp);
pr_err("Failed to create new queue err:%d\n", ret);
goto exit;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: flush pending RCU callbacks on module unload
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (7 preceding siblings ...)
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] drm/amdkfd: Properly acquire queue buffers in CRIU restore Sasha Levin
@ 2026-08-31 13:23 ` Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Fix updating clock limits from power states Sasha Levin
` (28 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:23 UTC (permalink / raw)
To: patches, stable
Cc: Perry Yuan, Yifan Zhang, Christian König, Alex Deucher,
Sasha Levin, airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Perry Yuan <perry.yuan@amd.com>
[ Upstream commit 67a654b41cfa73c3b83402c4a01b2689cad5b9bc ]
Call rcu_barrier() in module exit to wait for outstanding call_rcu() callbacks
before freeing module text, preventing late callback execution in freed memory.
BUG: unable to handle page fault for address: ffffffffc1d59c40
PGD 6a12067 P4D 6a12067 PUD 6a14067 PMD 13698b067 PTE 0
Oops: 0010 [#1] SMP NOPTI
RIP: 0010:0xffffffffc1d59c40
Code: Unable to access opcode bytes at RIP 0xffffffffc1d59c16.
RSP: 0018:ffffc900198c0f28 EFLAGS: 00010286
RAX: ffffffffc1d59c40 RBX: ffff897c7d6b61c0 RCX: ffff88826aff4590
RDX: ffff8884d8b35490 RSI: ffffc900198c0f30 RDI: ffff88812af67290
RBP: 000000000000000a (DONE segment entries) R08: 0000000000000000 R09: 0000000000000100
R10: 0000000000000000 R11: ffffffff82a06100 R12: ffff88811a4e3700
R13: 0000000000000000 R14: ffff897c7d6b6270 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff897c7d680000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffc1d59c16 CR3: 00000104a980a001 CR4: 0000000002770ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
PKRU: 55555554
Call Trace:
<IRQ>
? rcu_do_batch+0x163/0x450
? rcu_core+0x177/0x1c0
? __do_softirq+0xc1/0x280
? asm_call_irq_on_stack+0xf/0x20
</IRQ>
? do_softirq_own_stack+0x37/0x50
? irq_exit_rcu+0xc4/0x100
? sysvec_apic_timer_interrupt+0x36/0x80
? asm_sysvec_apic_timer_interrupt+0x12/0x20
? cpuidle_enter_state+0xd4/0x360
? cpuidle_enter+0x29/0x40
? cpuidle_idle_call+0x108/0x1a0
? do_idle+0x77/0xf0
? cpu_startup_entry+0x19/0x20
? secondary_startup_64_no_verify+0xbf/0xcb
Signed-off-by: Perry Yuan <perry.yuan@amd.com>
Reviewed-by: Yifan Zhang <yifan1.zhang@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit feaa5039f6c12acc9aa934c2d45dcd251a12c69f)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The background check finished: `feaa5039f6c12` is on mainline but not in
`stable/linux-6.18.y` (about 1.37M commits ahead of the stable branch
tip). A grep for "flush pending RCU" on the stable branch returned
nothing, so this fix still needs to be backported.
That matches the earlier analysis: the bug is present in v6.18.44, the
patch should apply cleanly at the end of `amdgpu_exit()`, and the
backport recommendation remains **YES**.
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 99f22633abf53..20e614db485cf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -3217,6 +3217,14 @@ static void __exit amdgpu_exit(void)
amdgpu_userq_fence_slab_fini();
mmu_notifier_synchronize();
amdgpu_xcp_drv_release();
+
+ /*
+ * Flush outstanding call_rcu() callbacks before the
+ * module text is freed. Otherwise a grace period elapsing after
+ * unload invokes a callback in already-freed module memory and
+ * faults in rcu_do_batch().
+ */
+ rcu_barrier();
}
module_init(amdgpu_init);
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Fix updating clock limits from power states
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (8 preceding siblings ...)
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: flush pending RCU callbacks on module unload Sasha Levin
@ 2026-08-31 13:23 ` Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Don't schedule thermal work when queue isn't initialized Sasha Levin
` (27 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:23 UTC (permalink / raw)
To: patches, stable
Cc: Jeremy Klarenbeek, Alex Deucher, Timur Kristóf, Sasha Levin,
kenneth.feng, christian.koenig, airlied, simona, amd-gfx,
dri-devel, linux-kernel
From: Jeremy Klarenbeek <jeremy.klarenbeek99@gmail.com>
[ Upstream commit e6c5d36756e7d4d260e2365fc4d01226f1973152 ]
VBIOS can contain conflicting values between:
- the maximum allowed clocks and voltages on AC or DC
- the clocks and voltages in power states on AC or DC
Update maximum clock (and voltage) limits for both AC/DC
and take the highest value from the VBIOS limits and
the performance/battery power states. Previously this
was only done for AC, but is also needed for DC.
This commit fixes the behaviour on some laptop GPUs,
where the VBIOS limit was set to the lowest possible
clock frequency, so the GPU was stuck on the lowest
possible power level on battery.
Some affected GPUs are:
FirePro W4170M (Dell Precision M2800)
Radeon HD 8790M (Dell Latitude E6540)
and possibly other laptop GPUs.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Co-developed-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Jeremy Klarenbeek <jeremy.klarenbeek99@gmail.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 background git searches finished and match the earlier analysis:
- **History search:** The AC-only `max_clock_voltage_on_ac` assignment
traces back through the SI DPM code (pickaxe hit `837d542a09cd5`, the
pm header relocation). No prior fix for DC clock limits was found.
- **Author search:** Jeremy Klarenbeek has no commits in this 6.18.44
tree.
- **Fix commit search:** `git log --grep="updating clock limits"`
returned nothing — the patch is not in this tree yet. The only "power
states" hit in `si_dpm.c` was an unrelated debug-level change.
- **Hardware search:** No existing commits mention the FirePro W4170M or
Radeon HD 8790M by name.
That supports the **YES** backport recommendation: the bug is present
and unfixed in 6.18.44, and this would be a new, standalone fix.The
hardware-related git search completed: there are no commits in this
6.18.44 tree that mention the FirePro W4170M, Radeon HD 8790M, or author
Jeremy Klarenbeek in connection with this clock-limits issue. That
confirms this would be a new fix rather than something already present
under a different commit.
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 29 ++++++++++++++++++----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
index 0385b24e7e4a2..ea97276358c0a 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
@@ -7238,6 +7238,7 @@ static void si_parse_pplib_clock_info(struct amdgpu_device *adev,
struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
struct si_power_info *si_pi = si_get_pi(adev);
struct si_ps *ps = si_get_ps(rps);
+ struct amdgpu_clock_and_voltage_limits *limits;
u16 leakage_voltage;
struct rv7xx_pl *pl = &ps->performance_levels[index];
int ret;
@@ -7297,12 +7298,30 @@ static void si_parse_pplib_clock_info(struct amdgpu_device *adev,
si_pi->mvdd_bootup_value = mvdd;
}
+ /*
+ * Update maximum allowed clock limits.
+ * VBIOS can contain conflicting values between:
+ * - the maximum allowed clocks and voltages on AC or DC
+ * - the clocks and voltages in power states on AC or DC
+ */
if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
- ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
- adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
- adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
- adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
- adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
+ ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE)
+ limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
+ else if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
+ ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)
+ limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
+ else
+ limits = NULL;
+
+ if (limits) {
+ if (pl->sclk > limits->sclk)
+ limits->sclk = pl->sclk;
+ if (pl->mclk > limits->mclk)
+ limits->mclk = pl->mclk;
+ if (pl->vddc > limits->vddc)
+ limits->vddc = pl->vddc;
+ if (pl->vddci > limits->vddci)
+ limits->vddci = pl->vddci;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Don't schedule thermal work when queue isn't initialized
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (9 preceding siblings ...)
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Fix updating clock limits from power states Sasha Levin
@ 2026-08-31 13:24 ` Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18] drm/amd/display: Fix 8K Mode Not Parsed by EDID Sasha Levin
` (26 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:24 UTC (permalink / raw)
To: patches, stable
Cc: Timur Kristóf, Alex Deucher, Sasha Levin, kenneth.feng,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Timur Kristóf <timur.kristof@gmail.com>
[ Upstream commit f8922d5a946699fc2bdc7660e6778bd6726bf8b8 ]
When DPM is turned off with the amdgpu.dpm=0 module parameter,
the thermal work queue isn't initialized so we shouldn't
schedule any work on it.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit bd018d36171a695952c6d391471c279c9e05c8b2)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `drm/amd/pm/si: Don't schedule thermal work
when queue isn't initialized`
**Local tree:** `v6.18.44` (Makefile: 6.18.44)
**Upstream commit:** `bd018d36171a695952c6d391471c279c9e05c8b2` — **not
present** in this checkout.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amd/pm/si]` `[Don't schedule]` — prevent scheduling
thermal work on an uninitialized workqueue when DPM is disabled.
### Step 1.2: Tags
**Record:**
- `Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>` (author)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (AMD DRM
maintainer)
- No `Fixes:`, `Reported-by:`, `Cc: stable@vger.kernel.org`, `Link:`,
`Tested-by:`, or `Reviewed-by:` tags
- Notable: maintainer sign-off; no syzbot/user crash report in message
### Step 1.3: Body analysis
**Record:**
- **Bug:** With `amdgpu.dpm=0`, thermal `struct work_struct` is never
initialized via `INIT_WORK()`, but thermal IRQ handling can still call
`schedule_work()` on it.
- **Symptom:** Undefined behavior / kernel crash when a thermal
interrupt fires under `dpm=0`.
- **Root cause (author):** Thermal IRQ IDs are registered before the
`amdgpu_dpm == 0` early-return in `si_dpm_sw_init()`, but
`INIT_WORK()` is skipped on that path.
### Step 1.4: Hidden bug fix?
**Record:** No — this is an explicit bug fix, not disguised cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c` (+1/-1, net 0
lines)
- **Function:** `si_dpm_process_interrupt()`
- **Scope:** Single-file, single-line surgical fix
### Step 2.2: Code flow change
**Record:**
- **Before:** Any thermal IRQ (src_id 230/231) →
`schedule_work(&adev->pm.dpm.thermal.work)` unconditionally.
- **After:** Same path, but only if `amdgpu_dpm` is non-zero.
- **Path affected:** Interrupt handler path (can run in interrupt
context; work is deferred).
### Step 2.3: Bug mechanism
**Record:** **Memory safety / logic correctness** — use of uninitialized
workqueue.
In `si_dpm_sw_init()`:
```7783:7808:drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230,
&adev->pm.dpm.thermal.irq);
// ...
ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231,
&adev->pm.dpm.thermal.irq);
// ...
if (amdgpu_dpm == 0)
return 0;
// ...
INIT_WORK(&adev->pm.dpm.thermal.work,
amdgpu_dpm_thermal_work_handler);
```
With `amdgpu.dpm=0`, IRQ handlers are registered but `INIT_WORK()` is
skipped. A thermal interrupt reaching `si_dpm_process_interrupt()` calls
`schedule_work()` on a zeroed but uninitialized work struct (device
allocated via `devm_drm_dev_alloc()`). The work function pointer is
NULL; queueing or executing such work can WARN or oops.
### Step 2.4: Fix quality
**Record:**
- **Quality:** High — mirrors existing `amdgpu_dpm` guards in the same
file (`si_dpm_hw_init`, `si_dpm_sw_init`).
- **Regression risk:** Very low — only suppresses work scheduling in the
exact case where work was never initialized.
- **Note:** `kv_dpm.c` has the same pattern unfixed; this commit only
addresses SI.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `si_dpm_process_interrupt()` and the unguarded
`schedule_work()` line blame to `^5d324e5159d9e` (predates reachable
history in this tree). Bug is long-standing, not a recent regression.
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related file history
**Record:** Recent `si_dpm.c` changes are unrelated powertune/HAINAN
fixes. No duplicate fix for this issue in this tree. Commit
`bd018d36171a` is **not** an ancestor of HEAD.
### Step 3.4: Author context
**Record:** Timur Kristóf is an active `drm/amd/pm` contributor
(multiple recent SI/CI/SMU7 fixes). Alex Deucher committed the fix.
### Step 3.5: Dependencies
**Record:** Standalone one-hunk change. `amdgpu_dpm` is already declared
in `amdgpu.h` (included by `si_dpm.c`). No prerequisite commits
required. Listed as patch 1/3 on the mailing list, but this hunk is
self-contained for SI.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- `b4 dig -c bd018d36171a`: https://patch.msgid.link/20260712173928.2597
01-1-timur.kristof@gmail.com
- `b4 dig -a`: v1 only; `[PATCH 1/3]` (series has 2 more patches, likely
KV/CI siblings)
- Lore/patch.msgid.link content blocked by bot protection — **could not
read thread replies, stable nominations, or NAKs**
### Step 4.2: Reviewers
**Record:** `b4 dig -w` CC'd `amd-gfx@lists.freedesktop.org`, Alex
Deucher, Natalie Vock, Mario Limonciello (AMD), Tvrtko Ursulin.
### Step 4.3: Bug report
**Record:** N/A — no external bug report linked.
### Step 4.4: Related patches
**Record:** Part of a 3-patch series; patches 2/3 and 3/3 not verified
in this tree. This commit does not depend on them.
### Step 4.5: Stable list
**Record:** UNVERIFIED — could not search lore stable archive due to bot
protection.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `si_dpm_process_interrupt()`, `si_dpm_sw_init()`,
`amdgpu_dpm_thermal_work_handler()`
### Step 5.2: Callers
**Record:** `si_dpm_process_interrupt` is the `.process` callback in
`si_dpm_irq_funcs`, wired via `si_dpm_set_irq_funcs()`. Invoked by the
amdgpu IRQ layer on thermal IH events (src_id 230/231).
### Step 5.3: Callees
**Record:** `schedule_work()` → workqueue; handler
`amdgpu_dpm_thermal_work_handler()` (which itself checks
`adev->pm.dpm_enabled`, but that does not help if work was never
initialized).
### Step 5.4: Reachability
**Record:**
- Requires `CONFIG_DRM_AMDGPU_SI` + `amdgpu.si_support=1` (SI support is
experimental, off by default)
- Requires `amdgpu.dpm=0` module parameter
- Requires thermal IRQ delivery (src_id 230 or 231)
- Not directly userspace-triggerable, but hardware thermal events under
load are realistic
### Step 5.5: Similar patterns
**Record:** Identical unguarded pattern in `kv_dpm_process_interrupt()`
at line 3189–3190 of `kv_dpm.c` — same `amdgpu_dpm == 0` early-return /
`INIT_WORK` split in `kv_dpm_sw_init()`.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE (6.18.44)
### Step 6.1: Buggy code present?
**Record:** **YES.** Lines 7674–7675 still have the unguarded
`schedule_work()`:
```7674:7675:drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
if (queue_thermal)
schedule_work(&adev->pm.dpm.thermal.work);
```
### Step 6.2: Backport complications
**Record:** Clean apply expected — single-line change, no structural
conflicts. File has had minor unrelated churn but this hunk is
untouched.
### Step 6.3: Fix already present?
**Record:** **NO.** `git merge-base --is-ancestor bd018d36171a HEAD`
fails; grep shows no `queue_thermal && amdgpu_dpm` in tree.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/gpu/drm/amd/pm` — **IMPORTANT** (GPU driver / power
management). Affects SI ASIC users on amdgpu, not core kernel.
### Step 7.2: Activity
**Record:** Actively maintained; recent SI powertune and display-timing
fixes in this tree.
---
## PHASE 8: IMPACT AND RISK
### Step 8.1: Who is affected
**Record:** Users of Southern Islands GPUs with experimental amdgpu SI
support enabled and `amdgpu.dpm=0`. Narrow but real population
(debugging, workarounds).
### Step 8.2: Trigger conditions
**Record:** `amdgpu.dpm=0` at module load + thermal IRQ from GPU.
Uncommon parameter combo, but thermal events are normal under GPU load.
### Step 8.3: Failure severity
**Record:** Kernel WARN/oops from scheduling or executing uninitialized
work — **HIGH** (system crash). Not data corruption or security
escalation.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** Prevents crash on a valid module-parameter configuration
- **Risk:** Minimal (one boolean guard matching existing conventions)
- **Ratio:** Favorable for stable
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real bug with clear mechanism (uninitialized work + `schedule_work()`)
- Can cause kernel crash
- One-line, obviously correct fix
- AMDGPU maintainer sign-off
- Buggy code confirmed in v6.18.44; fix not yet applied
- Matches existing `amdgpu_dpm` guards in same file
**AGAINST backport:**
- Narrow trigger: experimental SI support + `dpm=0` + thermal IRQ
- `CONFIG_DRM_AMDGPU_SI` off by default
- No user/syzbot report in commit message
- Sibling `kv_dpm.c` has same bug (out of scope for this commit)
**Unresolved:**
- Full mailing-list review thread (bot-blocked)
- Whether patches 2/3 fix KV/CI separately
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — logic is clear; maintainer
SOB; no Tested-by
2. Fixes a real bug? **PASS** — uninitialized work scheduling
3. Important issue? **PASS** — kernel crash (HIGH, narrow audience)
4. Small and contained? **PASS** — 1 line, 1 file
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** — code exists, clean apply expected
### Step 9.3: Exception categories
**Record:** N/A — standard bug fix, not device-ID/quirk/DT/build/doc
exception.
### Step 9.4: Decision rationale
This is a small, surgical crash fix for a valid `amdgpu.dpm=0`
configuration on SI hardware. The audience is narrow (legacy SI +
experimental amdgpu support), but stable trees routinely take such
driver crash fixes when the change is minimal and clearly correct. The
bug exists in this 6.18.44 tree and the fix applies cleanly.
---
## Verification
- [Phase 1] Parsed commit `bd018d36171a`: subject, body, SOBs from Timur
Kristóf and Alex Deucher; no Fixes/Reported-by/Link tags
- [Phase 2] Diff: 1-line guard `queue_thermal && amdgpu_dpm` before
`schedule_work()` in `si_dpm_process_interrupt()`
- [Phase 2] Read `si_dpm_sw_init()`: IRQ registered at 7783–7788, early
return at 7801–7802 skips `INIT_WORK()` at 7808
- [Phase 2] Read `amdgpu_drv.c`: `amdgpu_dpm` module param at lines 162,
382 (`module_param_named(dpm, ...)`)
- [Phase 3] `git blame -L 7674,7675`: lines present since pre-history
(`^5d324e5159d9e`)
- [Phase 3] `git merge-base --is-ancestor bd018d36171a HEAD`: commit
**NOT** in tree
- [Phase 3] `git log --oneline -20 -- si_dpm.c`: no duplicate fix
- [Phase 3] `git log --author="Timur Kristóf" -10 --
drivers/gpu/drm/amd/pm/`: author active in subsystem
- [Phase 4] `b4 dig -c bd018d36171a`: found v1 at https://patch.msgid.li
nk/20260712173928.259701-1-timur.kristof@gmail.com
- [Phase 4] `b4 dig -a`: patch 1/3 in series
- [Phase 4] `b4 dig -w`: CC'd amd-gfx, Alex Deucher, Mario Limonciello
- [Phase 4] UNVERIFIED: lore/patch.msgid.link thread content (bot
protection)
- [Phase 5] `si_dpm_process_interrupt` wired via
`si_dpm_irq_funcs.process` at line 8155
- [Phase 5] `kv_dpm.c` has identical unguarded pattern at 3189–3190
- [Phase 5] `amdgpu_dpm_thermal_work_handler()` checks `dpm_enabled` but
does not prevent uninitialized-work bug
- [Phase 6] `git describe HEAD`: v6.18.44-2-g1b9e1abadee04; Makefile
6.18.44
- [Phase 6] Buggy code confirmed at si_dpm.c:7674–7675 in working tree
- [Phase 6] `si_dpm.c` includes `amdgpu.h` with `extern int amdgpu_dpm`
— fix compiles
- [Phase 7] `CONFIG_DRM_AMDGPU_SI` in Kconfig: experimental SI support,
off by default
- [Phase 8] Failure mode: crash from uninitialized `schedule_work()` —
severity HIGH, trigger narrow
**YES****Result:** The fix commit `bd018d36171a` is **not** in this tree
(`v6.18.44`), and the bug is still present in `si_dpm.c`.
**Verdict:** **YES** — backport recommended.
With `amdgpu.dpm=0`, thermal IRQ handlers are registered but
`INIT_WORK()` is skipped, so a thermal interrupt can call
`schedule_work()` on an uninitialized work struct and crash the kernel.
The one-line guard (`queue_thermal && amdgpu_dpm`) matches existing
checks in the same file and should apply cleanly to 6.18.y.
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
index ea97276358c0a..39928eb71d669 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
@@ -7690,7 +7690,7 @@ static int si_dpm_process_interrupt(struct amdgpu_device *adev,
break;
}
- if (queue_thermal)
+ if (queue_thermal && amdgpu_dpm)
schedule_work(&adev->pm.dpm.thermal.work);
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amd/display: Fix 8K Mode Not Parsed by EDID
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (10 preceding siblings ...)
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Don't schedule thermal work when queue isn't initialized Sasha Levin
@ 2026-08-31 13:24 ` Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/display: Fix CRC open failure during active rendering Sasha Levin
` (25 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:24 UTC (permalink / raw)
To: patches, stable
Cc: Fangzhi Zuo, Sun peng (Leo) Li, George Zhang, Alex Deucher,
Sasha Levin, harry.wentland, christian.koenig, airlied, simona,
amd-gfx, dri-devel, linux-kernel
From: Fangzhi Zuo <Jerry.Zuo@amd.com>
[ Upstream commit 9b3aa1dec7c364b0d7b171dcc00ab1092e362aef ]
[why]
The 8K120/8K240 timings live in DisplayID extension blocks 2 and 3
of this EDID. The EDID is a 4-block (512-byte) HDMI 2.1 EDID
that uses HF-EEODB.
drm core reads and parses this correctly, but amdgpu rebuilds its own copy.
Only 2 of 4 blocks were copied into sink->dc_edid, that leads to
drm_edid_connector_add_modes() never sees blocks 2 and 3.
[how]
Directly populate edid_blob_ptr with a blob whose length is the full,
and HF-EEODB-aware size.
Reviewed-by: Sun peng (Leo) Li <sunpeng.li@amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Signed-off-by: George Zhang <george.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 11a90eaf5c808ba800249dda0d481c35d0888589)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The branch check finished: commit `11a90eaf5c808` (“Fix 8K Mode Not
Parsed by EDID”) is on `linux-next/master` only, not in the local
`v6.18.44` tree. That matches the earlier finding — the fix is in
mainline development and still needs to be backported to 6.18.y if
selected.
The backport recommendation remains **YES** for this tree.
.../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 20 ++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index d0f770dd0a956..c2de763d621d3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -1031,11 +1031,25 @@ enum dc_edid_status dm_helpers_read_local_edid(
continue;
edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw()
- if (!edid ||
- edid->extensions >= sizeof(sink->dc_edid.raw_edid) / EDID_LENGTH)
+ /*
+ * Use the length of the EDID property blob populated by
+ * drm_edid_connector_update() above. It reflects the true number
+ * of EDID blocks, including any HDMI Forum EDID Extension Override
+ * Data Block (HF-EEODB) count, which the raw byte 0x7e extension
+ * count can hide (e.g. HDMI 8K sinks).
+ */
+ if (!edid || !connector->edid_blob_ptr ||
+ connector->edid_blob_ptr->length > sizeof(sink->dc_edid.raw_edid))
return EDID_BAD_INPUT;
- sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1);
+ /*
+ * FIXME: amdgpu_dm today does not consider the HF-EEODB, which
+ * may contain additional mode info for sinks. This is a
+ * workaround until dc_edid is refactored out from DC into
+ * amdgpu_dm's ownership, allowing amdgpu_dm to use drm_edid
+ * directly
+ */
+ sink->dc_edid.length = connector->edid_blob_ptr->length;
memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length);
/* We don't need the original edid anymore */
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] drm/amd/display: Fix CRC open failure during active rendering
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (11 preceding siblings ...)
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18] drm/amd/display: Fix 8K Mode Not Parsed by EDID Sasha Levin
@ 2026-08-31 13:24 ` Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] drm/amdgpu: cap ATOM command table nesting depth Sasha Levin
` (24 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:24 UTC (permalink / raw)
To: patches, stable
Cc: Tom Chung, Ray Wu, James Lin, Daniel Wheeler, Alex Deucher,
Sasha Levin, harry.wentland, sunpeng.li, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Tom Chung <chiahsuan.chung@amd.com>
[ Upstream commit 5eb2fdafeb6f4a442643b77a21a4c9e70586a146 ]
[Why]
Opening the CRC data file during active rendering can fail with -EINVAL.
The wait for commit->hw_done returns remaining jiffies on success, but
the CRC path was treating that as an error.
[How]
Handle wait_for_completion_interruptible_timeout() correctly:
positive return as success, 0 as timeout, and negative as error.
Reviewed-by: Ray Wu <ray.wu@amd.com>
Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
Signed-off-by: James Lin <pinglei.lin@amd.com>
Tested-by: Daniel 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:
The 6.18.y backport check found no “CRC open failure” commit in
`v6.18..HEAD`. The fix exists only as candidate `6ad40a4a964c0` on the
`autosel` branch and is not in 6.18.43 HEAD — the buggy `if (ret)` code
is still there. Verdict remains **YES**.
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index e20aa74380665..596a97092e0dd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -584,8 +584,13 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
*/
ret = wait_for_completion_interruptible_timeout(
&commit->hw_done, 10 * HZ);
- if (ret)
+ if (ret < 0)
+ goto cleanup;
+
+ if (ret == 0) {
+ ret = -ETIMEDOUT;
goto cleanup;
+ }
}
enable = amdgpu_dm_is_valid_crc_source(source);
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: cap ATOM command table nesting depth
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (12 preceding siblings ...)
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/display: Fix CRC open failure during active rendering Sasha Levin
@ 2026-08-31 13:25 ` Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] drm/amd/ras: reset CPER ring on corrupt entry size Sasha Levin
` (23 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:25 UTC (permalink / raw)
To: patches, stable
Cc: Candice Li, Tao Zhou, Alex Deucher, Sasha Levin, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Candice Li <candice.li@amd.com>
[ Upstream commit 27ef1795bc4e47cae838e0a3ced531c549f9b23d ]
Cap nesting at 32 levels with execute_depth and
return -ELOOP when exceeded.
Signed-off-by: Candice Li <candice.li@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:
# Stable Backport Analysis: `drm/amdgpu: cap ATOM command table nesting
depth`
**Local tree:** `v6.18.44` (Makefile: 6.18.44)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amdgpu]` `[cap]` — Limit ATOM BIOS command-table
recursion depth to prevent unbounded `ATOM_OP_CALLTABLE` nesting.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Candice Li `<candice.li@amd.com>` (author)
- **Reviewed-by:** Tao Zhou `<tao.zhou1@amd.com>` (AMD reviewer)
- **Signed-off-by:** Alex Deucher `<alexander.deucher@amd.com>` (amdgpu
maintainer)
- **No** Fixes:, Reported-by:, Tested-by:, Link:, or Cc: stable tags
- **Notable:** Patch is labeled `[PATCH 2/4]` on amd-gfx (May 2026
security-hardening series); this hunk is self-contained in
`atom.c`/`atom.h`
### Step 1.3: Body analysis
**Record:**
- **Bug:** Unbounded recursion via `ATOM_OP_CALLTABLE` →
`amdgpu_atom_execute_table_locked()` can exhaust the kernel stack.
- **Symptom:** Kernel stack overflow (oops/panic) when VBIOS command
tables nest deeply or cycle.
- **Fix:** Track `execute_depth` in `atom_context`, cap at 32, return
`-ELOOP` when exceeded.
- **Root cause:** `atom_op_calltable()` recursively calls
`amdgpu_atom_execute_table_locked()` with no depth limit; present
since amdgpu’s initial atom interpreter (2015).
### Step 1.4: Hidden bug fix?
**Record:** Yes — despite “cap” wording, this is a defensive bug fix
preventing kernel stack overflow, not a feature or refactor.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- `drivers/gpu/drm/amd/amdgpu/atom.c`: +11 lines
- `drivers/gpu/drm/amd/amdgpu/atom.h`: +3 lines
- **Total:** 14 lines added, 0 removed
- **Functions:** `amdgpu_atom_execute_table_locked()`; `struct
atom_context` extended
- **Scope:** Single-subsystem, surgical, two-file fix
### Step 2.2: Code flow change
**Record:**
- **Hunk 1 (define):** Adds `ATOM_EXECUTE_MAX_DEPTH 32` with comment
explaining stack-overflow prevention.
- **Hunk 2 (entry):** Before table execution, checks `ctx->execute_depth
>= 32`, logs `DRM_ERROR`, returns `-ELOOP`; otherwise increments
depth.
- **Hunk 3 (exit):** On all normal/error exits through `free:`,
decrements `execute_depth`.
- **Hunk 4 (struct):** Adds `unsigned int execute_depth` to
`atom_context`.
- **Before:** Unlimited recursive `calltable` op → stack growth until
overflow.
- **After:** Depth-limited recursion; excess nesting returns error that
propagates via existing `ctx->abort` handling.
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Memory safety / kernel crash prevention (unbounded stack
recursion)
- **Mechanism:** `atom_op_calltable()` at line 642 calls
`amdgpu_atom_execute_table_locked()` recursively. A malicious,
corrupt, or cyclic VBIOS can nest arbitrarily deep. Each frame
allocates locals and may call further atom ops on the stack. No prior
limit existed (`debug_depth` is debug-print-only).
### Step 2.4: Fix quality
**Record:**
- **Quality:** High — standard recursion-depth counter pattern;
increment on entry, decrement on all `free:` paths.
- **Regression risk:** Very low. Real VBIOS tables do not nest anywhere
near 32 levels. On limit hit, `-ELOOP` → `ctx->abort = true` →
controlled `-EINVAL` exit (existing path), not panic.
- **Note:** `execute_depth` is not reset in
`amdgpu_atom_execute_table()`, but mutex serialization and balanced
inc/dec within each execution keep it at 0 between top-level calls.
`atom_context` is `kzalloc()`’d, so field starts at 0.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:**
- `atom_op_calltable()` introduced in `d38ceaf99ed01` (“drm/amdgpu: add
core driver (v4)”, 2015-04-20).
- Recursive call to `amdgpu_atom_execute_table_locked()` added in
`4630d5031cd87` (“drm/amdgpu: check PS, WS index”, 2024-01-11).
- Unbounded recursion bug present throughout amdgpu’s lifetime in this
tree.
### Step 3.2: Fixes: tag
**Record:** N/A — no Fixes: tag in commit message.
### Step 3.3: Related file history
**Record:** Recent `atom.c` fixes in this tree include:
- `cc9a8e238e42c` — kcalloc NULL check for WS buffer (OOM path)
- `e5f7e4e0a445f` — vbios NULL offset workaround
- `7bfd16d0ec374` — `last_jump_jiffies` initialization
- No prior nesting-depth or recursion-limit fix found.
### Step 3.4: Author context
**Record:** Candice Li is an active AMD amdgpu contributor. Alex Deucher
(maintainer) signed off. Part of a 4-patch May 2026 hardening series
(RAS bounds, atom depth cap, PSP fw validation).
### Step 3.5: Dependencies
**Record:** Standalone — patch 2/4 needs no other series members. No new
APIs, no prerequisite commits. `git apply --check` confirms clean apply
to this tree.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- **URL:** https://lists.freedesktop.org/archives/amd-
gfx/2026-May/144646.html
- **Series:** Patches 1/4 (RAS CPER bounds), 2/4 (this commit), 4/4 (PSP
fw_pri_buf validation); patches are independent.
- **Review feedback:** No NAKs or stable nominations found in fetched
thread; patch is minimal with maintainer sign-off.
- **b4 dig:** Failed to match commit `27ef1795bc4e` on lore (amd-gfx
list, not lore.kernel.org).
### Step 4.2: Reviewers
**Record:** Reviewed-by Tao Zhou (AMD); Signed-off-by Alex Deucher
(amdgpu maintainer). Submitted to amd-gfx@lists.freedesktop.org.
### Step 4.3: Bug reports
**Record:** No Reported-by:, syzbot, or bugzilla links. Issue identified
proactively as part of security hardening (comment explicitly cites
stack overflow).
### Step 4.4: Related patches
**Record:** Sibling patches address separate bounds-check issues
(userspace RAS ioctl, PSP firmware copy size). Not required for this
fix.
### Step 4.5: Stable list
**Record:** lore.kernel.org/stable search blocked (bot protection). No
stable-list discussion verified.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `amdgpu_atom_execute_table_locked()`, `atom_op_calltable()`,
`amdgpu_atom_execute_table()`.
### Step 5.2: Callers
**Record:** `amdgpu_atom_execute_table()` is widely used across amdgpu:
- Display: `atombios_encoders.c`, `atombios_crtc.c`, `atombios_dp.c`,
`command_table.c`
- PM: `ppatomctrl.c`, `ppatomfwctrl.c`, `smu_v11_0.c`, `smu_v12_0.c`
- Init: `amdgpu_atombios.c`, `amdgpu_atomfirmware.c`, `atom.c`
(`ATOM_CMD_INIT`)
- Called during GPU probe, mode set, power management, and display
hotplug — common operational paths.
### Step 5.3: Callees
**Record:** Recursive path: `atom_op_calltable()` →
`amdgpu_atom_execute_table_locked()`. Uses `kcalloc()` for workspace
(heap), but each stack frame still carries locals and interpreter state.
### Step 5.4: Reachability
**Record:** Triggered when amdgpu parses/executes VBIOS ATOM command
tables during normal driver operation (probe, display, PM). VBIOS
content comes from GPU ROM; can also be attacker-influenced via VFIO GPU
passthrough (guest-supplied VBIOS) or root-level VBIOS flashing. Not a
direct unprivileged-syscall path, but runs in kernel context on widely
used hardware.
### Step 5.5: Similar patterns
**Record:** No equivalent `execute_depth` / `ATOM_EXECUTE_MAX_DEPTH` in
radeon or other drm atom interpreters in this tree. `debug_depth` in
`atom.c` is unrelated (SDEBUG formatting only).
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE (v6.18.44)
### Step 6.1: Buggy code present?
**Record:** **Yes.** `atom_op_calltable()` at lines 632–646 recursively
calls `amdgpu_atom_execute_table_locked()` with no depth check.
`execute_depth` / `ATOM_EXECUTE_MAX_DEPTH` absent (`grep` returns no
matches).
### Step 6.2: Backport complications
**Record:** **Clean apply expected.** `git apply --check` succeeded with
no conflicts. File structure matches patch context.
### Step 6.3: Related fixes already present?
**Record:** **No.** `git log -S "execute_depth"` on amdgpu returns
empty. Fix not already in tree.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** **drivers/gpu/drm/amd/amdgpu** — IMPORTANT. Affects all
amdgpu GPU users on probe, display, and PM paths.
### Step 7.2: Subsystem activity
**Record:** Actively maintained; recent atom.c fixes (2024–2025) show
ongoing hardening of the interpreter.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** All systems with `CONFIG_DRM_AMDGPU` and amdgpu-loaded AMD
GPUs. Config-specific but affects a large user base (desktops, servers,
laptops, cloud GPUs).
### Step 8.2: Trigger conditions
**Record:** VBIOS ATOM command table with `calltable` nesting >32 (or
infinite cycle). Uncommon with legitimate AMD VBIOS, but possible with
corrupt ROM, malicious passthrough VBIOS, or pathological tables.
Requires GPU present and atom table execution.
### Step 8.3: Failure mode severity
**Record:** **CRITICAL** without fix — kernel stack overflow →
oops/panic, potential security implications. **MEDIUM** with fix —
controlled error return, display/PM operation may fail but system stays
up.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH — prevents kernel crash from unbounded recursion in
widely-used code path.
- **Risk:** VERY LOW — 14-line defensive bound, maintainer-reviewed, no
API changes.
- **Ratio:** Strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Fixes real unbounded-recursion bug present since amdgpu inception
- Prevents kernel stack overflow (crash-class issue)
- Small (14 lines), obviously correct, maintainer-signed
- Applies cleanly to v6.18.44
- Standalone — no series dependencies
- Graceful degradation on limit hit (existing abort path)
**AGAINST backport:**
- No user/syzbot report in commit message
- Trigger requires pathological VBIOS (uncommon on bare metal)
- Not directly reachable from unprivileged userspace without GPU
passthrough or root
**Unresolved:** Whether any legitimate production VBIOS exceeds 32
nesting levels (unverified; considered very unlikely given AMD’s own
32-level cap choice).
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — standard depth counter;
Reviewed-by + maintainer SOB; logic verifiable by inspection.
2. Fixes a real bug? **PASS** — unbounded recursion can overflow kernel
stack.
3. Important issue? **PASS** — kernel crash / potential security impact
(CRITICAL severity).
4. Small and contained? **PASS** — 14 lines, 2 files.
5. No new features/APIs? **PASS** — internal defensive bound only.
6. Can apply to local tree? **PASS** — buggy code present, patch applies
cleanly.
### Step 9.3: Exception categories
**Record:** N/A (not device ID, quirk, DT, build, or docs). Qualifies as
a critical bug-fix.
### Step 9.4: Decision rationale
For **v6.18.44**, the vulnerable unbounded-recursion code is present and
the fix is absent. The patch is minimal, self-contained, maintainer-
approved, and prevents a kernel stack overflow in a core amdgpu code
path used during normal GPU operation. Trigger rarity does not outweigh
crash severity for stable trees.
---
## Verification
- [Phase 1] Parsed subject, tags, body; identified as stack-overflow
prevention fix
- [Phase 1] Confirmed patch is `[PATCH 2/4]` but self-contained
- [Phase 2] Diff analysis: +14 lines in `atom.c`/`atom.h`; depth check
at entry, decrement at `free:`
- [Phase 2] Verified `atom_op_calltable()` recursive call at line 642
- [Phase 2] Verified `debug_depth` is debug-only (lines 95, 1259, 1282),
not a safety limit
- [Phase 3] `git blame`: `atom_op_calltable` from 2015 (`d38ceaf99ed01`)
- [Phase 3] `git log -S "execute_depth"`: empty — fix not in tree
- [Phase 3] `git log --oneline -20 -- atom.c`: recent hardening commits,
no depth cap
- [Phase 3] `git apply --check`: patch applies cleanly
- [Phase 4] WebFetch amd-gfx/144646.html: original submission found
- [Phase 4] WebFetch amd-gfx/144645.html: patch 1/4 is independent RAS
fix
- [Phase 4] `b4 dig -c 27ef1795bc4e`: no lore match (amd-gfx list)
- [Phase 4] lore.kernel.org/stable: blocked by bot protection —
UNVERIFIED
- [Phase 5] `grep amdgpu_atom_execute_table`: 30+ call sites across
display/PM/init
- [Phase 5] Traced recursion: `atom_op_calltable` →
`amdgpu_atom_execute_table_locked`
- [Phase 5] Verified `-ELOOP` propagates via `ctx->abort = true` (lines
643–645)
- [Phase 6] `git describe HEAD`: v6.18.44
- [Phase 6] `grep execute_depth|ATOM_EXECUTE_MAX_DEPTH`: no matches —
bug present, fix absent
- [Phase 6] `amdgpu_atom_parse` uses `kzalloc` (line 1527) —
`execute_depth` starts at 0
- [Phase 6] `mutex_lock` in `amdgpu_atom_execute_table` (line 1295) —
serializes execution
- [Phase 8] Failure mode: stack overflow without fix = CRITICAL; with
fix = controlled error
**YES**The background checks finished and match the earlier analysis:
- **Related-commit search** — No amdgpu fix for ATOM nesting depth or
`ATOM_EXECUTE` in this tree; only unrelated “stack overflow” hits
elsewhere.
- **Fix-already-present check** — `execute_depth` /
`ATOM_EXECUTE_MAX_DEPTH` never appear in amdgpu history here; the
vulnerable recursive `atom_op_calltable()` path is still present on
**v6.18.44**.
That supports the **YES** backport verdict: the bug exists locally, the
fix is missing, and the patch should apply cleanly.
drivers/gpu/drm/amd/amdgpu/atom.c | 11 +++++++++++
drivers/gpu/drm/amd/amdgpu/atom.h | 3 +++
2 files changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index 7a063e44d4298..639649ef6dd03 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -59,6 +59,9 @@
#define ATOM_CMD_TIMEOUT_SEC 20
+/* Limit ATOM command table recursion (calltable) to avoid kernel stack overflow. */
+#define ATOM_EXECUTE_MAX_DEPTH 32
+
typedef struct {
struct atom_context *ctx;
uint32_t *ps, *ws;
@@ -1229,6 +1232,13 @@ static int amdgpu_atom_execute_table_locked(struct atom_context *ctx, int index,
if (!base)
return -EINVAL;
+ if (ctx->execute_depth >= ATOM_EXECUTE_MAX_DEPTH) {
+ DRM_ERROR("atombios command table nesting exceeded limit (%u)\n",
+ ATOM_EXECUTE_MAX_DEPTH);
+ return -ELOOP;
+ }
+ ctx->execute_depth++;
+
len = CU16(base + ATOM_CT_SIZE_PTR);
ws = CU8(base + ATOM_CT_WS_PTR);
ps = CU8(base + ATOM_CT_PS_PTR) & ATOM_CT_PS_MASK;
@@ -1285,6 +1295,7 @@ static int amdgpu_atom_execute_table_locked(struct atom_context *ctx, int index,
free:
if (ws)
kfree(ectx.ws);
+ ctx->execute_depth--;
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.h b/drivers/gpu/drm/amd/amdgpu/atom.h
index 825ff28731f52..bb3d9eb7eb6b5 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.h
+++ b/drivers/gpu/drm/amd/amdgpu/atom.h
@@ -153,6 +153,9 @@ struct atom_context {
uint8_t vbios_ver_str[STRLEN_NORMAL];
uint8_t date[STRLEN_NORMAL];
uint8_t build_num[STRLEN_NORMAL];
+
+ /* Nesting depth for ATOM_OP_CALLTABLE */
+ unsigned int execute_depth;
};
extern int amdgpu_atom_debug;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amd/ras: reset CPER ring on corrupt entry size
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (13 preceding siblings ...)
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] drm/amdgpu: cap ATOM command table nesting depth Sasha Levin
@ 2026-08-31 13:25 ` Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: Use system unbound workqueue for soft IH ring Sasha Levin
` (22 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:25 UTC (permalink / raw)
To: patches, stable
Cc: Xiang Liu, Stanley.Yang, Tao Zhou, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Xiang Liu <xiang.liu@amd.com>
[ Upstream commit 4d695e66d7027a0c78302e47ac76293675fbbb4d ]
When CPER ring overflow handling advances the read pointer, it trusts the
parsed entry size from the current ring contents. Corrupt CPER data can
produce an entry size that does not advance rptr after dword conversion
and pointer masking.
In that case the recovery loop keeps testing the same location while
holding the CPER ring mutex. This can hang the worker that is writing the
next CPER record.
Detect a no-progress rptr update and reset the CPER ring to an empty
state instead. This drops the corrupt contents and lets the writer leave
the recovery path without spinning.
Signed-off-by: Xiang Liu <xiang.liu@amd.com>
Reviewed-by: Stanley.Yang <Stanley.Yang@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:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
Record: `[drm/amd/ras] [reset] reset CPER ring on corrupt entry size` —
subsystem is AMDGPU RAS/CPER; action is a defensive recovery/reset in
response to corrupt data.
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Xiang Liu <xiang.liu@amd.com>` (author)
- `Reviewed-by: Stanley.Yang <Stanley.Yang@amd.com>`
- `Reviewed-by: Tao Zhou <tao.zhou1@amd.com>`
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`, or
`Tested-by:` tags
- Notable: AMD subsystem reviewers and maintainer sign-off; no syzbot or
user bug report
**Step 1.3 — Body analysis**
Record:
- **Bug:** On CPER ring overflow, the recovery loop advances `rptr`
using parsed entry sizes from ring contents. Corrupt CPER data can
yield an entry size that does not advance `rptr` after dword
conversion and masking.
- **Symptom:** Recovery loop spins forever at the same location while
holding `cper.ring_lock`, hanging the worker writing the next CPER
record.
- **Fix:** Detect no-progress `rptr` updates and reset the ring to empty
rather than spinning.
- **Root cause:** Trusting corrupt in-ring metadata during overflow
recovery.
**Step 1.4 — Hidden bug fix?**
Record: Yes. Despite “reset” wording, this is a hang/deadlock-class bug
fix in error-recovery code, not a feature addition.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
Record:
- File: `drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c` (+12 net lines)
- Function modified: `amdgpu_cper_ring_write()`
- Scope: single-file, surgical fix in overflow recovery path
**Step 2.2 — Code flow per hunk**
Record:
- **Before:** `rptr += (ent_sz >> 2); rptr &= ring->ptr_mask;` always
runs; if `ent_sz` is 0, <4, or a multiple of ring circumference,
`rptr` may not move.
- **After:** Compute `next_rptr` only when `ent_sz >= sizeof(u32)`; if
`next_rptr == rptr`, reset ring (`rptr = wptr`, update `count_dw`,
`goto out_unlock`); otherwise advance normally.
- **Path affected:** CPER ring overflow recovery inside
`amdgpu_cper_ring_write()`, while `ring_lock` is held.
**Step 2.3 — Bug mechanism**
Record:
- Category: logic/correctness bug → infinite loop with mutex held (soft
hang)
- Mechanism: corrupt `record_length` or garbage between headers can make
`(rptr + (ent_sz >> 2)) & ptr_mask == rptr`; old code never exits the
`do { ... } while (!amdgpu_cper_is_hdr(...))` loop
**Step 2.4 — Fix quality**
Record:
- Fix is minimal and obviously correct: no-progress detection is
standard for ring-buffer parsers
- Recovery (drop corrupt contents, reset pointers) is preferable to
infinite spin
- Low regression risk: only triggers on already-corrupt overflow state
- Trade-off: loses corrupt CPER records, but that is acceptable vs.
permanent hang
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
Record: Overflow recovery loop introduced in `a6d9d192903ea`
(“drm/amdgpu: add data write function for CPER ring”, 2025-01-22).
Present in this tree at lines 507–515. First appeared in tag `v6.15`.
**Step 3.2 — Fixes: tag**
Record: Not applicable — no `Fixes:` tag in commit message.
**Step 3.3 — Related file history**
Record: Related prior fix `d6f9bbce18762` (“Fix computation for remain
size of CPER ring”) already in this tree; it fixed a *different*
infinite-loop cause in the same function. `8e0d1edb5c167` added missing
lock protection and was nominated for stable (`Cc:
stable@vger.kernel.org`). CPER subsystem landed starting `92d5d2a09de16`
in v6.15.
**Step 3.4 — Author context**
Record: Xiang Liu authored multiple CPER fixes including `d6f9bbce18762`
(same infinite-loop class). Reviews from AMD RAS engineers and
maintainer Alex Deucher.
**Step 3.5 — Dependencies**
Record: Standalone fix; no series markers, no prerequisite commits
referenced. Assumes existing `amdgpu_cper_ring_write()` overflow path —
present in this tree.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
Record: `b4 dig -c d5e59c24d907d` failed (commit not in local history).
`b4 shazam` found no matching message-id. lore.kernel.org search blocked
by bot protection. **UNVERIFIED:** full review-thread content.
**Step 4.2 — Reviewers**
Record: **UNVERIFIED** via `b4 dig -w` (commit hash unavailable
locally). Commit message lists Stanley.Yang, Tao Zhou, Alex Deucher.
**Step 4.3 — Bug report**
Record: Not applicable — no `Reported-by:` or `Link:` tags.
**Step 4.4 — Related patches**
Record: Complements `d6f9bbce18762` (already in tree) which fixed
another overflow infinite-loop cause. This patch addresses corrupt-
entry-size no-progress separately.
**Step 4.5 — Stable list history**
Record: **UNVERIFIED** — lore stable search inaccessible. Prior CPER
lock fix `8e0d1edb5c167` was explicitly CC'd to stable.
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
Record: `amdgpu_cper_ring_write()` (modified); uses
`amdgpu_cper_ring_get_ent_sz()`, `amdgpu_cper_is_hdr()`.
**Step 5.2 — Callers**
Record: `amdgpu_cper_ring_write()` called from:
- `amdgpu_cper_generate_ue_record()` — uncorrectable GPU errors
- `amdgpu_cper_generate_bp_threshold_record()` — bad-page threshold
(also from `amdgpu_ras_eeprom.c`)
- `amdgpu_cper_generate_ce_records()` — corrected errors
- `amdgpu_virt.c` — SR-IOV guest CPER dump path
All are RAS/error-reporting paths on ACA-enabled or SR-IOV CPER-enabled
devices.
**Step 5.3 — Callees**
Record: `mutex_lock/unlock(&ring->adev->cper.ring_lock)`,
`amdgpu_cper_ring_get_ent_sz()`, `memcpy()`, pointer masking.
**Step 5.4 — Reachability**
Record: Triggered when CPER ring overflows during error-record writes.
Call chain: ACA bank update (`aca_banks_update` →
`aca_banks_generate_cper` → `amdgpu_cper_generate_*` →
`amdgpu_cper_ring_write`). Reachable during real GPU RAS events — the
same conditions that fill the CPER ring. Not a syscall path, but
triggered by hardware error handling that must not hang.
**Step 5.5 — Similar patterns**
Record: Prior fix `d6f9bbce18762` explicitly described “unbreakable
while cycle when CPER ring overflow” in the same function — same bug
class, different root cause.
---
## Phase 6: Cross-Reference Against Local Tree
**Step 6.1 — Buggy code present?**
Record: **Yes.** Local tree is `v6.18.44` (Makefile: 6.18.44). Buggy
code at `amdgpu_cper.c:510-511` (`rptr += (ent_sz >> 2)` without no-
progress check). CPER code is an ancestor of HEAD; first CPER commits
tagged `v6.15`.
**Step 6.2 — Backport complications**
Record: Expected **clean apply with possible minor fuzz** — the
`amdgpu_cper_ring_write()` hunk matches this tree exactly; upstream diff
context in `amdgpu_cper_ring_get_ent_sz()` differs slightly (local uses
inline `chdr` check vs. `amdgpu_cper_is_hdr()` in upstream diff), but
the fix hunk is independent.
**Step 6.3 — Related fixes already present?**
Record: `d6f9bbce18762` (different overflow loop fix) and
`8e0d1edb5c167` (lock fix) are in tree. This specific corrupt-entry-size
hang is **not** yet fixed.
---
## Phase 7: Subsystem and Maintainer Context
**Step 7.1 — Subsystem criticality**
Record: `drivers/gpu/drm/amd/amdgpu` — IMPORTANT (AMD GPU RAS/CPER error
reporting). Not universal like mm/net, but critical for affected AMD GPU
users with ACA/RAS enabled.
**Step 7.2 — Activity**
Record: CPER code is actively developed (20 commits on `amdgpu_cper.c`);
subsystem is new (v6.15+) and still receiving bug fixes.
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
Record: AMD GPU systems with CPER enabled (`amdgpu_aca_is_enabled()` or
`amdgpu_sriov_ras_cper_en()`). Config/driver-specific, but includes
production RAS workloads and SR-IOV hosts.
**Step 8.2 — Trigger conditions**
Record: CPER ring overflow **and** corrupt/non-advancing entry size in
ring buffer. Plausible when the ring already contains damaged data from
hardware errors or partial overwrites. Not everyday, but realistic in
the exact failure mode CPER exists to handle.
**Step 8.3 — Failure mode severity**
Record: **CRITICAL** — infinite loop with `cper.ring_lock` held; CPER
writer thread/worker hangs permanently; subsequent CPER records cannot
be written; RAS error logging stalls during hardware fault scenarios.
**Step 8.4 — Risk/benefit**
Record:
- **Benefit:** HIGH — prevents permanent hang in RAS error path during
overflow recovery
- **Risk:** LOW — ~15 lines, defensive reset only on detected no-
progress, reviewed by AMD maintainers
- **Ratio:** Strong benefit, minimal risk
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence compile**
FOR backport:
- Real infinite-loop hang with mutex held
- Affects RAS error reporting on AMD GPUs with CPER
- Small, surgical, obviously correct fix
- Buggy code present since v6.15, present in this v6.18.44 tree
- Prior related infinite-loop fix already backported-worthy and in tree
- AMD reviewer + maintainer sign-off
AGAINST backport:
- No syzbot/user bug report (weaker impact evidence, but mechanism is
clear)
- Only affects CPER-enabled AMD GPUs (narrower audience)
- Lore review thread not verified
UNRESOLVED:
- Full mailing-list review discussion
- Whether any reviewer explicitly nominated for stable
**Step 9.2 — Stable rules checklist**
1. Obviously correct and tested? **PASS** — logic is clear; reviewed by
AMD engineers; no Tested-by
2. Fixes a real bug? **PASS** — infinite loop on corrupt overflow
recovery
3. Important issue? **PASS** — worker hang during RAS error handling
(CRITICAL)
4. Small and contained? **PASS** — one file, ~15 lines
5. No new features/APIs? **PASS** — defensive recovery only
6. Can apply to local tree? **PASS** — target code exists; fix hunk
matches
**Step 9.3 — Exception categories**
Record: Not a device-ID/quirk/DT/docs/build fix. Qualifies as a critical
bug fix on its own merits.
**Step 9.4 — Decision rationale**
For this **v6.18.44** tree, the AMDGPU CPER ring overflow recovery code
exists and contains the described infinite-loop bug. The fix prevents a
permanent hang in RAS error logging when corrupt ring data prevents
`rptr` advancement — exactly the scenario CPER is meant to survive. The
patch is small, self-contained, and follows the same pattern as the
already-merged `d6f9bbce18762` overflow-loop fix.
---
## Verification
- [Phase 1] Parsed commit message and tags from user-provided diff
- [Phase 2] Analyzed diff: `amdgpu_cper_ring_write()` overflow loop
change
- [Phase 3] `git describe HEAD` → `v6.18.44`; Makefile confirms 6.18.44
- [Phase 3] `git blame -L 507,516` → buggy loop from `a6d9d192903ea`
(2025-01-22)
- [Phase 3] `git tag --contains 92d5d2a09de16` → CPER introduced in
`v6.15`
- [Phase 3] `git show d6f9bbce18762` → related prior infinite-loop fix
in same function, already in tree
- [Phase 3] `git log --oneline -20 -- amdgpu_cper.c` → CPER subsystem
history reviewed
- [Phase 4] `b4 dig -c d5e59c24d907d` → no match (commit not in local
repo)
- [Phase 4] `b4 shazam -s 'reset CPER ring on corrupt entry size'` →
message-id not known
- [Phase 4] lore.kernel.org fetch → blocked by Anubis bot protection
- [Phase 4] Workspace `*.mbx` grep → no matching thread found
- [Phase 5] `grep amdgpu_cper_ring_write` → 4 call sites in
`amdgpu_cper.c`, `amdgpu_virt.c`
- [Phase 5] Traced `aca_banks_update` → `aca_banks_generate_cper` →
`amdgpu_cper_generate_*` → `amdgpu_cper_ring_write`
- [Phase 6] Read `amdgpu_cper.c:466-521` → buggy code confirmed present,
fix absent
- [Phase 6] `git merge-base --is-ancestor 4d614ce8ffd75 HEAD` → CPER
ring code is in this tree
- [Phase 6] Patch apply via `git apply --check` → failed on upstream
context mismatch in unrelated hunk; target `amdgpu_cper_ring_write()`
hunk verified identical by direct file read
- [Phase 7] `amdgpu_cper_init()` requires `amdgpu_aca_is_enabled()` or
`amdgpu_sriov_ras_cper_en()` — verified in source
- [Phase 8] Confirmed mutex held across infinite loop (`mutex_lock` at
line 481, loop at 507-515, `mutex_unlock` at 520)
**YES**The background search finished: the fix commit **is not in this
tree** (`v6.18.44`). `git log --grep='reset CPER ring'` and
`--grep='corrupt entry size'` found nothing; Xiang Liu’s other CPER
commits (including `d6f9bbce18762`, a related overflow infinite-loop
fix) are present, but not this one.
The buggy overflow-recovery loop is still in `amdgpu_cper.c` at lines
510–511. This patch should be backported here: it prevents an infinite
spin with `cper.ring_lock` held when corrupt CPER ring data doesn’t
advance `rptr` during overflow recovery — a hang in the RAS error-
reporting path on ACA/SR-IOV CPER-enabled AMD GPUs.
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
index 425a3e5643608..2694facb06c73 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
@@ -465,7 +465,7 @@ static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count)
{
- u64 pos, wptr_old, rptr;
+ u64 pos, wptr_old, rptr, next_rptr;
int rec_cnt_dw = count >> 2;
u32 chunk, ent_sz;
u8 *s = (u8 *)src;
@@ -506,9 +506,19 @@ void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count)
do {
ent_sz = amdgpu_cper_ring_get_ent_sz(ring, pos);
-
- rptr += (ent_sz >> 2);
- rptr &= ring->ptr_mask;
+ next_rptr = rptr;
+ if (ent_sz >= sizeof(u32))
+ next_rptr = (rptr + (ent_sz >> 2)) & ring->ptr_mask;
+
+ if (next_rptr == rptr) {
+ /* Corrupt entry size, reset the ring to avoid an infinite loop. */
+ rptr = ring->wptr;
+ *ring->rptr_cpu_addr = rptr;
+ ring->count_dw = (ring->ring_size - 4) >> 2;
+ goto out_unlock;
+ }
+
+ rptr = next_rptr;
*ring->rptr_cpu_addr = rptr;
pos = rptr;
@@ -517,6 +527,8 @@ void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count)
if (ring->count_dw >= rec_cnt_dw)
ring->count_dw -= rec_cnt_dw;
+
+out_unlock:
mutex_unlock(&ring->adev->cper.ring_lock);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: Use system unbound workqueue for soft IH ring
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (14 preceding siblings ...)
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] drm/amd/ras: reset CPER ring on corrupt entry size Sasha Levin
@ 2026-08-31 13:26 ` Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18] drm/amdgpu/userq: pin mqd and fw object bo to avoid eviction Sasha Levin
` (21 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:26 UTC (permalink / raw)
To: patches, stable
Cc: Timur Kristóf, Tvrtko Ursulin, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Timur Kristóf <timur.kristof@gmail.com>
[ Upstream commit ba2977dcce72127986fbad76c4c67f134e2f69ae ]
Allow the kernel to dispatch the soft IH work on other CPUs.
Otherwise it can happen that the soft IH ring fills up
before it actually starts processing anything, which
can easily happen with retry page faults, in which case
the CP repeatedly spams the CPU with a lot of interrupts.
This significantly improves retry page fault handling on
GPUs that don't have the filter CAM and must rely on
software based filtering.
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 3cdff3c8b93c2834977224d9c2b201fc334dd184)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: drm/amdgpu: Use system unbound workqueue for
soft IH ring
**Local tree:** `v6.18.44` (Makefile: 6.18.44)
**Fix commit:** `3cdff3c8b93c` (on `linux-next/master`, **not** an
ancestor of current HEAD — bug still present locally)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Parse subject line
**Record:** `[drm/amdgpu]` — no explicit verb; implied **fix/improve** —
**Use system unbound workqueue for soft IH ring**
### Step 1.2: Parse commit message tags
**Record:**
- **Reviewed-by:** Tvrtko Ursulin \<tvrtko.ursulin@igalia.com\>
- **Signed-off-by:** Timur Kristóf, Alex Deucher
- **No** Fixes:, Reported-by:, Tested-by:, Acked-by:, Link:, Cc:
stable@vger.kernel.org
- Notable: Reviewed-by from Igalia amdgpu contributor; no syzbot/user
bug report
### Step 1.3: Analyze commit body
**Record:**
- **Bug:** Soft IH ring can fill before its work item runs; CP floods
the CPU with interrupts during retry page faults.
- **Symptom:** Soft IH ring overflow / interrupt storm; degraded or
broken retry page fault handling on GPUs without hardware filter CAM
(software filtering only).
- **Root cause (author):** `schedule_work()` dispatches on a CPU-bound
workqueue; work stays pinned on the IRQ CPU and cannot run while that
CPU is saturated with interrupts.
- **Fix:** `queue_work(system_unbound_wq, ...)` allows processing on
another CPU.
- **Version info:** None in message.
### Step 1.4: Detect hidden bug fixes
**Record:** **Yes — functional bug fix disguised as scheduling
improvement.** Ring fill-up before processing means dropped interrupt
vectors and failed page-fault handling, not merely slower performance.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory changes
**Record:**
- **Files:** `drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c` (+1 / −1)
- **Function:** `amdgpu_irq_delegate()`
- **Scope:** Single-file, single-line surgical fix
### Step 2.2: Code flow change
**Record:**
- **Before:** `schedule_work(&adev->irq.ih_soft_work)` → queues on
`system_wq` (CPU-bound).
- **After:** `queue_work(system_unbound_wq, &adev->irq.ih_soft_work)` →
can run on any CPU.
- **Path:** Called from `amdgpu_irq_delegate()` after writing an IV to
the soft IH ring; triggered during retry page faults on GPUs using
software filtering (gmc_v9/v10/v11/v12).
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Logic / scheduling deadlock (interrupt storm + work
starvation).
- **Mechanism:** IRQ handler delegates to soft IH ring and schedules
bound work on the same CPU. Under retry page-fault storms, IRQs keep
arriving before work runs; `amdgpu_ih_ring_write()` can reach `wptr ==
rptr` and stop advancing the write pointer — IVs are written but not
committed/processed.
### Step 2.4: Fix quality
**Record:**
- **Quality:** Obviously correct; mirrors existing amdgpu usage of
`system_unbound_wq` in `amdgpu_reset.c`, `amdgpu_device.c`,
`aldebaran.c`.
- **Regression risk:** Very low. `queue_work()` deduplicates already-
queued work; same `work_struct` and handler unchanged.
- **No API, lock-order, or structural changes.**
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame changed lines
**Record:**
- `amdgpu_irq_delegate()` introduced in `26f32a377eedd` (Oct 2020,
Christian König) — soft IH infrastructure.
- `schedule_work()` line dates to that same commit; present in this tree
since 6.18 base.
- Bug has existed since soft IH ring was added (~5.10+ era).
### Step 3.2: Follow Fixes: tag
**Record:** N/A — no Fixes: tag.
### Step 3.3: Related file history
**Record:**
- Related: `bf80d34b6c58a` "Increase soft IH ring size" (symptom
mitigation, not root cause).
- `318e431b306e9` "Enable IH retry CAM on GFX9" — hardware path; this
fix targets GPUs **without** retry CAM.
- Part of series `[PATCH 3/3]` but **standalone** — patches 1/3 and 2/3
touch different concerns (ih6.1 version, HW register access).
### Step 3.4: Author context
**Record:** Timur Kristóf — active amdgpu contributor; Alex Deucher
merged. Tvrtko Ursulin reviewed.
### Step 3.5: Dependencies
**Record:** **No dependencies.** One-line change; `system_unbound_wq` is
a core kernel symbol. Applies cleanly to current `amdgpu_irq.c`.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- **b4 dig URL:** https://patch.msgid.link/20260513170849.27061-4-
timur.kristof@gmail.com
- **Series:** v1 only (May 13, 2026); committed version matches
submission.
- **Review:** Reviewed-by: Tvrtko Ursulin in thread.
- **No** stable@vger nomination, NAKs, or objections found in mbox.
### Step 4.2: Reviewers
**Record:** CC'd: amd-gfx, Alex Deucher, Christian König, Marek Olšák,
Natalie Vock, Melissa Wen, amir.shetaia@amd.com.
### Step 4.3: Bug report
**Record:** No external bug report or syzbot link. Issue identified by
developer from retry page-fault behavior.
### Step 4.4: Related patches
**Record:** Same series includes patch 2/3 "Don't perturb HW registers
when accessing soft IH ring" — separate fix, not required for this one.
### Step 4.5: Stable list history
**Record:** Not searched separately; no stable nomination in patch
thread. Not a negative signal per instructions.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `amdgpu_irq_delegate()`, `amdgpu_irq_handle_ih_soft()`,
`amdgpu_ih_ring_write()`, `amdgpu_ih_process()`
### Step 5.2: Callers of `amdgpu_irq_delegate()`
**Record:** Called from retry-fault paths in:
- `gmc_v9_0.c` (lines 589, 611)
- `gmc_v10_0.c` (line 128)
- `gmc_v11_0.c` (line 127)
- `gmc_v12_0.c` (line 120)
Triggered when `entry->ih == &adev->irq.ih` during retry page faults.
### Step 5.3: Callees
**Record:** `amdgpu_ih_ring_write()` writes IV to soft ring; work
handler calls `amdgpu_ih_process()` → `amdgpu_irq_dispatch()` → GMC
fault handler → `amdgpu_vm_handle_fault()`.
### Step 5.4: Reachability
**Record:**
- **Call chain:** HW IRQ → `amdgpu_irq_handler` → IH processing → GMC
fault handler → `amdgpu_irq_delegate` → work scheduling.
- **Reachable:** Yes — normal GPU compute/HMM/SVM page-fault path on
Navi/Vega/GFX9+ without hardware retry CAM.
- Only `vega20_ih.c` sets `retry_cam_enabled = true`; all other soft-IH
GPUs use software filtering path.
### Step 5.5: Similar patterns
**Record:** amdgpu already uses `queue_work(system_unbound_wq, ...)` for
reset/XGMI work to avoid CPU pinning — same rationale.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE
### Step 6.1: Buggy code in tree?
**Record:** **Yes.** `amdgpu_irq.c:515` still has
`schedule_work(&adev->irq.ih_soft_work)`. Soft IH infrastructure present
since 2020; retry page-fault delegation paths present in
gmc_v9/v10/v11/v12.
### Step 6.2: Backport complications
**Record:** **Clean apply expected** — identical one-line substitution
at same location. No structural divergence in this function vs. linux-
next.
### Step 6.3: Related fixes already present?
**Record:** `bf80d34b6c58a` (increase soft IH ring size) is present —
mitigates but does not fix scheduling starvation. This fix is **not**
yet in 6.18.44.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** **drivers/gpu/drm/amd/amdgpu** — IMPORTANT. Affects AMD GPU
users on compute and graphics workloads with recoverable page faults.
### Step 7.2: Subsystem activity
**Record:** Actively developed; interrupt and page-fault paths receive
frequent fixes in this tree.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** AMD GPU users on ASICs with soft IH ring and **without**
hardware retry CAM (most Navi, Vega10, GFX9, etc. — everything except
Vega20 in this tree). Config: `CONFIG_DRM_AMDGPU`.
### Step 8.2: Trigger conditions
**Record:**
- **When:** Retry page-fault storms (GPU compute, HMM, large sparse
mappings).
- **Likelihood:** Can occur under normal heavy GPU workloads, not exotic
edge case.
- **Unprivileged trigger:** Indirectly yes — userspace GPU workloads
trigger page faults.
### Step 8.3: Failure mode severity
**Record:**
- Soft IH ring overflow → dropped interrupt vectors → page faults not
handled.
- Interrupt storm → CPU saturation, possible soft lockup.
- GPU hang / application failure on affected workloads.
- **Severity: HIGH** (functional breakage + system responsiveness
impact; not proven kernel panic but can cause hangs).
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH for affected AMD GPU users — restores correct retry
page-fault handling.
- **Risk:** VERY LOW — one-line, established pattern, reviewed.
- **Ratio:** Strong benefit, minimal risk.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Fixes real scheduling starvation bug causing soft IH ring overflow.
- Affects common AMD GPUs (Navi, Vega10, GFX9, etc.) on retry page
faults.
- Can cause interrupt storms and broken page-fault recovery.
- One-line, obviously correct, reviewed.
- Bug present since 2020; code exists in 6.18.44.
- Standalone, no dependencies.
**AGAINST backport:**
- No user bug report or syzbot confirmation (developer-found).
- Patch 3/3 of a series (but functionally independent).
- Framed as "improves" handling — but mechanism is ring overflow /
dropped IVs.
**Unresolved:** No quantitative data on how often users hit this in
production.
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — reviewed, logical fix,
established amdgpu pattern.
2. Fixes real bug affecting users? **PASS** — ring overflow and
interrupt storm on retry page faults.
3. Important issue? **PASS** — HIGH: GPU hangs, CPU saturation, dropped
fault handling.
4. Small and contained? **PASS** — 1 line, 1 file.
5. No new features/APIs? **PASS**.
6. Can apply to local tree? **PASS** — buggy code present; clean apply.
### Step 9.3: Exception categories
**Record:** None (not device ID, quirk, DT, build, or docs). Standard
bug fix.
### Step 9.4: Decision rationale
For **6.18.y**, the soft IH ring and retry page-fault delegation code
are present and still use CPU-bound `schedule_work()`. Under retry page-
fault load on GPUs without hardware filter CAM, the soft IH work cannot
run on the IRQ-saturated CPU, the ring fills, IVs are dropped, and the
system can be flooded with interrupts. Switching to `system_unbound_wq`
is a minimal, reviewed fix already used elsewhere in amdgpu. This meets
stable criteria: real bug, important user impact, tiny contained change,
no new APIs.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body; no Fixes:/Reported-
by:/syzbot.
- **[Phase 2]** Diff: 1-line change in `amdgpu_irq_delegate()`; read
`amdgpu_ih_ring_write()` overflow behavior (lines 162–169).
- **[Phase 3]** `git describe HEAD` → v6.18.44; `git blame` →
`26f32a377eedd` (2020); `git merge-base --is-ancestor` → fix NOT in
HEAD.
- **[Phase 3]** Related commits: `bf80d34b6c58a`, `318e431b306e9`,
`26f32a377eedd`.
- **[Phase 4]** `b4 dig -c 3cdff3c` → lore URL; `b4 dig -a` → v1 series;
`b4 dig -w` → maintainers CC'd; mbox → Reviewed-by Tvrtko Ursulin, no
stable/NAK.
- **[Phase 5]** `grep amdgpu_irq_delegate` → 4 GMC files; `grep
retry_cam_enabled` → only `vega20_ih.c` sets true.
- **[Phase 5]** Read `gmc_v9_0.c:583–621`, `gmc_v10_0.c:115–137`,
`amdgpu_ih.c:150–169`, `amdgpu_irq.c:510–516`.
- **[Phase 5]** `grep system_unbound_wq` in amdgpu → prior usage in
reset/device code.
- **[Phase 6]** Confirmed `schedule_work` at `amdgpu_irq.c:515` in
current tree.
- **[Phase 6]** Fix commit only on `linux-next/master`, not ancestor of
HEAD.
- **[Phase 8]** Assessed severity from ring-overflow + interrupt-storm
mechanism in code.
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 8d7f97eed5a90..ccc378233bc5a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -512,7 +512,7 @@ void amdgpu_irq_delegate(struct amdgpu_device *adev,
unsigned int num_dw)
{
amdgpu_ih_ring_write(adev, &adev->irq.ih_soft, entry->iv_entry, num_dw);
- schedule_work(&adev->irq.ih_soft_work);
+ queue_work(system_unbound_wq, &adev->irq.ih_soft_work);
}
/**
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu/userq: pin mqd and fw object bo to avoid eviction
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (15 preceding siblings ...)
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: Use system unbound workqueue for soft IH ring Sasha Levin
@ 2026-08-31 13:26 ` Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18] drm/amdgpu: check and drop invalid bad page records Sasha Levin
` (20 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:26 UTC (permalink / raw)
To: patches, stable
Cc: Sunil Khatri, Christian König, Alex Deucher, Sasha Levin,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Sunil Khatri <sunil.khatri@amd.com>
[ Upstream commit a3bbf32a336939a1d21b9561f8e53333b684b7ef ]
mqd and fw objects are queue core objects which should remain
valid and never be unmapped and evicted for user queues to work
properly.
During eviction if these buffers are evicted the hw continue to
use the invalid addresses and caused page faults and system hung.
Signed-off-by: Sunil Khatri <sunil.khatri@amd.com>
Reviewed-by: Christian König <christian.koenig@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:
# Stable Backport Analysis: `drm/amdgpu/userq: pin mqd and fw object bo
to avoid eviction`
**Local tree:** Linux **6.18.43** (`git describe HEAD` →
`v6.18.43-1-gc7f0dac02d232`, `make kernelversion` → `6.18.43`)
**Upstream commit:** `a3bbf32a336939a1d21b9561f8e53333b684b7ef` (not
present in this tree)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Parse the subject line
**Record:** `[drm/amdgpu/userq]` — implicit **fix** (prevent eviction) —
**pin MQD and firmware-object BOs so they are not evicted while user
queues are active**.
### Step 1.2: Parse all commit message tags
**Record:**
- **Fixes:** — none (expected for manual review)
- **Reported-by:** — none
- **Tested-by:** — none
- **Reviewed-by:** Christian König `<christian.koenig@amd.com>`
- **Acked-by:** — none
- **Link:** — none
- **Cc: stable@vger.kernel.org:** — none (not a negative signal)
- **Signed-off-by:** Sunil Khatri (author), Alex Deucher (maintainer
merge)
- **Notable:** Reviewed-by from AMDGPU subsystem maintainer; no
syzbot/reporter tags
### Step 1.3: Analyze commit body
**Record:**
- **Bug:** MQD and firmware context objects are core user-queue state;
they must stay mapped and valid for the lifetime of an active queue.
- **Symptom:** Under eviction (memory pressure), these BOs can be
evicted while hardware still references their GPU addresses → GPU page
faults → **system hang**.
- **Root cause (author):** Objects were created as kernel BOs in GTT but
were not pinned, unlike other queue-critical objects.
- **Version info:** None in the message.
### Step 1.4: Detect hidden bug fixes
**Record:** Not disguised as cleanup — this is an explicit stability
fix. Pinning prevents TTM eviction of BOs the GPU firmware still uses.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory the changes
**Record:**
- **File:** `drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c` (+10 / −3)
- **Functions modified:** `amdgpu_userq_create_object()`,
`amdgpu_userq_destroy_object()`
- **Scope:** Single-file surgical fix
### Step 2.2: Code flow change (per hunk)
**Record:**
- **Hunk 1 (`create_object`):** Before → reserve BO, alloc GART, kmap.
After → **pin BO first**, then GART/kmap; error paths goto `unpin_bo`
before `unresv`.
- **Hunk 2 (`destroy_object`):** Before → kunmap + unref. After → kunmap
+ **unpin** + unref.
- **Paths affected:** Queue object creation/destruction for MQD and
firmware context objects.
### Step 2.3: Bug mechanism
**Record:** **Memory safety / resource lifetime bug.** MQD
(`queue->mqd`) and firmware context (`queue->fw_obj`) BOs created via
`amdgpu_userq_create_object()` were evictable. Doorbell objects in the
same file were already pinned (`amdgpu_bo_pin(...,
AMDGPU_GEM_DOMAIN_DOORBELL)` at line 331). MQD/fw objects were an
oversight.
### Step 2.4: Fix quality
**Record:**
- **Obviously correct:** Mirrors existing doorbell pinning pattern in
the same file.
- **Minimal:** 10 lines, proper error-path cleanup (`unpin_bo` label).
- **Regression risk:** Low — pinning is standard for BOs hardware must
keep resident; unpin on destroy balances pin on create.
- **Reviewer note:** Christian König suggested eviction-fence
association as a future improvement but gave **Reviewed-by** for
pinning as an immediate fix.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame changed lines
**Record:** `amdgpu_userq_create_object()` / `destroy_object()` present
in `7b923c78b50d2` (v6.18.43 tag) **without** pinning. `amdgpu_userq.c`
also exists in `v6.17` and `v6.18` tags. Bug predates the fix commit.
### Step 3.2: Follow Fixes: tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: File history for related changes
**Record:** Patch is **v2 2/2** in series with `drm/amdgpu/userq: use
drm_exec in amdgpu_userq_fence_read_wptr` (patch 1/2, different file:
`amdgpu_userq_fence.c`). **This patch is standalone** — no dependency on
patch 1/2.
### Step 3.4: Author's other commits
**Record:** Sunil Khatri is an active AMDGPU userq contributor (multiple
userq fixes in drm tree). Alex Deucher merged; Christian König reviewed.
### Step 3.5: Prerequisites
**Record:** No prerequisites. `amdgpu_bo_pin()` / `amdgpu_bo_unpin()`
exist in this tree (`amdgpu_object.c`). `git show a3bbf32... | git apply
--check` succeeds on current checkout.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original patch discussion
**Record:**
- **b4 dig -c a3bbf32a336939a1d21b9561f8e53333b684b7ef:**
https://patch.msgid.link/20260508103910.2442183-2-sunil.khatri@amd.com
- **b4 dig -a:** v1 single patch, v2 two-patch series; committed version
matches v2 2/2
- **Reviewer feedback:** Christian König: "We should probably use the
eviction fence instead of pinning, but that can come in a later patch
set." → **Reviewed-by for now.** Author agreed pinning is acceptable
interim fix.
### Step 4.2: Reviewers
**Record:** **b4 dig -w:** To/CC: Sunil Khatri, Alex Deucher, Christian
König, amd-gfx@lists.freedesktop.org — appropriate maintainer coverage.
### Step 4.3: Bug report
**Record:** No external bug report or syzbot link. Hang described in
commit message and patch submission; no stack trace provided.
### Step 4.4: Related patches
**Record:** Patch 1/2 (drm_exec locking in fence read) is independent.
Not required for this fix.
### Step 4.5: Stable mailing list
**Record:** Not searched on lore stable (Anubis blocked direct lore
fetch). No explicit stable nomination found in accessible amd-gfx
thread.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `amdgpu_userq_create_object()`,
`amdgpu_userq_destroy_object()`
### Step 5.2: Callers
**Record:** `mes_userqueue.c`:
- `mes_userq_create_ctx_space()` → `amdgpu_userq_create_object(uq_mgr,
&queue->fw_obj, ...)` (fw context)
- MQD setup → `amdgpu_userq_create_object(uq_mgr, &queue->mqd, ...)`
(line 266)
- Destroy paths call `amdgpu_userq_destroy_object()` for both objects
### Step 5.3: Callees
**Record:** `amdgpu_bo_create`, `amdgpu_bo_reserve`,
**`amdgpu_bo_pin`**, `amdgpu_ttm_alloc_gart`, `amdgpu_bo_kmap`,
`amdgpu_bo_kunmap`, **`amdgpu_bo_unpin`**, `amdgpu_bo_unref`
### Step 5.4: Call chain / reachability
**Record:**
`userspace DRM_IOCTL_AMDGPU_USERQ (CREATE)` → `amdgpu_userq_ioctl()` →
`amdgpu_userq_create()` → MES userq setup →
`amdgpu_userq_create_object()` for MQD/fw_obj.
**Reachable from userspace** by processes with DRM render access on
supported AMDGPU hardware (GFX11+ with MES userq support). Trigger
requires active user queues plus memory eviction pressure.
### Step 5.5: Similar patterns
**Record:** Doorbell pinning already done in
`amdgpu_userq_get_doorbell_index()` (line 331). Fix aligns MQD/fw_obj
with that established pattern.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE
### Step 6.1: Does buggy code exist?
**Record:** **YES.** At `7b923c78b50d2` and current HEAD,
`amdgpu_userq_create_object()` has no `amdgpu_bo_pin()`; only doorbell
path pins. Fix commit `a3bbf32` is **not** an ancestor of HEAD (`merge-
base --is-ancestor` returned 1).
### Step 6.2: Backport complications
**Record:** **Clean apply** — `git apply --check` passes with no
conflicts. Line numbers differ slightly from upstream diff (487 vs 243)
but context matches.
### Step 6.3: Related fixes already present?
**Record:** No equivalent pinning for MQD/fw_obj found. Doorbell pinning
present; this fix completes the pattern.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** **drivers/gpu/drm/amd/amdgpu** — IMPORTANT (AMD GPU users;
not universal core kernel, but affects all userq users on supported
hardware).
### Step 7.2: Subsystem activity
**Record:** Userq subsystem actively developed in 6.18.y (multiple
userq-related stable fixes in drm-fixes stream). Feature is present and
enabled via existing IOCTL path.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Users of **AMDGPU user mode queues** on hardware where
`userq_funcs` is registered (GFX11/GFX12, SDMA v6/v7, etc.). Config:
`CONFIG_DRM_AMDGPU` with userq-capable ASIC.
### Step 8.2: Trigger conditions
**Record:** Create user queues via `DRM_AMDGPU_USERQ`, then
**VRAM/memory pressure triggers TTM eviction** while queues are active.
Not every boot — requires memory pressure plus active userq workloads.
Triggerable by unprivileged render-capable processes.
### Step 8.3: Failure mode severity
**Record:** GPU page faults from stale MQD/fw addresses → **system
hang**. Severity: **CRITICAL**.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH for userq users — prevents GPU hangs under memory
pressure
- **Risk:** LOW — 10-line change, established pin/unpin API, reviewed by
maintainer
- **Ratio:** Strong benefit, minimal risk
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence compile
**FOR backport:**
- Fixes real system hang (page faults → hang) under eviction
- Small, surgical, reviewed by Christian König, merged by Alex Deucher
- Mirrors existing doorbell pinning in same file
- Applies cleanly to 6.18.43
- Buggy code confirmed present in this tree
- Standalone — no series dependency
**AGAINST backport:**
- Userq is a relatively new feature (not all stable users enable it)
- Pinning is acknowledged as interim; eviction-fence integration
preferred long-term
- No syzbot/reporter — harder to quantify frequency
- Affects driver-specific path, not core kernel
**Unresolved:** Exact reproduction rate in production; no public CVE or
bugzilla reference.
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — pattern matches doorbell
pinning; reviewed by maintainer
2. Fixes real bug affecting users? **PASS** — hang under eviction with
active user queues
3. Important issue? **PASS** — CRITICAL (system hang)
4. Small and contained? **PASS** — 1 file, +10/−3
5. No new features/APIs? **PASS** — lifecycle fix only
6. Can apply to local tree? **PASS** — clean apply verified
### Step 9.3: Exception categories
**Record:** None (not device ID, quirk, DT, build, or docs). Standard
bug fix.
### Step 9.4: Decision rationale
For **Linux 6.18.y**, the userq infrastructure is present and the bug is
real: MQD and firmware context BOs can be evicted while hardware still
references them, causing hangs. The fix is minimal, maintainer-reviewed,
follows an existing pattern in the same file, and applies cleanly. While
userq affects a subset of AMDGPU users, a system hang under memory
pressure meets stable criteria for important fixes.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body from provided commit message
and `git show a3bbf32`
- **[Phase 1]** Reviewed-by: Christian König; Signed-off-by: Sunil
Khatri, Alex Deucher
- **[Phase 2]** Diff: +10/−3 in `amdgpu_userq.c`;
`create_object`/`destroy_object` modified
- **[Phase 2]** Confirmed doorbell already pinned at line 331 in local
tree
- **[Phase 3]** `git describe` / `make kernelversion`: 6.18.43
- **[Phase 3]** `git merge-base --is-ancestor a3bbf32 7b923c78b50d2`:
NOT in tree (exit 1)
- **[Phase 3]** `git show 7b923c78b50d2:...amdgpu_userq.c`:
create_object lacks pin
- **[Phase 3]** `git apply --check` on upstream patch: clean apply
- **[Phase 3]** `git show v6.18:...amdgpu_userq.c | grep amdgpu_bo_pin`:
only doorbell pin
- **[Phase 3]** `git show v6.17:...amdgpu_userq.c`: file exists (982
lines)
- **[Phase 4]** `b4 dig -c a3bbf32`: lore URL found
- **[Phase 4]** `b4 dig -a`: v1/v2 series; v2 2/2 is committed version
- **[Phase 4]** `b4 dig -w`: Alex Deucher, Christian König CC'd
- **[Phase 4]** spinics.net msg143086: König Reviewed-by; eviction-fence
noted as future work
- **[Phase 5]** Grep callers: `mes_userqueue.c` uses create_object for
`fw_obj` and `mqd`
- **[Phase 5]** IOCTL path: `DRM_IOCTL_AMDGPU_USERQ` in `amdgpu_drv.c`
- **[Phase 6]** Buggy code at HEAD lines 243–303: no pin in
create_object
- **[Phase 6]** Eviction path: `amdgpu_eviction_fence.c` →
`amdgpu_userq_evict()` exists but does not pin MQD/fw BOs
- **[Phase 8]** Failure mode: page faults + system hang per commit
message
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 7e3175f82a20d..0f4281c9aea2f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -270,16 +270,20 @@ int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
goto free_obj;
}
+ r = amdgpu_bo_pin(userq_obj->obj, AMDGPU_GEM_DOMAIN_GTT);
+ if (r)
+ goto unresv;
+
r = amdgpu_ttm_alloc_gart(&(userq_obj->obj)->tbo);
if (r) {
drm_file_err(uq_mgr->file, "Failed to alloc GART for userqueue object (%d)", r);
- goto unresv;
+ goto unpin_bo;
}
r = amdgpu_bo_kmap(userq_obj->obj, &userq_obj->cpu_ptr);
if (r) {
drm_file_err(uq_mgr->file, "Failed to map BO for userqueue (%d)", r);
- goto unresv;
+ goto unpin_bo;
}
userq_obj->gpu_addr = amdgpu_bo_gpu_offset(userq_obj->obj);
@@ -287,11 +291,13 @@ int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
memset(userq_obj->cpu_ptr, 0, size);
return 0;
+unpin_bo:
+ amdgpu_bo_unpin(userq_obj->obj);
unresv:
amdgpu_bo_unreserve(userq_obj->obj);
-
free_obj:
amdgpu_bo_unref(&userq_obj->obj);
+
return r;
}
@@ -299,6 +305,7 @@ void amdgpu_userq_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj)
{
amdgpu_bo_kunmap(userq_obj->obj);
+ amdgpu_bo_unpin(userq_obj->obj);
amdgpu_bo_unref(&userq_obj->obj);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: check and drop invalid bad page records
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (16 preceding siblings ...)
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18] drm/amdgpu/userq: pin mqd and fw object bo to avoid eviction Sasha Levin
@ 2026-08-31 13:26 ` Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Fix OOB memory exposure in get_wave_state() Sasha Levin
` (19 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:26 UTC (permalink / raw)
To: patches, stable
Cc: YiPeng Chai, Tao Zhou, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: YiPeng Chai <YiPeng.Chai@amd.com>
[ Upstream commit 3999aa4a04a04167d70bfe4dc3ba239257e5b5df ]
Check and drop invalid bad page records.
Signed-off-by: YiPeng Chai <YiPeng.Chai@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:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
Record: `[drm/amdgpu]` `[check]` — validate and discard invalid RAS
EEPROM bad-page records before they are applied to VRAM reservation /
in-kernel bad-page tables.
**Step 1.2 — Tags**
Record:
- Signed-off-by: YiPeng Chai \<YiPeng.Chai@amd.com\> (author)
- Reviewed-by: Tao Zhou \<tao.zhou1@amd.com\> (AMD RAS reviewer; also
author of prior range-check work in this tree)
- Signed-off-by: Alex Deucher \<alexander.deucher@amd.com\> (amdgpu
maintainer)
- No Fixes:, Reported-by:, Link:, Cc: stable@vger.kernel.org, Tested-
by:, or Acked-by:
Notable: reviewed by subsystem expert; no public bug report in the
commit message.
**Step 1.3 — Body**
Record:
- Bug description: EEPROM / RAS bad-page records may contain
`retired_page` values outside usable VRAM.
- Symptom/failure mode: not spelled out in the message; code adds
`dev_warn()` and refuses to process out-of-range records.
- Version info: none in message.
- Root cause (from code): validation used `mc_vram_size` in some paths
(commit `2b17c240e8cd9`, already in 6.18.y), but reservation and
restore still lacked checks against `real_vram_size`, which can be
smaller than `mc_vram_size` when `amdgpu_vram_limit` is set
(`amdgpu_gmc_vram_location()` in `amdgpu_gmc.c`).
**Step 1.4 — Hidden bug fix?**
Record: **Yes.** Despite the terse message, this is a defensive
correctness fix: it prevents out-of-range PFNs from reaching
`amdgpu_ras_reserve_page()` → `amdgpu_vram_mgr_reserve_range()` and adds
a batch guard in `__amdgpu_ras_restore_bad_pages()` on EEPROM load.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
Record:
- File: `drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c` (+22 lines net)
- Functions: new `__check_record_in_range()`; modified
`__amdgpu_ras_restore_bad_pages()`, `amdgpu_ras_reserve_page()`
- Scope: single-file, surgical
**Step 2.2 — Code flow**
Record:
- Hunk 1 (`__check_record_in_range`): before — no upfront validation of
EEPROM batch; after — if any `retired_page >= real_vram_size >>
page_shift`, warn and return false.
- Hunk 2 (`__amdgpu_ras_restore_bad_pages`): before — processes all
records; after — if batch check fails, return 0 immediately (drop
entire batch).
- Hunk 3 (`amdgpu_ras_reserve_page`): before — only critical-address
check, then buddy reservation; after — early return with warning for
PFN beyond `real_vram_size`.
**Step 2.3 — Bug mechanism**
Record:
- Category: **logic / bounds validation** (prevents invalid VRAM
reservations and inconsistent bad-page state).
- Mechanism: corrupt or stale EEPROM entries (or entries beyond
`real_vram_size` after VRAM limiting) could reach VRAM buddy allocator
reservation. Existing `amdgpu_ras_check_bad_page_unlock()` (6.18.y)
validates against `mc_vram_size`, not `real_vram_size`.
`amdgpu_ras_reserve_page()` had no upper-bound check at all and is
called directly from `umc_v12_0.c` on ECC error paths.
**Step 2.4 — Fix quality**
Record: Fix is minimal and obviously correct for bounds checking.
Regression risk is low. One nuance: if **any** record in a batch is out
of range, **all** records are dropped (conservative, not per-record
filtering). No deadlock or API change.
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
Record:
- `amdgpu_ras_reserve_page()` introduced by YiPeng Chai (2024-03-29),
present since before 6.18.y.
- `__amdgpu_ras_restore_bad_pages()` core loop from 2025-02-24; related
fixes by Tao Zhou (July 2025).
- Target commit `3999aa4a04a04` dated 2026-05-12; **not** in current
tree (6.18.44).
**Step 3.2 — Fixes: tag**
Record: N/A — no Fixes: tag.
**Step 3.3 — Related commits**
Record:
- `2b17c240e8cd9` — "add range check for RAS bad page address" — **IN
6.18.y**; checks `mc_vram_size` in
`amdgpu_ras_check_bad_page_unlock()`.
- `0b7f78caeffa5` — "Move ras data alloc before bad page check" — **IN
6.18.y**; fixed NULL deref in sysfs bad-pages read when EEPROM had
only invalid entries.
- `0028b86b52f76` — "mark invalid records with U64_MAX" — **NOT in
6.18.y** (mainline only).
- `3fc96f60b61ce` — critical-address check in
`amdgpu_ras_reserve_page()` — **IN 6.18.y**.
- This commit is standalone (not part of a numbered series).
**Step 3.4 — Author context**
Record: YiPeng Chai is a regular amdgpu/RAS contributor (reserve_page
author, critical-address work). Tao Zhou reviewed and authored the prior
range-check commit.
**Step 3.5 — Dependencies**
Record: No prerequisites. Patch applies cleanly to 6.18.y (`git apply
--check` succeeded). Uses `adev->gmc.real_vram_size` and
`AMDGPU_GPU_PAGE_SHIFT`, both present in this tree.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
Record: `b4 dig -c 3999aa4a04a04` — **no lore match found**. Phase not
fully applicable.
**Step 4.2 — Reviewers**
Record: `b4 dig -w` not run (no thread found). Reviewed-by Tao Zhou and
Signed-off-by Alex Deucher verified from `git show`.
**Step 4.3 — Bug report**
Record: N/A — no Reported-by/Link tags; no public thread found.
**Step 4.4 — Related series**
Record: Related mainline-only work (`U64_MAX` invalid-record marking)
not in 6.18.y; this commit is independently useful without it.
**Step 4.5 — Stable list**
Record: Not searched (no lore thread to anchor a stable@ query). Related
NULL-deref fix (`0b7f78caeffa5`) was already backported to 6.18.y,
showing this problem class is stable-worthy.
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
Record: `__check_record_in_range()`, `__amdgpu_ras_restore_bad_pages()`,
`amdgpu_ras_reserve_page()`.
**Step 5.2 — Callers**
Record:
- `__amdgpu_ras_restore_bad_pages()` ← `amdgpu_ras_add_bad_pages()` ←
`amdgpu_ras_load_bad_pages()` (boot/RAS init EEPROM load) and runtime
UMC error paths.
- `amdgpu_ras_reserve_page()` ← `__amdgpu_ras_restore_bad_pages()` and
`umc_v12_0.c` ECC handler (line 609).
**Step 5.3 — Callees**
Record: `amdgpu_vram_mgr_reserve_range()`,
`amdgpu_vram_mgr_query_page_status()`, `dev_warn()`,
`amdgpu_ras_check_critical_address()`.
**Step 5.4 — Reachability**
Record: Triggered on boot when RAS EEPROM has records
(`amdgpu_ras_load_bad_pages()` during RAS init) and at runtime on UMC
ECC events. Requires `CONFIG_DRM_AMDGPU` + RAS-capable AMD hardware
(datacenter/workstation GPUs). Not a generic syscall path, but real
production hardware.
**Step 5.5 — Similar patterns**
Record: `2b17c240e8cd9` added `mc_vram_size` checks in
`amdgpu_ras_check_bad_page_unlock()`. This commit closes the
`real_vram_size` gap and protects the direct `amdgpu_ras_reserve_page()`
entry point. In 6.18.y, `__amdgpu_ras_restore_bad_pages()` still uses
`if (amdgpu_ras_check_bad_page_unlock(...))` as a boolean despite the
function returning `int` (-EINVAL/0/1), which can mishandle `-EINVAL`
(truthy) without adding a record — another reason upfront validation
helps.
---
## Phase 6: Cross-Reference Against Local Tree (6.18.44)
**Step 6.1 — Buggy code present?**
Record: **Yes.** Local tree is `v6.18.44` on `stable/linux-6.18.y`.
`__check_record_in_range()` and the `amdgpu_ras_reserve_page()` bounds
guard are absent. `amdgpu_ras_reserve_page()` at lines 5366–5383 has
only the critical-address check, no `real_vram_size` upper bound.
**Step 6.2 — Backport complications**
Record: **Clean apply** verified. No structural conflicts with 6.18.y
`amdgpu_ras.c`.
**Step 6.3 — Related fixes already present?**
Record: Partial coverage from `2b17c240e8cd9` (`mc_vram_size` in
`amdgpu_ras_check_bad_page_unlock`) and `0b7f78caeffa5` (NULL deref on
all-invalid EEPROM). This commit's `real_vram_size` checks and
`amdgpu_ras_reserve_page()` guard are **not** already present.
---
## Phase 7: Subsystem Context
**Step 7.1 — Subsystem / criticality**
Record: `drivers/gpu/drm/amd/amdgpu` — RAS (Reliability, Availability,
Serviceability) / VRAM error handling. **IMPORTANT** for AMD enterprise
GPU users; not core-kernel-wide.
**Step 7.2 — Activity**
Record: Active subsystem in 6.18.y (multiple RAS fixes in recent history
on `amdgpu_ras.c`).
---
## Phase 8: Impact and Risk
**Step 8.1 — Who is affected**
Record: Users of AMD GPUs with RAS page retirement enabled, especially
MI-series / CDNA / Instinct and other ECC-capable cards loading bad-page
records from EEPROM at boot or on UMC errors.
**Step 8.2 — Trigger conditions**
Record: Corrupt, migrated, or out-of-date EEPROM bad-page records; or
`real_vram_size < mc_vram_size` via `amdgpu_vram_limit`. Uncommon but
plausible on long-lived server GPUs. Not unprivileged-triggerable
directly; tied to hardware error state / EEPROM content.
**Step 8.3 — Failure mode severity**
Record: Without fix: attempted reservation of out-of-range VRAM
(`amdgpu_vram_mgr_reserve_range()` may fail silently in
`amdgpu_vram_mgr_do_reserve()`), inconsistent bad-page counts (related
NULL-deref class already hit stable), potential RAS tracking corruption.
Severity: **MEDIUM-HIGH** for affected hardware (reliability feature
breakage, possible oops in related paths already seen and fixed
separately).
**Step 8.4 — Risk/benefit**
Record:
- Benefit: **MEDIUM-HIGH** for RAS users — prevents invalid VRAM
reservations and drops clearly bad EEPROM batches.
- Risk: **LOW** — ~22 lines, warn-and-skip semantics, reviewed by AMD.
- Ratio: favorable for backport.
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence**
FOR:
- Real bounds-validation gap in 6.18.y (`real_vram_size` vs
`mc_vram_size`).
- `amdgpu_ras_reserve_page()` unguarded; called from runtime ECC path.
- EEPROM restore path lacks batch validation.
- Small, reviewed, applies cleanly.
- Same RAS/EEPROM invalid-record problem class already warranted stable
fixes (NULL deref in `0b7f78caeffa5`).
AGAINST:
- Sparse commit message (no explicit crash report).
- Niche hardware (RAS-enabled AMD GPUs only).
- Drops entire batch if any record is invalid (conservative).
- Partial overlap with `2b17c240e8cd9` (but does not fully subsume this
fix).
UNRESOLVED:
- No lore thread or user bug report found.
- Exact user-visible failure without this patch on 6.18.y not reproduced
here (inferred from code paths and related fixes).
**Step 9.2 — Stable rules checklist**
1. Obviously correct and tested? **PASS** — straightforward bounds
checks; Reviewed-by from AMD; no Tested-by.
2. Fixes a real bug? **PASS** — prevents out-of-range VRAM reservations
and invalid EEPROM restore.
3. Important issue? **PASS** — MEDIUM-HIGH for RAS/enterprise GPU
reliability; related crash class already backported.
4. Small and contained? **PASS** — single file, ~22 lines.
5. No new features/APIs? **PASS** — validation only.
6. Can apply to local tree? **PASS** — clean apply verified.
**Step 9.3 — Exception category**
Record: N/A (not device ID, quirk, DT, build, or docs).
**Step 9.4 — Decision rationale**
For the **6.18.y** tree checked out here, this commit closes a real
validation hole in amdgpu RAS bad-page handling. The tree already has
partial protection (`mc_vram_size` checks) and a related NULL-deref fix,
but still lacks `real_vram_size` validation and an
`amdgpu_ras_reserve_page()` guard. The fix is small, low-risk, and
targets production RAS hardware where EEPROM corruption or VRAM limiting
can produce out-of-range records.
---
## Verification
- [Phase 1] `git show 3999aa4a04a04` — parsed subject, tags, body
- [Phase 2] Diff from user query + `git show 3999aa4a04a04` — 22-line
change in `amdgpu_ras.c`
- [Phase 3] `git describe HEAD` → v6.18.44; `git merge-base --is-
ancestor 3999aa4a04a04 HEAD` → NOT IN TREE; `2b17c240e8cd9` → IN TREE
- [Phase 3] `git log --oneline -20 --
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c` — related RAS history
- [Phase 3] `git show 2b17c240e8cd9`, `0b7f78caeffa5`, `0028b86b52f76` —
related commits examined
- [Phase 3] `git blame` on restore loop and `amdgpu_ras_reserve_page`
- [Phase 4] `b4 dig -c 3999aa4a04a04` — no lore match
- [Phase 5] `Grep` callers of `amdgpu_ras_reserve_page`,
`__amdgpu_ras_restore_bad_pages`
- [Phase 5] Read `umc_v12_0.c:609`, `amdgpu_vram_mgr.c:298-327`,
`amdgpu_gmc.c:217-222`
- [Phase 6] `Grep` for `__check_record_in_range` — not in tree
- [Phase 6] `git show 3999aa4a04a04 --format= --
drivers/.../amdgpu_ras.c | git apply --check` — clean apply
- [Phase 6] Read current `amdgpu_ras_reserve_page()` at lines 5366–5383
— no range guard
- [Phase 8] Confirmed `real_vram_size` can be reduced below
`mc_vram_size` via `amdgpu_vram_limit` in `amdgpu_gmc_vram_location()`
**YES**The background git searches finished and matched what we already
had:
- **`3999aa4a04a04`** — `drm/amdgpu: check and drop invalid bad page
records` (the commit under review)
- **`2b17c240e8cd9`** — earlier related fix, `drm/amdgpu: add range
check for RAS bad page address`, already in **6.18.44**
That confirms the new commit is on master but not in this stable tree,
while only partial protection exists today. The backport recommendation
stands: **YES** for **6.18.y**.
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 27 +++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 9df691364a18c..4c1a65fffede7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -2884,6 +2884,25 @@ static int amdgpu_ras_mca2pa(struct amdgpu_device *adev,
return -EINVAL;
}
+static bool __check_record_in_range(struct amdgpu_device *adev,
+ struct eeprom_table_record *bps, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (bps[i].retired_page >=
+ (adev->gmc.real_vram_size >> AMDGPU_GPU_PAGE_SHIFT)) {
+ dev_warn(adev->dev,
+ "Recorded address out of range: 0x%llx, 0x%llx, 0x%x, 0x%x\n",
+ bps[i].address, bps[i].retired_page,
+ bps[i].mem_channel, bps[i].mcumc_id);
+ return false;
+ }
+ }
+
+ return true;
+}
+
static int __amdgpu_ras_restore_bad_pages(struct amdgpu_device *adev,
struct eeprom_table_record *bps, int count)
{
@@ -2891,6 +2910,9 @@ static int __amdgpu_ras_restore_bad_pages(struct amdgpu_device *adev,
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
struct ras_err_handler_data *data = con->eh_data;
+ if (!__check_record_in_range(adev, bps, count))
+ return 0;
+
for (j = 0; j < count; j++) {
if (!data->space_left &&
amdgpu_ras_realloc_eh_data_space(adev, data, 256)) {
@@ -5370,6 +5392,11 @@ int amdgpu_ras_reserve_page(struct amdgpu_device *adev, uint64_t pfn)
uint64_t start = pfn << AMDGPU_GPU_PAGE_SHIFT;
int ret = 0;
+ if (pfn >= (adev->gmc.real_vram_size >> AMDGPU_GPU_PAGE_SHIFT)) {
+ dev_warn(adev->dev, "Ignoring out-of-range bad page 0x%llx", start);
+ return 0;
+ }
+
if (amdgpu_ras_check_critical_address(adev, start))
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Fix OOB memory exposure in get_wave_state()
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (17 preceding siblings ...)
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18] drm/amdgpu: check and drop invalid bad page records Sasha Levin
@ 2026-08-31 13:27 ` Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: fix buffer overflow during vBIOS update Sasha Levin
` (18 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:27 UTC (permalink / raw)
To: patches, stable
Cc: Sunday Clement, Alex Deucher, Sasha Levin, Felix.Kuehling,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Sunday Clement <Sunday.Clement@amd.com>
[ Upstream commit 7ef144458f48d5589e36f1b3d83e83db2e5c5ba5 ]
The get_wave_state() function for v9 trusts cp_hqd_cntl_stack_size and
cp_hqd_cntl_stack_offset values read directly from the MQD, which are
written by GPU microcode and fully attacker-controlled on the
CRIU-restore path (via AMDKFD_IOC_RESTORE_PROCESS with H3).
this leads to an unbounded copy_to_user() that can leak adjacent
GTT/kernel memory. If offset > size, integer underflow produces a ~4 GiB
read length, if size is set to 1 MiB against a 4 KiB allocation, we leak
1 MiB of adjacent kernel memory (other queues' MQDs, ring buffers, KASLR
pointers).
Fix by clamping both cp_hqd_cntl_stack_size to the actual allocated
buffer size (q->ctl_stack_size) and cp_hqd_cntl_stack_offset to the
clamped size before performing arithmetic and copy_to_user().
This ensures we never read beyond the allocated kernel BO regardless of
attacker-supplied MQD field values.
Signed-off-by: Sunday Clement <Sunday.Clement@amd.com>
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:
Connection lost, reconnecting to https://agentn.us.api5.cursor.sh
(attempt 1)...
Retry attempt 1...
# Stable Backport Analysis: `drm/amdkfd: Fix OOB memory exposure in
get_wave_state()`
**Local tree:** Linux **6.18.43** (`v6.18.43-1-gc7f0dac02d232`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject Line
**Record:** `[drm/amdkfd]` `[Fix]` — Fix out-of-bounds kernel memory
exposure in `get_wave_state()` for GFX9 (v9 MQD manager).
### Step 1.2: Tags
**Record:**
| Tag | Value |
|-----|-------|
| Signed-off-by | Sunday Clement `<Sunday.Clement@amd.com>` (author) |
| Acked-by | Alex Deucher `<alexander.deucher@amd.com>` |
| Signed-off-by | Alex Deucher `<alexander.deucher@amd.com>` (committer)
|
| Fixes: | **Absent** (expected for candidate review) |
| Cc: stable | **Absent** (expected) |
| Reported-by: | **Absent** |
| Link: | **Absent** |
Notable: Acked-by from AMDGPU/KFD maintainer Alex Deucher is a strong
quality signal.
### Step 1.3: Body Analysis
**Record:**
- **Bug:** `get_wave_state()` in `kfd_mqd_manager_v9.c` trusts
`cp_hqd_cntl_stack_size` and `cp_hqd_cntl_stack_offset` from the MQD
without bounds checking.
- **Attack vector:** On the CRIU-restore path (`AMDKFD_IOC_CRIU_OP` /
`KFD_CRIU_OP_RESTORE`), the full MQD is copied from userspace via
`restore_mqd()` → `memcpy(m, mqd_src, sizeof(*m))`, making those
fields attacker-controlled.
- **Symptoms:** Unbounded `copy_to_user()` reads beyond the allocated
control-stack BO, leaking adjacent GTT/kernel memory (other MQDs, ring
buffers, KASLR pointers). If `offset > size`, unsigned subtraction
underflows to ~4 GiB copy length.
- **Root cause:** MQD fields used directly for pointer arithmetic and
copy size without clamping to `q->ctl_stack_size` (the actual
allocation size).
- **Version info:** Not specified; affects GFX9 v9 MQD path with CWSR
enabled.
### Step 1.4: Hidden Bug Fix Detection
**Record:** Not disguised — explicitly labeled as a security/memory-
safety fix. Clear OOB read → info-leak vulnerability.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Change Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c` (+7/−3
net, ~10 lines touched)
- **Function:** `get_wave_state()` (static, v9 MQD manager)
- **Scope:** Single-file, surgical fix
### Step 2.2: Code Flow Change
**Record:**
| Hunk | Before | After |
|------|--------|-------|
| Variable setup | Used raw MQD fields | Declares `cntl_stack_size`,
`cntl_stack_offset`; clamps to `q->ctl_stack_size` |
| Size calculation for copy | `*ctl_stack_used_size =
m->cp_hqd_cntl_stack_size - m->cp_hqd_cntl_stack_offset` (used directly
for copy) | Recalculated as `cntl_stack_size - cntl_stack_offset` after
clamping |
| `copy_to_user` of stack data | `ctl_stack +
m->cp_hqd_cntl_stack_offset`, length `*ctl_stack_used_size` | `ctl_stack
+ cntl_stack_offset`, length clamped `*ctl_stack_used_size` |
Header fields are still populated from unclamped MQD values before the
clamp (pre-existing behavior); the security-critical kernel read is what
gets fixed.
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Buffer overflow / out-of-bounds read → kernel
information disclosure
- **Mechanism:** Attacker-supplied MQD
`cp_hqd_cntl_stack_size`/`cp_hqd_cntl_stack_offset` drive
`copy_to_user()` source pointer (`mqd_ctl_stack + offset`) and length
(`size - offset`) without validation against the BO allocated as
`ALIGN(q->ctl_stack_size, PAGE_SIZE)` at MQD creation time.
### Step 2.4: Fix Quality
**Record:**
- Fix is obviously correct: `min_t()` clamping to known allocation bound
is standard kernel practice.
- Minimal, no API changes, no new features.
- Low regression risk: only affects the data-copy path; worst case
slightly truncates data returned to userspace when MQD fields are
corrupt/malicious (correct behavior).
- Alex Deucher noted C89 mixed-declaration issue in v1 (variables after
statements); the candidate diff moves declarations to function top,
addressing that.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `git blame` on lines 336–370 attributes all lines to
`a112b91dd6349` (sunrpc backport marker commit) — this stable tree has
flattened/squashed history, so blame is not reliable for dating the
original code. The `get_wave_state()` function and vulnerable
`copy_to_user` pattern are **present in the current tree**.
### Step 3.2: Fixes: Tag
**Record:** No `Fixes:` tag present. N/A.
### Step 3.3: Related File History
**Record:** `git log --oneline --
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c` returns only one commit
in this tree (history squashed). Cannot trace intermediate fixes from
local git alone.
### Step 3.4: Author Context
**Record:** Sunday Clement (AMD). Alex Deucher Acked and committed. No
other Sunday Clement commits found in this tree's amdkfd history
(squashed tree).
### Step 3.5: Dependencies
**Record:**
- **Standalone fix** — no series dependency, no prerequisite commits
referenced.
- Requires existing code: `get_wave_state()` v9 copy path, CRIU restore,
`q->ctl_stack_size` in `queue_properties`. All verified present in
6.18.43 tree.
- **v9-specific:** v10+ `get_wave_state()` does not copy control stack
to userspace (only header metadata), so this bug is unique to the v9
path.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original Discussion
**Record:**
- `b4 dig` failed in this environment.
- Web search found thread: https://lists.freedesktop.org/archives/amd-
gfx/2026-May/144498.html
- Submitted May 13, 2026 by Sunday Clement; Alex Deucher replied same
day with **Acked-by** (after noting C89 declaration placement).
- Single-patch submission, not part of a series.
### Step 4.2: Reviewers
**Record:** Alex Deucher (AMDGPU maintainer) reviewed and Acked.
Appropriate subsystem maintainer involvement confirmed.
### Step 4.3: Bug Report
**Record:** No external bug report, syzbot, or CVE referenced. Security
impact described in commit message and review thread.
### Step 4.4: Related Patches
**Record:** No related patches in a series. v10+ not affected (no stack
copy). No other GFX versions need this exact fix.
### Step 4.5: Stable List Discussion
**Record:** No stable@vger.kernel.org nomination found in the thread.
Not a negative signal per instructions.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key Functions
**Record:** `get_wave_state()` (v9), called via
`get_wave_state_v9_4_3()` for multi-XCC GFX9.4.3+.
### Step 5.2: Callers
**Record:**
```
kfd_ioctl_get_queue_wave_state() [kfd_chardev.c:541]
→ pqm_get_wave_state()
[kfd_process_queue_manager.c:685]
→ dqm->ops.get_wave_state()
[kfd_device_queue_manager.c:2690]
→ mqd_mgr->get_wave_state() [kfd_mqd_manager_v9.c:336]
```
`AMDKFD_IOC_GET_QUEUE_WAVE_STATE` has ioctl flag `0` (no special
capability beyond KFD device access).
### Step 5.3: Callees
**Record:** `get_mqd()`, `copy_to_user()` — the vulnerable path copies
from `mqd_ctl_stack` (kernel BO at `mqd + PAGE_SIZE`).
### Step 5.4: Attack Chain (Reachability)
**Record:**
1. Attacker with `CAP_CHECKPOINT_RESTORE` calls `AMDKFD_IOC_CRIU_OP`
with `KFD_CRIU_OP_RESTORE` (`kfd_ioctl_criu`, flag
`KFD_IOC_FLAG_CHECKPOINT_RESTORE`).
2. `kfd_criu_restore_queue()` → `copy_from_user()` of MQD →
`pqm_create_queue()` → `restore_mqd()` → `memcpy(m, mqd_src,
sizeof(*m))` — **full MQD including malicious stack size/offset
fields**.
3. Attacker calls `AMDKFD_IOC_GET_QUEUE_WAVE_STATE` on the restored
queue (queue must be inactive, `cwsr_enabled`).
4. `get_wave_state()` performs OOB `copy_to_user()`, leaking kernel
memory.
Reachable from userspace ioctl path. Poisoning requires
`CHECKPOINT_RESTORE` capability; the leak ioctl itself does not.
### Step 5.5: Similar Patterns
**Record:** `checkpoint_mqd()` also uses `m->cp_hqd_cntl_stack_size` for
`memcpy` (line 388) — potentially a separate concern on restore, but not
addressed by this commit and not the `get_wave_state` leak path under
review. v10/v11/v12 `get_wave_state()` do not perform the vulnerable
stack copy.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE (6.18.43)
### Step 6.1: Buggy Code Exists?
**Record:** **YES.** Current tree at `kfd_mqd_manager_v9.c:350-366`:
```350:366:drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
*ctl_stack_used_size = m->cp_hqd_cntl_stack_size -
m->cp_hqd_cntl_stack_offset;
// ...
if (copy_to_user(ctl_stack + m->cp_hqd_cntl_stack_offset,
mqd_ctl_stack +
m->cp_hqd_cntl_stack_offset,
*ctl_stack_used_size))
```
CRIU restore infrastructure (`kfd_criu_restore_queue`, `restore_mqd`,
`AMDKFD_IOC_CRIU_OP`) all present. Control stack BO allocated at
`ALIGN(q->ctl_stack_size, PAGE_SIZE)` in `alloc_mqd()` (line 139).
### Step 6.2: Backport Complications
**Record:** **Clean apply expected.** Single hunk in one file. No
structural conflicts observed. Candidate diff uses top-of-function
variable declarations (addresses maintainer C89 feedback).
### Step 6.3: Related Fixes Already Present?
**Record:** `git log --grep="OOB"` and `--grep="get_wave_state"` in
amdkfd returned no results. Fix is **not** already in this tree.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem Criticality
**Record:** `drivers/gpu/drm/amd/amdkfd` — AMDGPU KFD (HSA compute).
**IMPORTANT** subsystem: affects AMD GPU compute users (ROCm, HPC, ML
workloads). Security-relevant ioctl path.
### Step 7.2: Subsystem Activity
**Record:** Active development (CRIU, MES, multi-XCC support visible in
tree). CRIU restore is a relatively newer code path where insufficient
validation is plausible.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who Is Affected
**Record:** Users of AMD GFX9 GPUs (Vega20, MI50, MI100, etc.) with:
- `CONFIG_HSA_AMD`/amdkfd enabled
- CWSR (`cwsr_enabled`) enabled
- CRIU checkpoint/restore used (containers, migration)
### Step 8.2: Trigger Conditions
**Record:**
- Requires `CAP_CHECKPOINT_RESTORE` to poison MQD via CRIU restore
- Then `AMDKFD_IOC_GET_QUEUE_WAVE_STATE` on inactive queue
- Not every boot path — specific to CRIU restore + wave state query
- Unprivileged direct trigger: **No** (needs CHECKPOINT_RESTORE for
poisoning step)
### Step 8.3: Failure Mode Severity
**Record:**
- **Failure mode:** Kernel memory information disclosure to userspace
(KASLR pointers, adjacent BO contents)
- **Secondary:** Integer underflow could attempt multi-GB copy
(potential crash/hang)
- **Severity: HIGH** (security — info leak, KASLR bypass aid)
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit: HIGH** — closes a real kernel memory leak on a security-
sensitive ioctl path
- **Risk: VERY LOW** — 7 lines, bounds clamping only, maintainer-Acked
- **Ratio:** Strongly favors backport
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence Summary
**FOR backport:**
- Real security bug: OOB kernel read → info leak (KASLR, adjacent BOs)
- Small, surgical, maintainer-Acked fix
- Buggy code and CRIU infrastructure exist in 6.18.43
- v9-specific `copy_to_user` of control stack is the vulnerable
operation
- Integer underflow can produce ~4 GiB copy attempt
- Defense-in-depth: kernel must not trust MQD fields without validation
**AGAINST backport:**
- Requires `CAP_CHECKPOINT_RESTORE` for the poisoning step (limits
attack surface to CRIU-capable contexts)
- Only affects GFX9 (v9 MQD manager), not GFX10+
- Header metadata still uses unclamped values (minor, not the security
issue)
**Unresolved:** Exact mainline commit SHA not available in this tree;
original introduction date of vulnerable code not determinable due to
squashed stable history.
### Step 9.2: Stable Rules Checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — `min_t()` clamping is
standard; Acked by maintainer |
| 2. Fixes real bug affecting users? | **PASS** — kernel memory info
leak via ioctl |
| 3. Important issue? | **PASS** — security (info disclosure, KASLR
leak) |
| 4. Small and contained? | **PASS** — 1 file, ~10 lines |
| 5. No new features/APIs? | **PASS** — validation only |
| 6. Can apply to local tree? | **PASS** — buggy code present, clean
apply expected |
### Step 9.3: Exception Categories
**Record:** None of the hardware-quirk/DT/device-ID exceptions apply.
This is a security bug fix.
### Step 9.4: Decision Rationale
For **Linux 6.18.43**, the vulnerable `get_wave_state()` code exists,
the CRIU restore attack path is present, and the fix is a minimal
bounds-check that closes a kernel memory information disclosure. This
meets all stable kernel criteria for a security fix. The
`CAP_CHECKPOINT_RESTORE` requirement limits who can trigger it, but
container/CRIU environments are exactly where stable kernels with AMDGPU
compute are deployed, and leaking KASLR/kernel pointers is a meaningful
security impact.
---
## Verification
- **[Phase 1]** Parsed commit message and tags from user query;
confirmed Acked-by Alex Deucher
- **[Phase 1]** No Fixes:/Reported-by:/Cc: stable tags (expected)
- **[Phase 2]** Read diff and current `kfd_mqd_manager_v9.c:336-370` —
vulnerable `copy_to_user` confirmed
- **[Phase 2]** Verified BO allocation size uses `q->ctl_stack_size` at
`kfd_mqd_manager_v9.c:139`
- **[Phase 3]** `git blame -L 336,370` — squashed history, unreliable
for dating
- **[Phase 3]** `git log --oneline -- kfd_mqd_manager_v9.c` — single
commit (squashed tree)
- **[Phase 3]** No Fixes: tag to follow
- **[Phase 4]** `b4 dig` — **failed** (tool unavailable)
- **[Phase 4]** WebFetch lore thread — Alex Deucher Acked-by confirmed
at https://lists.freedesktop.org/archives/amd-gfx/2026-May/144498.html
- **[Phase 4]** No stable list nomination found
- **[Phase 5]** Traced call chain: `kfd_ioctl_get_queue_wave_state` →
`pqm_get_wave_state` → `get_wave_state` (v9)
- **[Phase 5]** Verified CRIU restore path: `kfd_criu_restore_queue` →
`restore_mqd` → `memcpy(m, mqd_src, sizeof(*m))` at line 422
- **[Phase 5]** Verified v10 `get_wave_state` does NOT copy stack data
(only header) — bug v9-specific
- **[Phase 6]** `git describe HEAD` → v6.18.43; `Makefile` → 6.18.43
- **[Phase 6]** Buggy code present; fix not yet applied
- **[Phase 6]** CRIU ioctl `KFD_CRIU_OP_RESTORE` present with
`KFD_IOC_FLAG_CHECKPOINT_RESTORE`
- **[Phase 8]** Failure mode: kernel info leak, severity HIGH
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
index f2dee320fada4..e3a33a92b1799 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
@@ -341,11 +341,15 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
{
struct v9_mqd *m;
struct kfd_context_save_area_header header;
+ u32 cntl_stack_size;
+ u32 cntl_stack_offset;
/* Control stack is located one page after MQD. */
void *mqd_ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
m = get_mqd(mqd);
+ cntl_stack_size = min_t(u32, m->cp_hqd_cntl_stack_size, q->ctl_stack_size);
+ cntl_stack_offset = min_t(u32, m->cp_hqd_cntl_stack_offset, cntl_stack_size);
*ctl_stack_used_size = m->cp_hqd_cntl_stack_size -
m->cp_hqd_cntl_stack_offset;
@@ -361,9 +365,10 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
if (copy_to_user(ctl_stack, &header, sizeof(header.wave_state)))
return -EFAULT;
- if (copy_to_user(ctl_stack + m->cp_hqd_cntl_stack_offset,
- mqd_ctl_stack + m->cp_hqd_cntl_stack_offset,
- *ctl_stack_used_size))
+ *ctl_stack_used_size = cntl_stack_size - cntl_stack_offset;
+
+ if (copy_to_user(ctl_stack + cntl_stack_offset, mqd_ctl_stack + cntl_stack_offset,
+ *ctl_stack_used_size))
return -EFAULT;
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: fix buffer overflow during vBIOS update
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (18 preceding siblings ...)
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Fix OOB memory exposure in get_wave_state() Sasha Levin
@ 2026-08-31 13:27 ` Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: harden FRU PIA parsing with bounded helpers Sasha Levin
` (17 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:27 UTC (permalink / raw)
To: patches, stable
Cc: Shiwu Zhang, Alex Deucher, Sasha Levin, christian.koenig, airlied,
simona, amd-gfx, dri-devel, linux-kernel
From: Shiwu Zhang <shiwu.zhang@amd.com>
[ Upstream commit 6229898d46c0cbc238a6fe9f11c1ea12cf8bb9c5 ]
Clamp the buffer postion to write by setting the bin attribute
to the maximum buffer size so that VFS layer will block the
out-of-bounds accessing.
Signed-off-by: Shiwu Zhang <shiwu.zhang@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:
## Phase 1: Commit Message Forensics
### Step 1.1: Subject Line
**Record:** `[drm/amdgpu]` `[fix]` — buffer overflow during vBIOS (IFWI)
update via `psp_vbflash` sysfs interface.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Shiwu Zhang `<shiwu.zhang@amd.com>` (author)
- **Reviewed-by:** Alex Deucher `<alexander.deucher@amd.com>` (amdgpu
maintainer)
- **Signed-off-by:** Alex Deucher (maintainer ack)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable`, or `Tested-by:`
tags
- Notable: maintainer review is a strong quality signal; no
syzbot/fuzzer report
### Step 1.3: Body Analysis
**Record:**
- **Bug:** `psp_vbflash` `bin_attribute` has `.size = 0`, so the
sysfs/VFS layer does not enforce write bounds;
`amdgpu_psp_vbflash_write()` can `memcpy()` past the 16 MiB
`kvmalloc()` buffer.
- **Symptom:** heap buffer overflow on write to
`/sys/class/drm/card*/device/psp_vbflash` with out-of-bounds
offset/length.
- **Fix:** set `.size = AMD_VBIOS_FILE_MAX_SIZE_B` (16 MiB) so
`sysfs_kf_bin_write()` clamps writes.
- **Root cause:** missing sysfs size limit; driver-side check only
tracks cumulative `vbflash_image_size`, not `pos + count`.
### Step 1.4: Hidden Bug Fix?
**Record:** No — explicitly labeled as a buffer overflow fix.
---
## Phase 2: Diff Analysis
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c` (+1/-1)
- **Function/struct:** `psp_vbflash_bin_attr`
- **Scope:** single-line surgical fix in one file
### Step 2.2: Code Flow Change
**Record:**
- **Before:** `.size = 0` → inode `i_size = 0` → `sysfs_kf_bin_write()`
skips bounds check (`if (size)` is false).
- **After:** `.size = AMD_VBIOS_FILE_MAX_SIZE_B` → sysfs rejects `pos >=
size` with `-EFBIG` and clamps `count` to `size - pos`.
- **Path:** sysfs write to `psp_vbflash` on IFWI-capable AMDGPU
(Navi3x+).
### Step 2.3: Bug Mechanism
**Record:** **Buffer overflow / out-of-bounds write (memory safety).**
Vulnerable write path in this tree:
```4210:4212:drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
mutex_lock(&adev->psp.mutex);
memcpy(adev->psp.vbflash_tmp_buf + pos, buffer, count);
adev->psp.vbflash_image_size += count;
```
Sysfs enforcement when `size == 0`:
```157:161:fs/sysfs/file.c
if (size) {
if (size <= pos)
return -EFBIG;
count = min_t(ssize_t, count, size - pos);
}
```
With `.size = 0`, a user in the device group can seek past 16 MiB and
overflow the kmalloc'd buffer.
### Step 2.4: Fix Quality
**Record:** Obviously correct — `.size` matches the allocation size
(`AMD_VBIOS_FILE_MAX_SIZE_B`). Minimal, no API change. Very low
regression risk.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame
**Record:**
- `.size = 0` introduced in `521289d2a279b2` / `8424f2ccb3c0d`
(2022–2023).
- `psp_vbflash` interface present since `8424f2ccb3c0d` (May 2022).
- IFWI visibility gated by `sup_ifwi_up` since `e7347f1c73cd2` (Jul
2023); expanded in `b3dd2903b09c6`, `c09910b511de0` (2025).
### Step 3.2: Fixes: Tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related Changes
**Record:**
- Part of a 3-patch series (May 2026): (1) ww_mutex/GEM leaks, **(2)
this overflow fix**, (3) concurrent allocation mutex.
- Patch 2/3 is standalone; patch 3/3 addresses a separate race.
- Fix **not merged** in this tree (`.size = 0` still at line 4275).
### Step 3.4: Author Context
**Record:** Shiwu Zhang is an AMD amdgpu contributor; Alex Deucher
reviewed.
### Step 3.5: Dependencies
**Record:** None. One-line change; `AMD_VBIOS_FILE_MAX_SIZE_B` already
defined at line 47.
---
## Phase 4: Mailing List and External Research
### Step 4.1: Original Discussion
**Record:**
- **URL:** https://lists.freedesktop.org/archives/amd-
gfx/2026-May/144957.html
- **Series:** PATCH 2/3, May 20, 2026
- No stable nomination found in the thread snippet; no NAKs observed
- `b4 dig -c <hash>` not run — commit not in this checkout (no local
commitish)
### Step 4.2: Reviewers
**Record:** Alex Deucher reviewed (maintainer). Full recipient list via
`b4 dig -w` unavailable without commit hash.
### Step 4.3: Bug Report
**Record:** No external bug report or syzbot link; vulnerability
identified by driver author during review.
### Step 4.4: Related Patches
**Record:** Patches 1/3 and 3/3 are separate issues (leaks, concurrent
alloc). Not prerequisites for this fix.
### Step 4.5: Stable List
**Record:** Not searched separately; prior related commit
`fe56c6ee04570` was nominated with `Cc: stable@vger.kernel.org`.
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `amdgpu_psp_vbflash_write()`, `psp_vbflash_bin_attr`,
`amdgpu_bin_flash_attr_is_visible()`
### Step 5.2: Callers
**Record:** sysfs write path → `sysfs_kf_bin_write()` →
`amdgpu_psp_vbflash_write()`. Triggered by userspace writes to
`psp_vbflash`.
### Step 5.3: Callees
**Record:** `kvmalloc(AMD_VBIOS_FILE_MAX_SIZE_B)`, `memcpy()`,
`mutex_lock/unlock`
### Step 5.4: Reachability
**Record:**
- Exposed when `adev->psp.sup_ifwi_up` is true (PSP 13.0.0/7/10/12,
14.0.2/3 per `psp_early_init()`).
- Mode `0660` — root and device group (typically `render`/`video`).
- Reachable from userspace by privileged/group members on supported
dGPUs (Navi3x+ IFWI flashing per
`Documentation/gpu/amdgpu/flashing.rst`).
### Step 5.5: Similar Patterns
**Record:** Related bounds-checking work by Lijo Lazar on VBIOS parsing
(`atom.c`, Jun 2026) is a separate code path.
---
## Phase 6: Cross-Reference Against Local Tree (v6.18.44)
### Step 6.1: Buggy Code Present?
**Record:** **Yes.** `git describe HEAD` → `v6.18.44`. `.size = 0` at
line 4275; vulnerable `memcpy()` at line 4211. `vbflash` ancestor commit
`8424f2ccb3c0d` is in this tree.
### Step 6.2: Backport Complications
**Record:** Clean one-line apply expected. No structural conflicts
observed.
### Step 6.3: Fix Already Present?
**Record:** **No.** `git log --grep="buffer overflow"` on `amdgpu_psp.c`
returns nothing; `.size = 0` still present.
---
## Phase 7: Subsystem Context
### Step 7.1: Subsystem / Criticality
**Record:** `drivers/gpu/drm/amd/amdgpu` — **IMPORTANT** (GPU driver,
kernel memory safety on reachable sysfs path).
### Step 7.2: Activity
**Record:** Actively maintained; recent IFWI support commits in 2025.
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** Users of AMDGPU with IFWI update support (Navi3x+ dGPUs with
supported PSP versions). Not universal, but real production hardware.
### Step 8.2: Trigger Conditions
**Record:** Write to `psp_vbflash` with `pos + count > 16 MiB` (e.g.,
`lseek` + `write`). Requires membership in device group or root — not
fully unprivileged, but still a kernel memory corruption primitive for
local attackers with GPU access.
### Step 8.3: Failure Mode
**Record:** Heap buffer overflow in kernel context → potential crash,
memory corruption, or local privilege escalation. **Severity: HIGH**
(security-relevant memory safety bug).
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH — closes exploitable overflow on documented flashing
interface
- **Risk:** VERY LOW — one-line, matches existing allocation bound,
reviewed by maintainer
- **Ratio:** Strongly favors backport
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Summary
**FOR:**
- Real, verifiable buffer overflow (sysfs bypass + unbounded `memcpy`)
- Security-relevant memory safety fix
- One-line, maintainer-reviewed, obviously correct
- Buggy code present and unfixed in v6.18.44
- Feature is exposed on supported production hardware
**AGAINST:**
- Requires device-group membership (not arbitrary unprivileged user)
- Part of a 3-patch series (but this patch is self-contained)
- No fuzzer report or CVE (yet)
**Unresolved:** Whether patch 3/3 (concurrent alloc race) should also be
backported — separate issue.
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — mechanism verified in
`fs/sysfs/file.c`; maintainer reviewed
2. Fixes a real bug? **PASS** — heap overflow on sysfs write
3. Important issue? **PASS** — buffer overflow / potential local
escalation
4. Small and contained? **PASS** — 1 line, 1 file
5. No new features/APIs? **PASS** — bounds enforcement only
6. Can apply to local tree? **PASS** — buggy code present, clean apply
### Step 9.3: Exception Category
**Record:** Security/memory-safety fix (not device ID, quirk, or docs).
### Step 9.4: Decision Rationale
For **Linux 6.18.44**, the `psp_vbflash` sysfs interface allocates a 16
MiB buffer but advertises unlimited size to the VFS layer. A group-
privileged user can trigger a kernel heap overflow with an out-of-bounds
write. The fix correctly delegates bounds enforcement to sysfs by
setting `.size` to the allocation limit. It is minimal, maintainer-
reviewed, and the vulnerable code is present and unfixed in this tree.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body; no syzbot/Fixes tags
- **[Phase 2]** Read diff and `amdgpu_psp_vbflash_write()` /
`psp_vbflash_bin_attr` in tree
- **[Phase 2]** Verified `sysfs_kf_bin_write()` skips bounds when `size
== 0` (`fs/sysfs/file.c:157-161`)
- **[Phase 3]** `git describe HEAD` → `v6.18.44`; Makefile confirms
6.18.44
- **[Phase 3]** `git blame` on line 4275 → `.size = 0` since 2023
- **[Phase 3]** `git log -S "psp_vbflash_bin_attr"` → introduced
`8424f2ccb3c0d` (2022)
- **[Phase 3]** `git merge-base --is-ancestor 8424f2ccb3c0d HEAD` →
ancestor confirmed
- **[Phase 3]** `git log --grep="buffer overflow"` on `amdgpu_psp.c` →
no fix merged
- **[Phase 4]** WebFetch lore thread:
https://lists.freedesktop.org/archives/amd-gfx/2026-May/144957.html —
PATCH 2/3 confirmed
- **[Phase 4]** UNVERIFIED: `b4 dig -c` — commit not in local tree, no
commitish available
- **[Phase 4]** UNVERIFIED: `b4 dig -w` / `-a` — same reason
- **[Phase 5]** Read `amdgpu_bin_flash_attr_is_visible()` — `0660` when
`sup_ifwi_up`
- **[Phase 5]** Read `psp_early_init()` — `sup_ifwi_up` set for PSP
13.0.0/7/10/12, 14.0.2/3
- **[Phase 5]** Read `Documentation/gpu/amdgpu/flashing.rst` — documents
`psp_vbflash` userspace interface
- **[Phase 6]** Confirmed `.size = 0` at line 4275 (fix not applied)
- **[Phase 6]** Confirmed `AMD_VBIOS_FILE_MAX_SIZE_B` defined at line 47
- **[Phase 8]** Assessed severity as HIGH based on verified overflow
mechanism
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 9f3581ce492f3..346e9c9cde40c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -4290,7 +4290,7 @@ static ssize_t amdgpu_psp_vbflash_read(struct file *filp, struct kobject *kobj,
*/
static const struct bin_attribute psp_vbflash_bin_attr = {
.attr = {.name = "psp_vbflash", .mode = 0660},
- .size = 0,
+ .size = AMD_VBIOS_FILE_MAX_SIZE_B,
.write = amdgpu_psp_vbflash_write,
.read = amdgpu_psp_vbflash_read,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: harden FRU PIA parsing with bounded helpers
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (19 preceding siblings ...)
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: fix buffer overflow during vBIOS update Sasha Levin
@ 2026-08-31 13:27 ` Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Unwind debug trap enable on copy_to_user failure Sasha Levin
` (16 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:27 UTC (permalink / raw)
To: patches, stable
Cc: Stanley.Yang, Tao Zhou, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: "Stanley.Yang" <Stanley.Yang@amd.com>
[ Upstream commit c990c05eb6c74c98d1ff3acf67a19015312820b7 ]
Replace the open-coded TLV walk with fru_pia_advance()
and fru_pia_copy_field() helpers that bound every read
by the actual EEPROM data length, preventing out-of-bounds
reads on truncated or malformed FRU data.
Signed-off-by: Stanley.Yang <Stanley.Yang@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:
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: PARSE THE SUBJECT LINE
**Record:** `[drm/amdgpu]` `[harden]` — Harden FRU (Field Replaceable
Unit) Product Info Area (PIA) parsing by replacing open-coded TLV
walking with bounded helper functions.
### Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
**Record:**
- **Fixes:** — not present (expected for manual review)
- **Reported-by:** — none
- **Tested-by:** — none
- **Reviewed-by:** Tao Zhou \<tao.zhou1@amd.com\>
- **Acked-by:** — none
- **Link:** — none
- **Cc: stable@vger.kernel.org:** — absent (not a negative signal)
- **Signed-off-by:** Stanley.Yang \<Stanley.Yang@amd.com\>, Alex Deucher
\<alexander.deucher@amd.com\> (ignore pipeline SOBs)
Notable: reviewed by AMD developer; no fuzzer or user bug reports cited.
### Step 1.3: ANALYZE COMMIT BODY
**Record:**
- **Bug described:** Open-coded TLV walk in FRU PIA parsing does not
bound reads against actual EEPROM buffer length; truncated or
malformed FRU data can cause out-of-bounds reads.
- **Symptom/failure mode:** Out-of-bounds kernel memory reads when
parsing malformed/truncated FRU EEPROM TLV fields.
- **Version info:** none stated.
- **Root cause:** TLV cursor advancement (`addr += 1 + (pia[addr] &
0x3F)`) and `memcpy()` use field-length bytes without ensuring the
cursor and copy length stay within the allocated `pia` buffer (`len`).
### Step 1.4: DETECT HIDDEN BUG FIXES
**Record:** Not disguised — this is an explicit memory-safety hardening
fix. "Harden" and "preventing out-of-bounds reads" clearly describe a
buffer over-read bug fix, not cosmetic cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: INVENTORY THE CHANGES
**Record:**
- **Files:** `drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c` only (~37
lines added helpers, ~43 lines changed in parsing loop; net ~+37/-6 in
parsing region)
- **Functions added:** `fru_pia_advance()`, `fru_pia_copy_field()`
- **Functions modified:** `amdgpu_fru_get_product_info()`
- **Scope:** single-file, surgical fix within one parsing function
### Step 2.2: CODE FLOW CHANGE (per hunk)
**Record:**
1. **New helpers (before `amdgpu_fru_get_product_info`):**
- *Before:* no shared TLV walking helpers.
- *After:* `fru_pia_advance()` checks `*addr >= len` before reading
`pia[*addr]`; `fru_pia_copy_field()` validates header presence and
uses `min3(field_len, dst_size-1, len-addr-1)` for bounded
`memcpy()`.
2. **Manufacturer/product/serial/fru_id field extraction:**
- *Before:* `if (addr + 1 >= len) goto Out` then `memcpy(...,
min_t(sizeof(dst), pia[addr] & 0x3F))`; advances via `addr += 1 +
(pia[addr] & 0x3F)` often without prior bounds check.
- *After:* each field uses `fru_pia_copy_field()` (bounded copy) and
`fru_pia_advance()` (bounded advance); failure jumps to `Out`.
3. **Skip fields (Product Version, Asset Tag):**
- *Before:* unconditional `addr += 1 + (pia[addr] & 0x3F)` with no
bounds check (lines 251, 254, 262, 265 in current tree).
- *After:* `fru_pia_advance()` returns false on overrun, triggering
`goto Out`.
### Step 2.3: BUG MECHANISM
**Record:** **Category:** buffer over-read / out-of-bounds access.
**Specific mechanisms in current 6.18.44 code:**
1. **Unchecked TLV advance** — e.g. at lines 251–254:
```250:255:drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
/* Go to the Product Version field. */
addr += 1 + (pia[addr] & 0x3F);
/* Go to the Product Serial Number field. */
addr += 1 + (pia[addr] & 0x3F);
```
If `addr` is near `len` or a prior field length is inflated,
`pia[addr]` reads past the kmalloc buffer.
2. **Unbounded memcpy** — e.g. at lines 227–229:
```227:229:drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
memcpy(fru_info->manufacturer_name, pia + addr + 1,
min_t(size_t, sizeof(fru_info->manufacturer_name),
pia[addr] & 0x3F));
```
Copy length is capped by destination size and TLV length byte, but
**not** by remaining buffer bytes (`len - addr - 1`). A field claiming
63 bytes with only a few bytes remaining causes OOB read.
Checksum validation (lines 211–217) does not prevent structurally
inconsistent TLV lengths within a checksum-valid PIA.
### Step 2.4: FIX QUALITY
**Record:**
- Fix is obviously correct: every read/advance is bounded by `len`.
- Minimal scope: adds two static helpers, replaces inline parsing.
- Low regression risk: same parsing logic, stricter bounds; failure
paths already go to `Out` and return 0.
- `min3()` exists in this tree (`include/linux/minmax.h`).
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: BLAME THE CHANGED LINES
**Record:**
- Buggy TLV walk introduced in `0dbf2c5626253` ("drm/amdgpu: Interpret
IPMI data for product information (v2)", 2022-11-17) by Luben Tuikov.
- Field additions in `ac6b1f275f17b` and `8a2b51392ac4a` (2023-10-04)
retained the same unchecked advance pattern.
- Prior OOB-related FRU fix: `02b865f88b4e4` (2021), `00b14ce075732`
(2022) — shows this subsystem has a history of bounds fixes.
- Bug present since ~6.2; confirmed present in this 6.18.44 tree.
### Step 3.2: FOLLOW Fixes: TAG
**Record:** No `Fixes:` tag. N/A.
### Step 3.3: FILE HISTORY FOR RELATED CHANGES
**Record:** Recent FRU commits in tree include `fd0c6bd82d19c` (increase
FRU File Id buffer), `25907304cfce5` (fetch FRU for smu_v13_0_12),
`a8558fce7ad0c` (avoid FRU on APU). No existing bounded-TLV fix found.
Standalone fix, not part of a multi-patch series in this tree.
### Step 3.4: AUTHOR'S OTHER COMMITS
**Record:** Stanley.Yang has multiple amdgpu commits (RAS, VCN, eeprom
fixes) but is not the original FRU author. Reviewed by Tao Zhou; signed
off by Alex Deucher (amdgpu maintainer).
### Step 3.5: DEPENDENT/PREREQUISITE COMMITS
**Record:** No prerequisites identified. Commit not in this tree
(candidate only). Diff context shows `kzalloc_obj()` on mainline; local
tree uses `kzalloc(sizeof(*adev->fru_info), GFP_KERNEL)` — PIA parsing
portion applies independently. No dependency on missing code structures.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: ORIGINAL PATCH DISCUSSION
**Record:** Commit hash not in local tree; `b4 dig -c` cannot be run.
`b4 dig -S` is not supported. Lore.kernel.org search blocked by anti-bot
page. **UNVERIFIED:** original submission thread, series revisions,
reviewer stable nominations.
### Step 4.2: REVIEWERS
**Record:** **UNVERIFIED** via b4 -w. Commit message lists Reviewed-by:
Tao Zhou, Signed-off-by: Alex Deucher.
### Step 4.3: BUG REPORT
**Record:** No Reported-by, Link, or syzbot reference. No external bug
report to follow.
### Step 4.4: RELATED PATCHES/SERIES
**Record:** Appears standalone. Related historical fixes in same file
(`02b865f`, `00b14ce`) addressed similar OOB concerns in older FRU
parsing code.
### Step 4.5: STABLE MAILING LIST
**Record:** **UNVERIFIED** — lore search unavailable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: KEY FUNCTIONS
**Record:** `fru_pia_advance()`, `fru_pia_copy_field()` (new);
`amdgpu_fru_get_product_info()` (modified).
### Step 5.2: TRACE CALLERS
**Record:**
- `amdgpu_fru_get_product_info()` called from `amdgpu_device_init()` at
line 3307 of `amdgpu_device.c`.
- `amdgpu_device_init()` called from `amdgpu_driver_load_kms()` in
`amdgpu_kms.c` line 148.
- **Context:** GPU driver probe/load path during PCI/DRM device
initialization.
- `amdgpu_fru_sysfs_init()` at line 4873 exposes sysfs attributes but
does not re-parse FRU data.
### Step 5.3: TRACE CALLEES
**Record:** `is_fru_eeprom_supported()`, `amdgpu_eeprom_read()`,
`kzalloc()`, `kfree()`, `memcpy()`, `sprintf()` (default serial),
`dev_err()`.
### Step 5.4: CALL CHAIN / REACHABILITY
**Record:** PCI probe → `amdgpu_driver_load_kms()` →
`amdgpu_device_init()` → `amdgpu_fru_get_product_info()` → PIA TLV
parse. Triggered on every boot for supported AMD server GPUs with
accessible FRU EEPROM. Not directly userspace-syscall reachable, but
runs automatically on driver load when hardware matches (Vega20 server
SKUs, D603, Aldebaran, SMU v13.0.6/v13.0.14, etc.).
### Step 5.5: SIMILAR PATTERNS
**Record:** Same unchecked `addr += 1 + (pia[addr] & 0x3F)` pattern
repeated 6+ times in current code. AMD previously fixed similar FRU OOB
issues in `02b865f88b4e4` and `00b14ce075732`.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE
### Step 6.1: DOES BUGGY CODE EXIST?
**Record:** **YES.** Local tree is **v6.18.44 / 6.18.44**.
`amdgpu_fru_eeprom.c` lines 220–270 contain the vulnerable unchecked TLV
walk. Bug introduced November 2022 (`0dbf2c5626253`), well before 6.18
branch.
### Step 6.2: BACKPORT COMPLICATIONS
**Record:** Expected **clean apply** for the PIA parsing helpers and
loop replacement. Minor context difference: mainline diff shows
`kzalloc_obj()` but local tree uses `kzalloc()` — unrelated to the fix
hunks. No significant refactoring conflicts in recent file history
(`a3e510fd69c31` dev_* conversion is already present).
### Step 6.3: RELATED FIXES ALREADY PRESENT?
**Record:** No `fru_pia_advance`/`fru_pia_copy_field` or "harden FRU
PIA" commit in tree. `git log --grep='harden FRU'` returned empty. Fix
not yet applied.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: SUBSYSTEM CRITICALITY
**Record:** **Subsystem:** `drm/amdgpu` driver — FRU EEPROM parsing for
AMD server GPUs. **Criticality:** PERIPHERAL (hardware-specific,
server/datacenter GPUs only), but touches kernel memory safety during
probe.
### Step 7.2: SUBSYSTEM ACTIVITY
**Record:** File actively maintained — 20+ commits since 2022, most
recent in 2025 (dev_* conversion, SMU v13.0.12 support).
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: WHO IS AFFECTED
**Record:** Users of AMD server GPUs with FRU EEPROM support (Vega20
D161/D163, Instinct MI D603, Aldebaran, SMU v13.0.6/v13.0.14, etc.). Not
APUs, not VF, not all consumer cards. Config/hardware-specific, but real
production datacenter hardware.
### Step 8.2: TRIGGER CONDITIONS
**Record:** Malformed, truncated, or internally inconsistent FRU Product
Info Area TLV data in on-card EEPROM. Occurs during driver probe
(boot/module load). Not userspace-triggerable directly; requires
corrupt/tampered EEPROM or hardware/firmware fault. Moderately rare but
plausible (manufacturing errors, EEPROM corruption, physical tampering
on servers).
### Step 8.3: FAILURE MODE SEVERITY
**Record:** Out-of-bounds read from kmalloc'd PIA buffer during GPU
init. Potential KASAN splat, kernel oops during probe, or information
leak from adjacent heap data. Severity: **HIGH** for affected hardware
(memory safety during init); **MEDIUM** overall due to narrow
hardware/trigger scope. Does not cause silent data corruption of user
files.
### Step 8.4: RISK-BENEFIT
**Record:**
- **Benefit:** MEDIUM — closes real OOB read in server GPU probe path;
aligns with prior FRU bounds fixes AMD has shipped.
- **Risk:** LOW — small, reviewed, behavior-preserving with stricter
bounds.
- **Ratio:** Benefit outweighs risk for 6.18.y.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: EVIDENCE COMPILED
**FOR backport:**
- Real, verifiable OOB read bug in current 6.18.44 code (unchecked TLV
advance + unbounded memcpy).
- Fixes memory safety during GPU driver probe on affected server
hardware.
- Small, single-file, obviously correct bounded helpers.
- Reviewed by AMD developer; signed off by amdgpu maintainer (Alex
Deucher).
- Same file had prior OOB fixes backported historically.
- Bug present since 2022; code exists in this tree.
- `min3()` available; patch should apply cleanly.
**AGAINST backport:**
- No syzbot report, no user bug report, no CVE cited.
- Very limited hardware population (AMD server GPUs with FRU EEPROM).
- Requires malformed EEPROM data — not commonly triggered.
- Not directly exploitable from userspace.
- Mailing list review context unverified.
**UNRESOLVED:**
- Original lore discussion and whether reviewers nominated for stable.
- Whether any production incident motivated this fix.
### Step 9.2: STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — logic is clear; reviewed by
AMD; no Tested-by but mechanism is verifiable by inspection.
2. Fixes a real bug affecting users? **PASS** — OOB read on server GPU
probe with malformed FRU data.
3. Important issue? **PASS** — kernel memory safety / potential oops
during init (HIGH for affected systems).
4. Small and contained? **PASS** — one file, ~40 lines of meaningful
change.
5. No new features or APIs? **PASS** — parsing hardening only.
6. Can apply to local tree? **PASS** — buggy code confirmed present;
clean apply expected.
### Step 9.3: EXCEPTION CATEGORIES
**Record:** None directly (not device ID, quirk, DT, build fix, or
docs). Standard memory-safety bug fix.
### Step 9.4: DECISION RATIONALE
For **linux-6.18.y** (this checkout): the vulnerable FRU PIA parsing
code is present and has been since the 2022 IPMI rewrite. The fix
addresses a concrete out-of-bounds read that can occur when TLV length
fields in FRU EEPROM data are inconsistent with the actual buffer size —
a scenario checksum validation does not prevent. While the affected
hardware base is narrow (AMD server GPUs), memory-safety fixes in probe
paths are appropriate stable material, especially given AMD's prior
history of backporting similar FRU bounds fixes. The patch is small,
reviewed, and low-risk.
---
## Verification
- [Phase 1] Parsed subject, tags, body: hardening fix for OOB reads;
Reviewed-by Tao Zhou; no Reported-by/syzbot.
- [Phase 2] Read full diff and current `amdgpu_fru_eeprom.c`: confirmed
unchecked advances at lines 251, 254, 262, 265 and unbounded memcpy at
227–229, 237–238, etc.
- [Phase 2] Verified `min3` exists in `include/linux/minmax.h`.
- [Phase 3] `git blame -L 220,270`: buggy walk from `0dbf2c5626253`
(2022-11-17).
- [Phase 3] `git log --oneline -20 -- amdgpu_fru_eeprom.c`: no existing
bounded-helper fix.
- [Phase 3] `git log --grep='harden FRU'`: empty (commit not in tree).
- [Phase 3] `git show 00b14ce075732`, `git show 02b865f88b4e4`: prior
FRU OOB fixes confirmed.
- [Phase 4] `b4 dig -c`: **UNVERIFIED** — commit not in tree.
- [Phase 4] Lore search: **UNVERIFIED** — blocked by anti-bot page.
- [Phase 5] `grep amdgpu_fru_get_product_info`: callers in
`amdgpu_device.c:3307`, init via `amdgpu_kms.c:148`.
- [Phase 6] `git describe HEAD` → v6.18.44; `make kernelversion` →
6.18.44.
- [Phase 6] Read `amdgpu_fru_eeprom.c` lines 220–270: buggy code
confirmed present.
- [Phase 6] `git merge-base --is-ancestor 0dbf2c5626253 HEAD`: buggy
code ancestor in tree.
- [Phase 8] Failure mode: OOB kernel read during probe; severity HIGH
(affected hw) / MEDIUM (overall).
**YES**The background search finished: `git log --grep='harden FRU'`,
`--grep='bounded helpers'`, and `--grep='fru_pia'` all returned nothing,
so this fix is not in the local **6.18.44** tree yet.
That matches what we saw in the file — `amdgpu_fru_eeprom.c` still has
the unchecked TLV walk (e.g. unguarded `addr += 1 + (pia[addr] & 0x3F)`
around lines 251–265).
**Verdict for linux-6.18.y: YES** — real out-of-bounds read on malformed
FRU EEPROM data during server GPU probe; small, reviewed hardening fix
that should apply cleanly.
.../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 95 ++++++++++++-------
1 file changed, 63 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index b0082aa7f3c61..2875627dce8e9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -114,6 +114,43 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
}
}
+/*
+ * IPMI FRU Product Info Area fields are TLV: one type/length byte
+ * (low 6 bits = data length) followed by that many data bytes. These
+ * helpers walk the cursor and copy a single field while bounding all
+ * accesses to the actual buffer length read from the EEPROM.
+ */
+#define FRU_FIELD_LEN(p, a) ((p)[a] & 0x3F)
+
+/* Advance cursor past the current TLV. Returns false if no more data. */
+static bool fru_pia_advance(u32 *addr, const unsigned char *pia, int len)
+{
+ if (*addr >= (u32)len)
+ return false;
+ *addr += 1 + FRU_FIELD_LEN(pia, *addr);
+ return true;
+}
+
+/*
+ * Copy the current TLV's data into dst (NUL-terminated). Returns false if
+ * the TLV header or data would read past the end of pia.
+ */
+static bool fru_pia_copy_field(char *dst, size_t dst_size,
+ const unsigned char *pia, u32 addr, int len)
+{
+ size_t fl;
+
+ if (addr + 1 >= (u32)len)
+ return false;
+
+ fl = min3((size_t)FRU_FIELD_LEN(pia, addr),
+ dst_size - 1,
+ (size_t)(len - addr - 1));
+ memcpy(dst, pia + addr + 1, fl);
+ dst[fl] = '\0';
+ return true;
+}
+
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
{
struct amdgpu_fru_info *fru_info;
@@ -222,52 +259,46 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
* Read Manufacturer Name field whose length is [3].
*/
addr = 3;
- if (addr + 1 >= len)
+ if (!fru_pia_copy_field(fru_info->manufacturer_name,
+ sizeof(fru_info->manufacturer_name),
+ pia, addr, len))
goto Out;
- memcpy(fru_info->manufacturer_name, pia + addr + 1,
- min_t(size_t, sizeof(fru_info->manufacturer_name),
- pia[addr] & 0x3F));
- fru_info->manufacturer_name[sizeof(fru_info->manufacturer_name) - 1] =
- '\0';
/* Read Product Name field. */
- addr += 1 + (pia[addr] & 0x3F);
- if (addr + 1 >= len)
+ if (!fru_pia_advance(&addr, pia, len) ||
+ !fru_pia_copy_field(fru_info->product_name,
+ sizeof(fru_info->product_name),
+ pia, addr, len))
goto Out;
- memcpy(fru_info->product_name, pia + addr + 1,
- min_t(size_t, sizeof(fru_info->product_name), pia[addr] & 0x3F));
- fru_info->product_name[sizeof(fru_info->product_name) - 1] = '\0';
/* Go to the Product Part/Model Number field. */
- addr += 1 + (pia[addr] & 0x3F);
- if (addr + 1 >= len)
+ if (!fru_pia_advance(&addr, pia, len) ||
+ !fru_pia_copy_field(fru_info->product_number,
+ sizeof(fru_info->product_number),
+ pia, addr, len))
goto Out;
- memcpy(fru_info->product_number, pia + addr + 1,
- min_t(size_t, sizeof(fru_info->product_number),
- pia[addr] & 0x3F));
- fru_info->product_number[sizeof(fru_info->product_number) - 1] = '\0';
- /* Go to the Product Version field. */
- addr += 1 + (pia[addr] & 0x3F);
+ /* Skip the Product Version field. */
+ if (!fru_pia_advance(&addr, pia, len))
+ goto Out;
- /* Go to the Product Serial Number field. */
- addr += 1 + (pia[addr] & 0x3F);
- if (addr + 1 >= len)
+ /* Read the Product Serial Number field. */
+ if (!fru_pia_advance(&addr, pia, len) ||
+ !fru_pia_copy_field(fru_info->serial,
+ sizeof(fru_info->serial),
+ pia, addr, len))
goto Out;
- memcpy(fru_info->serial, pia + addr + 1,
- min_t(size_t, sizeof(fru_info->serial), pia[addr] & 0x3F));
- fru_info->serial[sizeof(fru_info->serial) - 1] = '\0';
- /* Asset Tag field */
- addr += 1 + (pia[addr] & 0x3F);
+ /* Skip the Asset Tag field. */
+ if (!fru_pia_advance(&addr, pia, len))
+ goto Out;
/* FRU File Id field. This could be 'null'. */
- addr += 1 + (pia[addr] & 0x3F);
- if ((addr + 1 >= len) || !(pia[addr] & 0x3F))
+ if (!fru_pia_advance(&addr, pia, len) ||
+ !fru_pia_copy_field(fru_info->fru_id,
+ sizeof(fru_info->fru_id),
+ pia, addr, len))
goto Out;
- memcpy(fru_info->fru_id, pia + addr + 1,
- min_t(size_t, sizeof(fru_info->fru_id), pia[addr] & 0x3F));
- fru_info->fru_id[sizeof(fru_info->fru_id) - 1] = '\0';
Out:
kfree(pia);
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Unwind debug trap enable on copy_to_user failure
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (20 preceding siblings ...)
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: harden FRU PIA parsing with bounded helpers Sasha Levin
@ 2026-08-31 13:27 ` Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: fix UAF race in destroy_queue_cpsch Sasha Levin
` (15 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:27 UTC (permalink / raw)
To: patches, stable
Cc: Yongqiang Sun, Alex Deucher, Sasha Levin, Felix.Kuehling,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Yongqiang Sun <Yongqiang.Sun@amd.com>
[ Upstream commit 01112e241e37f9ac98b6f418d93ce2e0b87b7ee0 ]
If kfd_dbg_trap_enable() fails while copying runtime_info to userspace,
it had already activated the trap, set debug_trap_enabled, taken an extra
process reference, and opened the debug event file. Return -EFAULT without
unwinding that state, leaving inconsistent trap state and a refcount
imbalance that could break later DISABLE/ENABLE.
On copy_to_user failure, deactivate the trap and undo the rest of the
enable setup before returning.
Signed-off-by: Yongqiang Sun <Yongqiang.Sun@amd.com>
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:
## Phase 1: Commit Message Forensics
### Step 1.1: Parse the Subject Line
**Record:** `[drm/amdkfd]` `[Unwind]` — On `copy_to_user` failure in
`kfd_dbg_trap_enable()`, undo partial debug-trap enable setup that was
left behind.
### Step 1.2: Parse All Commit Message Tags
**Record:**
- **Fixes:** — none
- **Reported-by:** — none
- **Tested-by:** — none
- **Reviewed-by:** — none
- **Acked-by:** Alex Deucher `<alexander.deucher@amd.com>` (AMD DRM
maintainer)
- **Link:** — none
- **Cc: stable@vger.kernel.org:** — none (expected for manual review)
- **Signed-off-by:** Yongqiang Sun `<Yongqiang.Sun@amd.com>` (author);
Alex Deucher (committer)
Notable: maintainer **Acked-by** only; no syzbot or user reports.
### Step 1.3: Analyze Commit Body
**Record:**
- **Bug:** If `copy_to_user()` fails after `kfd_dbg_trap_enable()` has
activated the HW trap, set `debug_trap_enabled`, taken an extra
`kref`, and opened `dbg_ev_file`, the function returned `-EFAULT`
without undoing that state.
- **Symptom:** Inconsistent trap state; refcount imbalance; later
DISABLE/ENABLE can misbehave.
- **Root cause:** Error path only called `kfd_dbg_trap_deactivate()` but
did not mirror the rest of `kfd_dbg_trap_disable()` cleanup.
- **Version info:** None in the message.
### Step 1.4: Detect Hidden Bug Fixes
**Record:** Not disguised — explicitly an error-path unwind / resource-
leak / state-machine fix.
---
## Phase 2: Diff Analysis
### Step 2.1: Inventory Changes
**Record:**
- **Files:** `drivers/gpu/drm/amd/amdkfd/kfd_debug.c` (+6 / −0)
- **Function:** `kfd_dbg_trap_enable()`
- **Scope:** Single-file, surgical error-path fix
### Step 2.2: Code Flow Change
**Record:** On `copy_to_user()` failure in `kfd_dbg_trap_enable()`:
- **Before:** `kfd_dbg_trap_deactivate(target, false, 0); r = -EFAULT;`
— HW trap deactivated, but `dbg_ev_file`, `debug_trap_enabled`, extra
`kref`, and `debugged_process_count` left as if enable succeeded.
- **After:** Same deactivate, then `fput()` + NULL `dbg_ev_file`,
`atomic_dec(debugged_process_count)`, `debug_trap_enabled = false`,
`kfd_unref_process(target)`, then `-EFAULT`.
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Error-path resource leak + inconsistent state (reference
counting + flag/file leak)
- **Mechanism:** `kref_get()`, `fget()`, `debug_trap_enabled = true`,
and `atomic_inc()` run before `copy_to_user()`. Failure left software
state enabled while userspace received `-EFAULT`.
### Step 2.4: Fix Quality
**Record:** Mirrors the corresponding cleanup in
`kfd_dbg_trap_disable()` (lines 682–692). Minimal, obviously correct.
Low regression risk — only runs on an already-failing path. Does not add
`cancel_work_sync()` or clear `debugger_process`; same gap as the pre-
existing partial `kfd_dbg_trap_deactivate()` unwind.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame Changed Lines
**Record:** Buggy `copy_to_user` error path from Jonathan Kim,
2022-04-05 (`218895820e6fcc`). `kfd_dbg_trap_enable()` with
refcount/file/flag setup from `0ab2d7532b05a` (2023-06-09, “prepare per-
process debug enable and disable”). Bug present since ~v6.5+; definitely
in this tree.
### Step 3.2: Follow Fixes Tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: File History
**Record:** Recent `kfd_debug.c` changes are other debugger fixes (watch
bounds, MES debug, PASID). Fix commit `a50676d5a72a2` is on `all-next`
but **not** on `stable/linux-6.18.y`. Standalone one-commit fix.
### Step 3.4: Author's Other Commits
**Record:** Yongqiang Sun has limited amdkfd history in this tree (e.g.
CWSR overflow fix). Alex Deucher is DRM/AMD maintainer and committed the
fix.
### Step 3.5: Prerequisites
**Record:** No series dependencies. `kfd_dbg_trap_enable()`,
`kfd_dbg_trap_deactivate()`, and `kfd_unref_process()` all exist in this
tree. Applies standalone.
---
## Phase 4: Mailing List and External Research
### Step 4.1: Original Patch Discussion
**Record:** `b4 dig -c a50676d5a72a2` →
https://patch.msgid.link/20260602141422.4982-1-Yongqiang.Sun@amd.com.
Single revision (no `-a` series). Alex Deucher replied with **Acked-by**
in-thread. No NAKs found in mbox. No explicit `Cc: stable` nomination in
thread.
### Step 4.2: Reviewers
**Record:** `b4 dig -w` — CC'd to `amd-gfx@lists.freedesktop.org`. Alex
Deucher reviewed and acked.
### Step 4.3: Bug Report
**Record:** N/A — no `Reported-by` or `Link:` tags. Code-review / error-
path analysis fix.
### Step 4.4: Related Patches
**Record:** Standalone; not part of a multi-patch series.
### Step 4.5: Stable Mailing List
**Record:** Not searched separately; no stable nomination found in patch
thread.
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `kfd_dbg_trap_enable()` (modified); related:
`kfd_dbg_trap_deactivate()`, `kfd_dbg_trap_disable()`,
`kfd_unref_process()`.
### Step 5.2: Callers
**Record:** `kfd_dbg_trap_enable()` called from `kfd_chardev.c` on
`KFD_IOC_DBG_TRAP_ENABLE` (ioctl path ~line 3029). Reached by ROCm/KFD
GPU debugger tooling via `/dev/kfd`.
### Step 5.3: Callees
**Record:** `fget`, `kfd_dbg_trap_activate`, `kref_get`, `atomic_inc`,
`copy_to_user`, `kfd_dbg_trap_deactivate`, `fput`, `kfd_unref_process`.
### Step 5.4: Call Chain / Reachability
**Record:** Userspace debugger → `KFD_IOC_DBG_TRAP` ioctl →
`kfd_dbg_trap_enable()`. `copy_to_user()` fails on invalid/unmapped
userspace buffers (buggy debugger, bad pointer, page fault under memory
pressure). Not a general unprivileged attack surface, but reachable by
authorized KFD clients.
### Step 5.5: Similar Patterns
**Record:** `kfd_dbg_trap_disable()` already performs the full cleanup
the fix adds. The error path was an incomplete subset of disable logic.
---
## Phase 6: Cross-Reference Against Local Tree
### Step 6.1: Does Buggy Code Exist?
**Record:** **Yes.** Tree is **Linux 6.18.44** (`git describe HEAD` →
`v6.18.44`, `VERSION=6 PATCHLEVEL=18 SUBLEVEL=44`). Buggy code at
`kfd_debug.c:817-819`:
```817:819:drivers/gpu/drm/amd/amdkfd/kfd_debug.c
if (copy_to_user(runtime_info, (void *)&target->runtime_info,
copy_size)) {
kfd_dbg_trap_deactivate(target, false, 0);
r = -EFAULT;
```
### Step 6.2: Backport Complications
**Record:** **Clean apply expected.** Fix commit diff matches current
file structure; only 6 lines in one hunk.
### Step 6.3: Related Fixes Already Present?
**Record:** **No.** `git log stable/linux-6.18.y --grep="Unwind debug
trap"` returns nothing. Fix exists on `all-next` (`a50676d5a72a2`) but
not in this stable checkout.
---
## Phase 7: Subsystem and Maintainer Context
### Step 7.1: Subsystem Criticality
**Record:** `drivers/gpu/drm/amd/amdkfd` — **IMPORTANT** (AMD GPU
compute/ROCm KFD driver). Debug-trap path only; not core kernel, but
affects production debugger workflows.
### Step 7.2: Subsystem Activity
**Record:** Actively maintained — recent stable-relevant amdkfd fixes
(debugger auth, overflows, CRIU, NULL deref).
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** Users of AMD KFD GPU debugging (ROCm debugger,
`KFD_IOC_DBG_TRAP_ENABLE`). Requires `CONFIG_HSA_AMD` / amdkfd. Not
universal, but real for that population.
### Step 8.2: Trigger Conditions
**Record:** `copy_to_user()` failure during debug-trap enable — uncommon
but valid (bad userspace buffer). **Likelihood:** low in normal use,
easy to hit with a buggy debugger or invalid pointer. **Privilege:** KFD
device access required.
### Step 8.3: Failure Mode Severity
**Record:**
- Extra `kref` leak on `kfd_process` → process object retained longer
than intended
- `dbg_ev_file` leak → kernel `struct file` refcount leak
- `debug_trap_enabled` stuck `true` while ioctl returned error →
subsequent enable returns `-EALREADY` (verified: line 779-780)
- `debugged_process_count` skew → wrong debugger session accounting
- **Severity:** **MEDIUM-HIGH** for debugger users (broken
retry/disable-enable cycle, resource leaks); **LOW** for non-debug
workloads
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** Restores correct error recovery; prevents leaks and stuck
debug state
- **Risk:** Very low — 6 lines on failure-only path, mirrors existing
disable logic
- **Ratio:** Favorable for stable
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Summary
**FOR backport:**
- Real bug in error path present since 2023
- Resource leaks (`kref`, `struct file`)
- Functional breakage: `-EALREADY` on retry after failed enable
- Small (6 lines), maintainer-acked
- Buggy code confirmed in Linux 6.18.44; fix not yet applied
- Clean backport
**AGAINST backport:**
- No user report or syzbot — code-review discovery
- Affects debugger-only path, not general workloads
- “Important issue” bar is borderline vs crash/security (no oops/UAF
demonstrated)
**Unresolved:** Whether `debugger_process` should also be cleared on
failure (fix matches partial unwind intent, not full disable).
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — mirrors
`kfd_dbg_trap_disable()`; maintainer acked; no Tested-by
2. Fixes a real bug? **PASS** — refcount/file leak and stuck
`debug_trap_enabled`
3. Important issue? **PASS (MEDIUM)** — resource leaks + broken debug
enable/disable state machine
4. Small and contained? **PASS** — 6 lines, one function
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** — code exists; clean apply
### Step 9.3: Exception Categories
**Record:** None (not device ID, quirk, DT, build, or docs). Standard
error-path bug fix.
### Step 9.4: Decision Rationale
For **Linux 6.18.y** specifically: the incomplete unwind in
`kfd_dbg_trap_enable()` is present, the fix is absent, and the patch is
a minimal error-path correction that prevents reference and file leaks
and restores consistent debug-trap state after `-EFAULT`. This matches
the kind of driver error-recovery fixes routinely accepted for stable,
especially with AMD maintainer acknowledgment.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body from provided commit message
and `git show a50676d5a72a2`
- **[Phase 2]** Read diff and current `kfd_debug.c:772-825`,
`kfd_dbg_trap_disable()` at 667-694
- **[Phase 3]** `git blame -L 817,820` → `218895820e6fcc` (2022); `git
show 0ab2d7532b05a` → introduced enable setup (2023); `git log
stable/linux-6.18.y --grep="Unwind debug trap"` → empty
- **[Phase 3]** `git log --oneline -5 --
drivers/gpu/drm/amd/amdkfd/kfd_debug.c`
- **[Phase 4]** `b4 dig -c a50676d5a72a2` → lore URL; `b4 dig -m
/tmp/kfd_debug_trap.mbx` → Alex Deucher Acked-by in thread; `b4 dig
-a` → no revisions
- **[Phase 5]** `grep kfd_dbg_trap_enable` → caller in
`kfd_chardev.c:3029`; `grep debug_trap_enabled` across amdkfd
- **[Phase 6]** `git describe HEAD` → `v6.18.44`; Makefile `6.18.44`;
confirmed buggy lines at 817-819 without fix
- **[Phase 6]** `git log stable/linux-6.18.y..all-next --
drivers/gpu/drm/amd/amdkfd/kfd_debug.c` → fix commit listed, not in
stable
- **[Phase 6]** `git branch --contains a50676d5a72a2` → `all-next` and
others, not `stable/linux-6.18.y`
- **[Phase 7]** `git log --oneline -20 -- drivers/gpu/drm/amd/amdkfd/` →
active subsystem
- **[Phase 8]** Verified `-EALREADY` guard at line 779-780; verified
`kfd_dbg_trap_disable()` cleanup pattern at 682-692
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_debug.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c
index 986cb297de8f8..78e1dfdb27147 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c
@@ -816,6 +816,12 @@ int kfd_dbg_trap_enable(struct kfd_process *target, uint32_t fd,
if (copy_to_user(runtime_info, (void *)&target->runtime_info, copy_size)) {
kfd_dbg_trap_deactivate(target, false, 0);
+ fput(target->dbg_ev_file);
+ target->dbg_ev_file = NULL;
+ if (target->debugger_process)
+ atomic_dec(&target->debugger_process->debugged_process_count);
+ target->debug_trap_enabled = false;
+ kfd_unref_process(target);
r = -EFAULT;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: fix UAF race in destroy_queue_cpsch
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (21 preceding siblings ...)
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Unwind debug trap enable on copy_to_user failure Sasha Levin
@ 2026-08-31 13:27 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: Prefer ROM BAR for default VGA device Sasha Levin
` (14 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:27 UTC (permalink / raw)
To: patches, stable
Cc: Alysa Liu, Amir Shetaia, Alex Deucher, Sasha Levin,
Felix.Kuehling, christian.koenig, airlied, simona, amd-gfx,
dri-devel, linux-kernel
From: Alysa Liu <Alysa.Liu@amd.com>
[ Upstream commit ac081deaf16a639ea7dff2f285fe421a33c1ade0 ]
wait_on_destroy_queue() drops locks to wait for queue resume, allowing
a concurrent destroy to free the queue. Use is_being_destroyed flag to
serialize destruction.
Reviewed-by: Amir Shetaia <Amir.Shetaia@amd.com>
Signed-off-by: Alysa Liu <Alysa.Liu@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:
## Phase 1: Commit Message Forensics
### Step 1.1: Subject Line
**Record:** `[drm/amdkfd]` `[fix]` — UAF race in `destroy_queue_cpsch`
during concurrent queue destruction.
### Step 1.2: Commit Message Tags
**Record:**
- **Reviewed-by:** Amir Shetaia \<Amir.Shetaia@amd.com\> (AMD reviewer)
- **Signed-off-by:** Alysa Liu \<Alysa.Liu@amd.com\> (author)
- **Signed-off-by:** Alex Deucher \<alexander.deucher@amd.com\> (DRM/AMD
maintainer)
- **Absent (expected):** Fixes:, Reported-by:, Link:, Tested-by:, Cc:
stable@vger.kernel.org
Notable: maintainer sign-off and subsystem reviewer present; no syzbot
or user bug report.
### Step 1.3: Commit Body Analysis
**Record:**
- **Bug:** `wait_on_destroy_queue()` drops `dqm` lock and process mutex
while waiting for a suspended queue to resume. A concurrent destroy
can complete and free the queue while the first caller still holds a
pointer to it.
- **Symptom:** Use-after-free when the first destroy path resumes after
the wait.
- **Root cause:** No serialization of concurrent destruction;
`is_being_destroyed` was set but not checked at entry; not cleared on
error paths.
- **Fix:** Check `is_being_destroyed` and return `-EBUSY` for concurrent
destroyers; clear the flag on wait failure and on the debug-queue
error path.
### Step 1.4: Hidden Bug Fix Detection
**Record:** Not disguised — explicitly labeled UAF race. The
`failed_try_destroy_debugged_queue` cleanup also fixes a stuck-flag bug
(queue permanently marked as being destroyed after `-EBUSY`).
---
## Phase 2: Diff Analysis
### Step 2.1: Change Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c` (+6
lines net)
- **Functions:** `wait_on_destroy_queue()`, `destroy_queue_cpsch()`
error path
- **Scope:** Single-file, surgical fix (3 small hunks)
### Step 2.2: Code Flow Changes
**Record:**
- **Hunk 1 (wait_on_destroy_queue entry):** Before → unconditionally set
`is_being_destroyed = true`. After → if already set, return `-EBUSY`
immediately (serialize concurrent destroys).
- **Hunk 2 (wait_on_destroy_queue exit):** Before → on
`wait_event_interruptible()` failure (signal), flag stayed true
forever. After → clear `is_being_destroyed` on non-zero `ret` so
destroy can be retried.
- **Hunk 3 (failed_try_destroy_debugged_queue):** Before → returned
`-EBUSY` for debug queues but left `is_being_destroyed = true`. After
→ clears flag before unlock/return.
### Step 2.3: Bug Mechanism
**Record:** **Category:** Use-after-free / race condition (reference-
counting-like serialization via flag).
**Mechanism verified in code:**
1. `kfd_ioctl_destroy_queue()` holds `p->mutex`.
2. `destroy_queue_cpsch()` → `dqm_lock()` → `wait_on_destroy_queue()`.
3. When `debug_trap_enabled && is_suspended`, `wait_on_destroy_queue()`
calls `dqm_unlock()`, `mutex_unlock(&q->process->mutex)`, then blocks
on `wait_event_interruptible(dqm->destroy_wait,
!q->properties.is_suspended)`.
4. With mutex released, a second thread can enter
`kfd_ioctl_destroy_queue()` for the same queue.
5. Without the fix, the second thread proceeds through destruction;
`pqm_destroy_queue()` calls `uninit_queue()` and frees resources.
6. First thread wakes and continues using freed `struct queue` → UAF.
The `is_being_destroyed` flag was already used in
`suspend_single_queue()` (line 1075) to block suspend during destroy,
but was never checked at the destroy entry point.
### Step 2.4: Fix Quality
**Record:** Fix is minimal and obviously correct — standard serialize-
with-flag pattern. Low regression risk: `-EBUSY` on concurrent destroy
is consistent with existing error handling in `pqm_destroy_queue()`
(non-`-ETIME`/non-`-EIO` errors skip freeing). No new APIs or data
structures.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame
**Record:** `wait_on_destroy_queue()` and `is_being_destroyed` usage
introduced in commit `a70a93fa568b4` ("drm/amdkfd: add debug suspend and
resume process queues operation", 2023-06-09, Jonathan Kim). Confirmed
ancestor of HEAD in this tree. Bug has existed since that commit.
### Step 3.2: Fixes: Tag
**Record:** N/A — no Fixes: tag in commit message.
### Step 3.3: Related File History
**Record:** Recent `amdkfd` stable-relevant fixes in this tree include
NULL deref, overflow, list corruption, and UAF fixes — active
maintenance area. No prior fix for this specific race found (`git log
--grep="destroy_queue_cpsch"` and `--grep="is_being_destroyed"` show
only the introducing commit).
### Step 3.4: Author Context
**Record:** Alysa Liu has other security/reliability fixes in
amdgpu/amdkfd in this tree (e.g., `7885eb335d8f9` VM acquire UAF). Alex
Deucher is AMDGPU maintainer.
### Step 3.5: Dependencies
**Record:** Standalone — uses existing `is_being_destroyed` field in
`kfd_priv.h` (line 521), already present since `a70a93fa568b4`. No
series dependencies.
---
## Phase 4: Mailing List and External Research
### Step 4.1: Original Discussion
**Record:** `b4 dig -c <commit>` could not be run — commit is not in
this checkout. Lore.kernel.org search blocked (Anubis bot protection).
**UNVERIFIED:** full mailing list review thread.
### Step 4.2: Reviewers
**Record:** **UNVERIFIED** via b4 dig -w. Commit message shows Reviewed-
by from AMD and Signed-off-by from maintainer.
### Step 4.3: Bug Report
**Record:** N/A — no Reported-by or Link tags.
### Step 4.4: Related Patches/Series
**Record:** Appears standalone; not part of a multi-patch series.
### Step 4.5: Stable List History
**Record:** **UNVERIFIED** — could not search lore stable archive.
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `wait_on_destroy_queue()`, `destroy_queue_cpsch()`, callers
`pqm_destroy_queue()`, `kfd_ioctl_destroy_queue()`.
### Step 5.2: Callers
**Record:**
- `destroy_queue_cpsch` assigned at line 2953 as
`dqm->ops.destroy_queue` (CP scheduling path).
- Called from `pqm_destroy_queue()` (line 550).
- `pqm_destroy_queue()` called from `kfd_ioctl_destroy_queue()` (line
429) under `p->mutex`.
- Userspace entry: `KFD_IOC_DESTROY_QUEUE` ioctl on `/dev/kfd`.
### Step 5.3: Callees
**Record:** `wait_on_destroy_queue()` calls `dqm_unlock/lock`,
`mutex_unlock/lock`, `wait_event_interruptible()`. On success path,
`destroy_queue_cpsch()` calls `mqd_mgr->free_mqd()` after unlock — the
UAF window is between wait return and completion of destroy.
### Step 5.4: Reachability
**Record:** **Userspace-reachable** for processes with KFD access.
Trigger requires:
- `debug_trap_enabled` on the process (KFD debugger path)
- Queue `is_suspended`
- Concurrent destroy while first destroy waits (mutex dropped during
wait)
Narrower than everyday compute, but real for ROCm debugger / debug-trap
workloads.
### Step 5.5: Similar Patterns
**Record:** `suspend_single_queue()` already checks `is_being_destroyed`
(line 1075) — this fix completes the symmetric protection for the
destroy side.
---
## Phase 6: Cross-Reference Against Local Tree (6.18.44)
### Step 6.1: Buggy Code Present?
**Record:** **YES.** Tree is `v6.18.44` (Makefile: 6.18.44). Current
`wait_on_destroy_queue()` at lines 2480–2506 lacks all three fix hunks.
`is_being_destroyed` field exists. Introducing commit `a70a93fa568b4` is
an ancestor of HEAD.
### Step 6.2: Backport Complications
**Record:** **Clean apply.** `git apply --check` succeeded for all three
hunks against current file (minor 1-line offset on first hunk). No
structural refactoring conflicts.
### Step 6.3: Related Fixes Already Present?
**Record:** **NO** — grep and `git log -S "is_being_destroyed"` show no
subsequent fix for this race in this tree.
---
## Phase 7: Subsystem Context
### Step 7.1: Subsystem Criticality
**Record:** `drivers/gpu/drm/amd/amdkfd/` — **IMPORTANT** (AMD GPU
compute/KFD/ROCm). Not universal like mm/VFS, but affects all KFD users
on AMDGPU.
### Step 7.2: Activity Level
**Record:** Actively maintained — multiple recent amdkfd security and
stability fixes in 6.18.y (NULL deref, overflow, list corruption, CRIU
fixes).
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** AMD GPU users with `CONFIG_DRM_AMDGPU` + KFD enabled,
specifically processes using debug-trap with suspended queues.
Config/driver-specific, not platform-specific.
### Step 8.2: Trigger Conditions
**Record:**
- Process has `debug_trap_enabled`
- Target queue is `is_suspended`
- Two concurrent destroy attempts (or destroy during wait after mutex
drop)
- **Likelihood:** Uncommon but realistic in debugger scenarios (multi-
threaded teardown, signal interruption + retry)
- **Privilege:** Requires access to `/dev/kfd` (not arbitrary
unprivileged, but reachable by compute users)
### Step 8.3: Failure Mode Severity
**Record:** **UAF** on `struct queue` → kernel oops/crash, potential
memory corruption. **Severity: HIGH** (approaching CRITICAL for
exploitable UAF, though trigger is somewhat specialized).
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH — prevents real UAF crash in production KFD debugger
paths
- **Risk:** LOW — 6 lines, uses existing flag, `-EBUSY` is
safe/conventional
- **Ratio:** Strongly favors backport
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Summary
**FOR backport:**
- Explicit UAF race fix with clear mechanism
- Bug present since 2023 in code that exists in 6.18.44
- Small, surgical, applies cleanly
- Userspace-reachable via KFD ioctl
- Maintainer + reviewer sign-off
- Matches pattern of other amdkfd stable fixes (UAF, NULL deref, races)
- Error-path flag cleanup prevents stuck "being destroyed" state
**AGAINST backport:**
- Narrow trigger (debug_trap + suspended queue + concurrency)
- No syzbot/user report in commit message
- Mailing list discussion unverified
**Unresolved:**
- Full lore review thread (blocked)
- Whether fix commit hash exists on mainline (not in this tree)
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — logic is clear; AMD reviewer
+ maintainer SOB; no Tested-by but pattern is standard
2. Fixes a real bug? **PASS** — verified UAF race in code
3. Important issue? **PASS** — UAF / crash (HIGH severity)
4. Small and contained? **PASS** — 6 lines, 1 file, 2 functions
5. No new features/APIs? **PASS** — uses existing `is_being_destroyed`
field
6. Can apply to local tree? **PASS** — verified with `git apply --check`
### Step 9.3: Exception Categories
**Record:** N/A — standard bug fix, not a quirk/ID/DT/build/doc
exception.
### Step 9.4: Decision Rationale
This is a textbook stable backport: a real use-after-free in KFD queue
destruction, introduced years ago, still present in 6.18.44, fixed with
a minimal flag-based serialization that mirrors existing suspend-side
logic. The trigger is specialized (debugger + suspended queue) but the
consequence is a kernel crash. The patch applies cleanly and carries low
risk.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body from provided commit message
- **[Phase 1]** Confirmed no Fixes:/Reported-by:/Link: tags
- **[Phase 2]** Read current `wait_on_destroy_queue()` at lines
2480–2506: missing all fix hunks
- **[Phase 2]** Read `destroy_queue_cpsch()` at lines 2508–2601: missing
flag cleanup on error path
- **[Phase 2]** Read `suspend_single_queue()` line 1075: existing
`is_being_destroyed` check confirms flag infrastructure
- **[Phase 2]** Read `kfd_priv.h` line 521: `is_being_destroyed` field
exists
- **[Phase 3]** `git describe HEAD`: v6.18.44
- **[Phase 3]** `git blame -L 2480,2506`: `wait_on_destroy_queue` from
`a70a93fa568b4` (Jonathan Kim, 2023-06-09)
- **[Phase 3]** `git show a70a93fa568b4f`: introduced debug
suspend/resume and `wait_on_destroy_queue`
- **[Phase 3]** `git merge-base --is-ancestor a70a93fa568b4f HEAD`:
buggy commit is in tree
- **[Phase 3]** `git log -S "is_being_destroyed"`: only introducing
commit, no fix
- **[Phase 3]** `git log --oneline -20 -- kfd_device_queue_manager.c`:
recent amdkfd activity confirmed
- **[Phase 4]** `b4 dig -c`: N/A — commit not in checkout
- **[Phase 4]** lore.kernel.org fetch: blocked by Anubis (UNVERIFIED)
- **[Phase 5]** `grep destroy_queue`: traced call chain ioctl →
pqm_destroy_queue → destroy_queue_cpsch
- **[Phase 5]** Read `pqm_destroy_queue()` lines 505–574: frees queue
only after successful destroy
- **[Phase 5]** Read `kfd_ioctl_destroy_queue()` lines 417–433:
holds/releases `p->mutex`
- **[Phase 6]** Confirmed buggy code at lines 2493, 2495–2503 (drops
locks during wait)
- **[Phase 6]** `git apply --check`: patch applies cleanly to 6.18.44
- **[Phase 6]** `grep "fix UAF race in destroy_queue_cpsch"`: not in
tree (fix not yet applied)
- **[Phase 8]** Race mechanism verified: mutex dropped at line 2497
enables concurrent destroy
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index d9f09f25911a7..b02fe5d08c79f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -2499,6 +2499,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm,
if (pdd->qpd.is_debug)
return ret;
+ if (q->properties.is_being_destroyed)
+ return -EBUSY;
+
q->properties.is_being_destroyed = true;
if (pdd->process->debug_trap_enabled && q->properties.is_suspended) {
@@ -2511,6 +2514,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm,
dqm_lock(dqm);
}
+ if (ret)
+ q->properties.is_being_destroyed = false;
+
return ret;
}
@@ -2604,7 +2610,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
return retval;
failed_try_destroy_debugged_queue:
-
+ q->properties.is_being_destroyed = false;
dqm_unlock(dqm);
return retval;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: Prefer ROM BAR for default VGA device
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (22 preceding siblings ...)
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: fix UAF race in destroy_queue_cpsch Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds for allocate_sdma_queue restore_sdma_id Sasha Levin
` (13 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Lijo Lazar, Hawking Zhang, Alex Deucher, Sasha Levin,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Lijo Lazar <lijo.lazar@amd.com>
[ Upstream commit 9e32d17592950478baffaecdbda8e2e60935fd3d ]
Fetching from platform ROM doesn't work with hybrid ROM images. For
default VGA devices also prefer ROM BAR.
Signed-off-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:
The background `git log -S` search finished, but this stable tree’s
shallow history isn’t useful here — it only surfaced baseline import
commits (`19eef1d98eeda`, `ac3fd01e4c1ef`), not the real introduction.
The function was added upstream in `27145f78f56a` (“drm/amdgpu: Prefer
shadow rom when available”, March 2025), and that code is already
present in v6.18.43. This patch is a small follow-up for default VGA
devices with hybrid ROM images.
**Verdict: YES** — backport to this tree.
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 4e60753e16e90..dec312b0f3b0a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -33,6 +33,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/acpi.h>
+#include <linux/vgaarb.h>
/*
* BIOS.
*/
@@ -491,7 +492,8 @@ static bool amdgpu_prefer_rom_resource(struct amdgpu_device *adev)
{
struct resource *res = &adev->pdev->resource[PCI_ROM_RESOURCE];
- return (res->flags & IORESOURCE_ROM_SHADOW);
+ return (res->flags & IORESOURCE_ROM_SHADOW) ||
+ adev->pdev == vga_default_device();
}
static bool amdgpu_get_bios_dgpu(struct amdgpu_device *adev)
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds for allocate_sdma_queue restore_sdma_id
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (23 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: Prefer ROM BAR for default VGA device Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.6] drm/amd/pm: Check SMUv13.0.6/12 metrics integrity Sasha Levin
` (12 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: David Francis, Harish Kasiviswanathan, Alex Deucher, Sasha Levin,
Felix.Kuehling, christian.koenig, airlied, simona, amd-gfx,
dri-devel, linux-kernel
From: David Francis <David.Francis@amd.com>
[ Upstream commit bfe9a7545b2a7be1c543f1741e16f2d5ec4116ae ]
allocate_sdma_queue has an option where the sdma queue id can be
specified (used by CRIU). We weren't bounds-checking that
value.
Confirm it's less than the maximum number of queues.
Signed-off-by: David Francis <David.Francis@amd.com>
Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@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...
Connection lost, reconnecting to https://agentn.us.api5.cursor.sh
(attempt 2)...
Retry attempt 2...
# Stable Backport Analysis: `drm/amdkfd: Check bounds for
allocate_sdma_queue restore_sdma_id`
**Local tree:** Linux **6.18.43** (`git describe HEAD` →
`v6.18.43-1-gc7f0dac02d232`, `make kernelversion` → `6.18.43`)
**Commit under review:** `bfe9a7545b2a7be1c543f1741e16f2d5ec4116ae` (not
present in this tree)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1 – Subject line**
Record: `[drm/amdkfd]` `[Check]` – add bounds validation for user-
specified `restore_sdma_id` in `allocate_sdma_queue()` during CRIU queue
restore.
**Step 1.2 – Tags**
| Tag | Value |
|-----|-------|
| Signed-off-by | David Francis \<David.Francis@amd.com\> |
| Reviewed-by | Harish Kasiviswanathan
\<Harish.Kasiviswanathan@amd.com\> |
| Signed-off-by | Alex Deucher \<alexander.deucher@amd.com\>
(maintainer) |
Notable absences (expected for manual review): no `Fixes:`, `Reported-
by:`, `Cc: stable@vger.kernel.org`, `Link:`.
Record: AMD maintainer-reviewed fix; no fuzzer or user bug report tags.
Part of a 2-patch series (patch 1/2 fixes `allocate_doorbell` bounds).
**Step 1.3 – Body**
Record:
- **Bug:** `allocate_sdma_queue()` accepts a caller-specified SDMA queue
ID for CRIU restore but never validates it is within the number of
available queues.
- **Symptom:** Out-of-bounds `test_bit()` / `clear_bit()` on
`sdma_bitmap` / `xgmi_sdma_bitmap` when a restored `sdma_id` is too
large; kernel memory safety issue.
- **Root cause:** CRIU restore path passes `q_data->sdma_id` (copied
from userspace) straight into `allocate_sdma_queue()` without
validation.
**Step 1.4 – Hidden bug fix?**
Record: **Yes.** Although the subject says "Check bounds," this is a
genuine memory-safety bug fix, not cosmetic cleanup. The companion
`deallocate_sdma_queue()` already bounds-checks `sdma_id`; the allocate-
restore path was inconsistent.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1 – Inventory**
| File | Change |
|------|--------|
| `drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c` | +6 lines |
Functions modified: `allocate_sdma_queue()` only. Scope: single-file,
surgical fix.
**Step 2.2 – Code flow (per hunk)**
**Hunk 1 – `KFD_QUEUE_TYPE_SDMA` restore path:**
- Before: if `restore_sdma_id` is non-NULL, immediately
`test_bit(*restore_sdma_id, dqm->sdma_bitmap)`.
- After: reject `*restore_sdma_id >= get_num_sdma_queues(dqm)` with
`-EINVAL` before touching the bitmap.
**Hunk 2 – `KFD_QUEUE_TYPE_SDMA_XGMI` restore path:**
- Same pattern using `get_num_xgmi_sdma_queues(dqm)`.
Record: Both hunks guard the CRIU-restore branch only; normal allocation
(`find_first_bit`) is unchanged.
**Step 2.3 – Bug mechanism**
Record: **Memory safety / bounds validation bug (d).**
- `sdma_bitmap` is `DECLARE_BITMAP(sdma_bitmap, KFD_MAX_SDMA_QUEUES)`
where `KFD_MAX_SDMA_QUEUES = 128`.
- `get_num_sdma_queues()` is typically much smaller (e.g., engines ×
queues_per_engine, often single digits to low tens).
- `kfd_criu_restore_queue()` copies `q_data->sdma_id` (`uint32_t`) from
userspace with no validation.
- Without the fix, `sdma_id >= 128` causes out-of-bounds bitmap access
in `test_bit()` / `clear_bit()`.
- For `sdma_id` in `[get_num_sdma_queues(), 127)`, bits are zero →
misleading `-EBUSY` rather than crash, but still incorrect.
**Step 2.4 – Fix quality**
Record: Fix is **obviously correct**, minimal (6 lines), mirrors
existing `deallocate_sdma_queue()` bounds checks at lines 1686–1691.
Regression risk is very low: only rejects previously invalid inputs
earlier with `-EINVAL`.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1 – Blame**
Record: `restore_sdma_id` logic in `allocate_sdma_queue()` is present in
this tree (lines 1588–1621). `git blame` attributes the block to commit
`a112b91dd6349` (history in this tree is squashed/limited). The restore
path and CRIU infrastructure are present in 6.18.43.
**Step 3.2 – Fixes: tag**
Record: N/A – no `Fixes:` tag in commit message.
**Step 3.3 – Related file history**
Record: `git log --oneline --
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c` returns only one
commit in this tree (limited history). CRIU queue restore code
(`kfd_criu_restore_queue`, `create_queue_cpsch` with `qd->sdma_id`) is
present and active.
**Step 3.4 – Author context**
Record: David Francis (AMD). Reviewed by Harish Kasiviswanathan;
committed by Alex Deucher (amdkfd maintainer). Part of v1 series
submitted 2026-05-12.
**Step 3.5 – Dependencies**
Record: **Standalone.** Patch 1/2 (`allocate_doorbell` bounds) is a
separate, related hardening fix. This patch does not depend on it. `git
merge-base --is-ancestor bfe9a75 HEAD` → exit 1 (fix not yet in tree).
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1 – Original discussion**
Record:
- `b4 dig -c bfe9a7545b2a7be1c543f1741e16f2d5ec4116ae` → https://patch.m
sgid.link/20260512192824.3682569-2-David.Francis@amd.com
- `b4 dig -a`: v1 series, 2 patches, dated 2026-05-12.
- v1 initially had a bug (`restore_sdma_id >= ...` instead of
`*restore_sdma_id`); author self-corrected in follow-up. The
committed/applied version uses `*restore_sdma_id` (matches the diff
under review).
**Step 4.2 – Reviewers**
Record: `b4 dig -w` → To/Cc: David Francis, amd-
gfx@lists.freedesktop.org. Reviewed-by from AMD colleague; Signed-off-by
maintainer Alex Deucher.
**Step 4.3 – Bug report**
Record: No external bug report, syzbot link, or crash trace. Bug
identified by code inspection during CRIU hardening (paired with
doorbell bounds patch).
**Step 4.4 – Series context**
Record: `[PATCH 1/2] drm/amdkfd: Check bounds on allocate_doorbell` is
independent. Both are CRIU ioctl-input validation fixes.
**Step 4.5 – Stable list**
Record: Could not search lore stable archive (Anubis bot protection). No
evidence of prior stable rejection found.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1 – Key functions**
Record: `allocate_sdma_queue()` (modified); callers unchanged.
**Step 5.2 – Callers**
Record:
- `create_queue_nocpsch()` line 664: `allocate_sdma_queue(dqm, q, qd ?
&qd->sdma_id : NULL)`
- `create_queue_cpsch()` line 1985: same pattern
Both reached from `pqm_create_queue()` → `kfd_criu_restore_queue()` when
`q_data` is non-NULL.
**Step 5.3 – Callees**
Record: `get_num_sdma_queues()`, `get_num_xgmi_sdma_queues()`,
`test_bit()`, `clear_bit()`, `find_first_bit()`, `bitmap_empty()`.
**Step 5.4 – Reachability**
Call chain:
```
kfd_ioctl_criu (KFD_CRIU_OP_RESTORE)
→ criu_restore()
→ criu_restore_objects()
→ kfd_criu_restore_queue() [copy_from_user q_data->sdma_id]
→ pqm_create_queue(..., q_data, ...)
→ dqm->ops.create_queue(..., qd, ...)
→ allocate_sdma_queue(dqm, q, &qd->sdma_id)
```
Record: **Reachable from userspace** via `KFD_IOC_CRIU` restore ioctl.
Requires `CAP_CHECKPOINT_RESTORE` or `CAP_SYS_ADMIN` (verified in
`kfd_chardev.c` lines 3332–3337). Not unprivileged, but still a
privileged ioctl input-validation bug.
**Step 5.5 – Similar patterns**
Record: `deallocate_sdma_queue()` already bounds-checks before
`set_bit()`:
```1685:1692:drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
if (q->sdma_id >= get_num_sdma_queues(dqm))
return;
set_bit(q->sdma_id, dqm->sdma_bitmap);
} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
if (q->sdma_id >= get_num_xgmi_sdma_queues(dqm))
return;
```
The allocate-restore path was the missing symmetric check.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE (6.18.43)
**Step 6.1 – Buggy code present?**
Record: **YES.** `allocate_sdma_queue()` at lines 1588–1621 lacks bounds
checks. CRIU infrastructure (`kfd_criu_queue_priv_data.sdma_id`,
`kfd_criu_restore_queue`) is fully present. `KFD_MAX_SDMA_QUEUES = 128`.
**Step 6.2 – Backport complications**
Record: **Clean apply expected.** The target lines match the mainline
diff context. No conflicting changes observed. Fix commit is not in tree
(`git merge-base --is-ancestor` → not ancestor).
**Step 6.3 – Related fixes already present?**
Record: `deallocate_sdma_queue()` bounds checks exist. No equivalent
allocate-side check. `git log --grep="bounds.*sdma"` → no matches. Fix
not yet applied.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1 – Subsystem**
Record: `drivers/gpu/drm/amd/amdkfd` – AMDGPU HSA/KFD compute driver.
**IMPORTANT** (not core kernel, but widely deployed on AMD GPU systems
with ROCm/compute workloads).
**Step 7.2 – Activity**
Record: amdkfd is actively maintained; CRIU checkpoint/restore support
is a relatively newer feature in this area.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1 – Who is affected**
Record: Users of **AMD GPU compute (amdkfd)** with **CRIU
checkpoint/restore** enabled. Config-dependent
(`CONFIG_HSA_AMD`/amdkfd). Not universal, but real for containerized GPU
workload migration.
**Step 8.2 – Trigger conditions**
Record:
- Malformed or adversarial CRIU checkpoint with `sdma_id >=
get_num_sdma_queues()` (especially `>= 128`).
- Triggered during `KFD_CRIU_OP_RESTORE` on SDMA or SDMA_XGMI queue
objects.
- Requires `CAP_CHECKPOINT_RESTORE` or `CAP_SYS_ADMIN`.
- Likelihood: low in normal use; realistic with corrupted checkpoints or
malicious privileged actor.
**Step 8.3 – Failure mode severity**
Record:
- `sdma_id >= 128`: **out-of-bounds bitmap access** → potential kernel
oops, memory corruption. **Severity: HIGH** (memory safety).
- `sdma_id` in valid bitmap range but above queue count: incorrect
`-EBUSY`, no crash. **Severity: LOW**.
**Step 8.4 – Risk/benefit**
| | Assessment |
|--|------------|
| **Benefit** | Prevents OOB kernel memory access on a privileged ioctl
path; aligns allocate/deallocate safety |
| **Risk** | Very low – 6 lines, only rejects invalid input |
| **Ratio** | Favorable for backport |
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1 – Evidence summary**
**FOR backport:**
- Real bounds-check omission with OOB potential (`sdma_id >= 128` on
128-bit bitmap)
- Userspace-controlled value via CRIU restore ioctl
- Small, surgical, maintainer-reviewed fix
- Buggy code confirmed present in 6.18.43
- Consistent with existing `deallocate_sdma_queue()` pattern
- Standalone (no dependencies)
**AGAINST backport:**
- Requires elevated capability (not unprivileged attack)
- CRIU/amdkfd is a niche code path
- No syzbot or user crash report
- Patch 1/2 (doorbell bounds) is a separate fix not included here
**Unresolved:** No runtime crash report; exact introduction commit of
`restore_sdma_id` path not traceable in this tree's limited git history.
**Step 9.2 – Stable rules checklist# Stable Backport Analysis:
`drm/amdkfd: Check bounds for allocate_sdma_queue restore_sdma_id`
**Local tree:** Linux **6.18.43** (`git describe HEAD` →
`v6.18.43-1-gc7f0dac02d232`, `make kernelversion` → `6.18.43`)
**Commit under review:** `bfe9a7545b2a7be1c543f1741e16f2d5ec4116ae` (not
present in this tree)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amdkfd]` `[Check]` — Add bounds validation for
`restore_sdma_id` in `allocate_sdma_queue()` during CRIU queue restore.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** David Francis `<David.Francis@amd.com>` (author)
- **Reviewed-by:** Harish Kasiviswanathan
`<Harish.Kasiviswanathan@amd.com>`
- **Signed-off-by:** Alex Deucher `<alexander.deucher@amd.com>`
(maintainer)
- **No** Fixes:, Reported-by:, Link:, Cc: stable@vger.kernel.org,
Tested-by:, Acked-by:
- Notable: Part of a 2-patch series (`[PATCH 2/2]`); patch 1/2 is a
separate `allocate_doorbell` bounds fix.
### Step 1.3: Body analysis
**Record:**
- **Bug:** `allocate_sdma_queue()` accepts a user-specified SDMA queue
ID for CRIU restore but never validates it is within the number of
available queues.
- **Symptom:** Out-of-range `sdma_id` reaches `test_bit()` /
`clear_bit()` on the SDMA bitmap without validation.
- **Root cause:** The CRIU restore path passes `q_data->sdma_id` from
userspace straight into `allocate_sdma_queue()` with no bounds check
on the allocate path (unlike the deallocate path).
- **Version info:** None in the commit message.
### Step 1.4: Hidden bug fix?
**Record:** No — this is an explicit bounds-check bug fix, not disguised
cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **Files:** `drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c` (+6
/ −0)
- **Function:** `allocate_sdma_queue()`
- **Scope:** Single-file, surgical fix in two CRIU-restore branches
(SDMA and XGMI SDMA).
### Step 2.2: Code flow change
**Record:**
- **Hunk 1 (KFD_QUEUE_TYPE_SDMA):** Before → `restore_sdma_id` used
directly in `test_bit(*restore_sdma_id, dqm->sdma_bitmap)`. After →
reject with `-EINVAL` if `*restore_sdma_id >=
get_num_sdma_queues(dqm)`.
- **Hunk 2 (KFD_QUEUE_TYPE_SDMA_XGMI):** Same pattern using
`get_num_xgmi_sdma_queues(dqm)`.
- **Path affected:** CRIU queue restore only (when `restore_sdma_id` is
non-NULL).
### Step 2.3: Bug mechanism
**Record:** **Memory safety / bounds validation bug (d).**
- `sdma_bitmap` is `DECLARE_BITMAP(sdma_bitmap, KFD_MAX_SDMA_QUEUES)`
where `KFD_MAX_SDMA_QUEUES` is **128**.
- `get_num_sdma_queues()` is typically much smaller (e.g. engines ×
queues_per_engine, often single digits to low tens).
- Without the check, a `sdma_id >= 128` from userspace causes
`test_bit()` / `clear_bit()` to operate outside the 128-bit bitmap →
out-of-bounds kernel memory access.
- For `get_num_sdma_queues() <= sdma_id < 128`, bits are zero and the
code returns `-EBUSY` (no crash, but still invalid input that should
be rejected earlier).
### Step 2.4: Fix quality
**Record:**
- Fix is minimal and mirrors the existing pattern in
`deallocate_sdma_queue()` (lines 1686–1691), which already bounds-
checks `q->sdma_id`.
- Low regression risk: only affects the CRIU-restore path with an out-
of-range ID.
- No API or structural changes.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `restore_sdma_id` logic in `allocate_sdma_queue()` is
present in this tree at lines 1588–1621. Git blame attributes these
lines to `a112b91dd6349` (history in this checkout is shallow/squashed
and not reliable for dating the original feature). The vulnerable
pattern is confirmed present in 6.18.43.
### Step 3.2: Fixes: tag
**Record:** N/A — no Fixes: tag in the commit message.
### Step 3.3: Related file history
**Record:** `git log --oneline -20 -- kfd_device_queue_manager.c` shows
only one commit in this tree’s history for that file. The CRIU restore
infrastructure (`kfd_criu_restore_queue`, `create_queue_cpsch`,
`create_queue_nocpsch`) is fully present in 6.18.43. This patch is
**standalone** within its series; patch 1/2 (`allocate_doorbell` bounds)
is a separate fix.
### Step 3.4: Author context
**Record:** David Francis (AMD). Alex Deucher signed off. Harish
Kasiviswanathan reviewed. No other amdkfd commits from this author
visible in this tree’s limited history.
### Step 3.5: Dependencies
**Record:** No functional dependency on patch 1/2. The `restore_sdma_id`
pointer parameter and CRIU call sites already exist in this tree. `git
merge-base --is-ancestor bfe9a75 HEAD` → **not an ancestor** (fix not
yet applied).
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- `b4 dig -c bfe9a7545b2a7be1c543f1741e16f2d5ec4116ae` → https://patch.m
sgid.link/20260512192824.3682569-2-David.Francis@amd.com
- Series: v1 only (`b4 dig -a`); patch 2/2 of 2.
- v1 initially had a typo (`restore_sdma_id >=` instead of
`*restore_sdma_id >=`); the committed/applied version (and the diff
under review) correctly dereferences the pointer.
### Step 4.2: Reviewers
**Record:** `b4 dig -w` — sent to David Francis and `amd-
gfx@lists.freedesktop.org`. Harish Kasiviswanathan reviewed; Alex
Deucher committed.
### Step 4.3: Bug report
**Record:** No external bug report, syzbot report, or crash log.
Internal code-review discovery.
### Step 4.4: Series context
**Record:** 2-patch series:
1. `drm/amdkfd: Check bounds on allocate_doorbell`
2. This commit (SDMA queue ID bounds)
Each patch addresses a separate CRIU-restore validation gap. This one is
independently applicable.
### Step 4.5: Stable list history
**Record:** Could not search lore stable list (Anubis bot protection).
No stable nomination found via b4.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `allocate_sdma_queue()` (modified); callers unchanged.
### Step 5.2: Callers
**Record:**
- `create_queue_nocpsch()` — line 664: `allocate_sdma_queue(dqm, q, qd ?
&qd->sdma_id : NULL)`
- `create_queue_cpsch()` — line 1985: same pattern
- Both reached from `pqm_create_queue()` → `kfd_criu_restore_queue()`
when `q_data` is non-NULL.
### Step 5.3: Callees
**Record:** `get_num_sdma_queues()`, `get_num_xgmi_sdma_queues()`,
`test_bit()`, `clear_bit()`, `bitmap_empty()`, `find_first_bit()`.
### Step 5.4: Reachability
**Record:**
```
userspace ioctl (KFD_IOC_CRIU, KFD_CRIU_OP_RESTORE)
→ criu_restore() → criu_restore_objects()
→ kfd_criu_restore_queue() [copy_from_user q_data->sdma_id]
→ pqm_create_queue(..., q_data, ...)
→ create_queue_{nocpsch,cpsch}(..., qd, ...)
→ allocate_sdma_queue(dqm, q, &qd->sdma_id)
```
- Requires `CONFIG_HSA_AMD` / amdgpu KFD.
- CRIU ioctl gated on `CAP_CHECKPOINT_RESTORE` or `CAP_SYS_ADMIN`
(kfd_chardev.c:3332–3337).
- Reachable from userspace with elevated privileges, not from
unprivileged users.
### Step 5.5: Similar patterns
**Record:** `deallocate_sdma_queue()` already bounds-checks before
`set_bit()`:
```1686:1691:drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
if (q->sdma_id >= get_num_sdma_queues(dqm))
return;
set_bit(q->sdma_id, dqm->sdma_bitmap);
```
The allocate path was missing the symmetric check. `allocate_doorbell()`
CP-queue restore path (patch 1/2) has a similar gap but is out of scope
for this commit.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE
### Step 6.1: Buggy code exists?
**Record:** **Yes.** Lines 1588–1621 in this tree use `*restore_sdma_id`
in `test_bit()` / `clear_bit()` without prior bounds validation.
`KFD_MAX_SDMA_QUEUES` is 128 (`kfd_priv.h:123`). CRIU restore and
`kfd_criu_queue_priv_data.sdma_id` exist in 6.18.43.
### Step 6.2: Backport complications
**Record:** Expected **clean apply** — 6 lines added in two well-defined
locations; no structural conflicts observed.
### Step 6.3: Related fixes already present?
**Record:** **No.** `git merge-base --is-ancestor bfe9a75 HEAD` failed
(fix not in tree). No grep hits for the bounds-check pattern in the
allocate path.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/gpu/drm/amd/amdkfd` — **IMPORTANT** (AMD GPU
compute / ROCm KFD). Not core kernel, but widely deployed on AMD GPU
servers and workstations.
### Step 7.2: Activity
**Record:** Limited git history in this checkout; amdkfd CRIU support is
mature enough to be present in 6.18.43.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Users of AMD KFD with CRIU checkpoint/restore (container
migration, HPC job migration). Requires amdgpu + HSA_AMD + privileged
CRIU ioctl access.
### Step 8.2: Trigger conditions
**Record:**
- CRIU restore of an SDMA or XGMI SDMA queue with `sdma_id >=
get_num_sdma_queues()` (or `>= 128` for definite OOB).
- Triggered by malicious/corrupt checkpoint data or a buggy userspace
restorer.
- **Not** triggerable by unprivileged users.
- Moderately rare in practice (CRIU + AMD GPU), but straightforward to
trigger with crafted input once privileges are held.
### Step 8.3: Failure mode severity
**Record:**
- `sdma_id >= 128`: **HIGH** — out-of-bounds `test_bit()` /
`clear_bit()` on a 128-bit bitmap → potential kernel memory corruption
or crash.
- `get_num_sdma_queues() <= sdma_id < 128`: **LOW** — returns `-EBUSY`,
no memory corruption.
- Overall: **HIGH** for the OOB case; privilege requirement lowers
practical exploitability but not correctness importance.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** MEDIUM — closes a kernel memory-safety hole on a
privileged ioctl path; aligns allocate/deallocate symmetry.
- **Risk:** VERY LOW — 6-line validation, reviewed by AMD maintainers.
- **Ratio:** Benefit outweighs risk.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real missing bounds check on userspace-supplied `sdma_id` in CRIU
restore.
- Can cause OOB bitmap access when `sdma_id >= 128`.
- Small (6 lines), obviously correct, AMD-reviewed.
- Buggy code confirmed in 6.18.43; fix not yet applied.
- Symmetric with existing `deallocate_sdma_queue()` bounds checks.
**AGAINST backport:**
- Requires `CAP_CHECKPOINT_RESTORE` or `CAP_SYS_ADMIN` — not
unprivileged attack surface.
- CRIU + AMD GPU is a niche configuration.
- No syzbot/user crash report.
- Companion patch 1/2 (doorbell bounds) is separate; ideally both go in,
but this patch stands alone.
**Unresolved:** Exact kernel version when CRIU `restore_sdma_id` was
introduced (shallow history in this checkout).
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — trivial validation;
Reviewed-by from AMD; no Tested-by.
2. Fixes a real bug? **PASS** — missing input validation on ioctl-fed
data.
3. Important issue? **PASS** — OOB kernel memory access (HIGH when
`sdma_id >= 128`).
4. Small and contained? **PASS** — 6 lines, one file, one function.
5. No new features or APIs? **PASS** — validation only.
6. Can apply to local tree? **PASS** — code exists; clean apply
expected.
### Step 9.3: Exception categories
**Record:** None (not a device ID, quirk, DT, build, or docs fix).
Qualifies as a standard security/correctness bug fix.
### Step 9.4: Decision rationale
For **Linux 6.18.43**, the vulnerable CRIU-restore path exists and the
fix is a minimal, maintainer-reviewed bounds check that prevents out-of-
bounds bitmap access on a userspace-controlled value. The privilege
requirement reduces attack surface but does not eliminate the bug:
privileged container/orchestration stacks using KFD CRIU are exactly the
affected users, and kernel memory safety fixes on ioctl paths are
appropriate stable material. The fix is self-contained and does not
depend on patch 1/2.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body from provided commit message.
- **[Phase 2]** Diff analysis: +6 lines, two bounds checks with
`*restore_sdma_id` dereference.
- **[Phase 3]** `git describe HEAD` / `make kernelversion` → 6.18.43.
- **[Phase 3]** `git blame -L 1588,1621` → restore_sdma_id code present.
- **[Phase 3]** `git merge-base --is-ancestor bfe9a75 HEAD` → exit 1
(fix not in tree).
- **[Phase 4]** `b4 dig -c bfe9a75` → lore URL found.
- **[Phase 4]** `b4 dig -a` → v1, 2-patch series.
- **[Phase 4]** `b4 dig -w` → amd-gfx@lists.freedesktop.org CC'd.
- **[Phase 4]** Web search confirmed commit
`bfe9a7545b2a7be1c543f1741e16f2d5ec4116ae` and v1 pointer-deref fix in
review.
- **[Phase 5]** `grep allocate_sdma_queue` → callers at lines 664, 1985.
- **[Phase 5]** Read `kfd_criu_restore_queue()` →
`copy_from_user(q_data)` includes `sdma_id`, no validation.
- **[Phase 5]** Read `kfd_chardev.c:3332-3337` → CAP_CHECKPOINT_RESTORE
or CAP_SYS_ADMIN required.
- **[Phase 5]** `KFD_MAX_SDMA_QUEUES` = 128 (`kfd_priv.h:123`).
- **[Phase 5]** `deallocate_sdma_queue()` bounds checks at lines
1686–1691 confirmed.
- **[Phase 6]** Current code at lines 1588–1621 lacks bounds check
(verified by read + grep).
- **[Phase 6]** CRIU infrastructure present: `kfd_criu_restore_queue`,
`kfd_criu_queue_priv_data.sdma_id`.
- **[Phase 8]** Failure mode: OOB when `sdma_id >= 128`; privilege-gated
trigger confirmed.
- **UNVERIFIED:** Exact upstream commit that introduced
`restore_sdma_id` (shallow git history in this checkout).
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index c650ffc3e66e8..2f8df95382bc3 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -1586,6 +1586,9 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
}
if (restore_sdma_id) {
+ if (*restore_sdma_id >= get_num_sdma_queues(dqm))
+ return -EINVAL;
+
/* Re-use existing sdma_id */
if (!test_bit(*restore_sdma_id, dqm->sdma_bitmap)) {
dev_err(dev, "SDMA queue already in use\n");
@@ -1612,6 +1615,9 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
return -ENOMEM;
}
if (restore_sdma_id) {
+ if (*restore_sdma_id >= get_num_xgmi_sdma_queues(dqm))
+ return -EINVAL;
+
/* Re-use existing sdma_id */
if (!test_bit(*restore_sdma_id, dqm->xgmi_sdma_bitmap)) {
dev_err(dev, "SDMA queue already in use\n");
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amd/pm: Check SMUv13.0.6/12 metrics integrity
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (24 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds for allocate_sdma_queue restore_sdma_id Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] drm/amdgpu: avoid integer overflow in VA range check Sasha Levin
` (11 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Lijo Lazar, Asad Kamal, Alex Deucher, Sasha Levin, kenneth.feng,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Lijo Lazar <lijo.lazar@amd.com>
[ Upstream commit 6fc63d80c01a480e3d2c98620f07d46e5bcfc85a ]
Check if data fetch is proper by matching the first few bytes against
0xFFs. If 0xFFs, that means data couldn't be read properly.
Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Asad Kamal <asad.kamal@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:
# Stable Backport Analysis: `drm/amd/pm: Check SMUv13.0.6/12 metrics
integrity`
**Local tree:** `v6.18.43` (Linux 6.18.43)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amd/pm]` `[Check]` — Add integrity validation for SMU
v13.0.6/12 metrics table reads.
### Step 1.2: Tags
**Record:**
- `Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>` (author)
- `Reviewed-by: Asad Kamal <asad.kamal@amd.com>`
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (AMD DRM
maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`, or
`Tested-by:`
Notable: AMD maintainer review and sign-off, but no public bug report or
fuzzer report.
### Step 1.3: Body analysis
**Record:**
- **Bug:** SMU metrics table fetch can succeed at the SMC-message level
while the copied data is invalid (all `0xFF`, meaning unread).
- **Symptom:** Driver treats poisoned/unread data as valid metrics.
- **Root cause:** No post-copy validation after `GetMetricsTable` +
VRAM/CPU copy.
- **Fix:** Check first 16 bytes with `memchr_inv()`; if all `0xFF`,
return `-EHWPOISON`.
- No kernel version or hardware list in the message; subject names
SMUv13.0.6/12.
### Step 1.4: Hidden bug fix?
**Record:** Yes. Despite “Check” wording, this is a real correctness bug
fix: it stops silently consuming invalid SMU metrics that would
otherwise drive power limits, clock tables, sysfs metrics, and XGMI
configuration.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c` (+4
lines)
- **Function:** `smu_v13_0_6_get_metrics_table()`
- **Scope:** Single-file, surgical fix
Note: upstream diff context uses `amdgpu_hdp_invalidate()` +
`smu_cmn_vram_cpy()`. This tree uses `amdgpu_asic_invalidate_hdp()` +
`memcpy()` — same logical point, different API names.
### Step 2.2: Code flow change
**Record:**
- **Before:** After SMC message + copy, metrics are cached and returned
unconditionally.
- **After:** After copy, if first `min(16, table_size)` bytes are all
`0xFF`, return `-EHWPOISON` and do not update `metrics_time`.
- **Path:** Metrics refresh path (cache bypass or >1 ms stale).
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Memory/hardware data integrity / logic correctness
- **Mechanism:** Uninitialized or failed VRAM read leaves `0xFF`
pattern; driver previously treated it as valid. With all-`0xFF` data,
`AccumulationCounter` appears non-zero, so
`smu_v13_0_6_setup_driver_pptable()` can exit its retry loop
immediately and write garbage into `pptable` (power limits, clock
tables, serial numbers). The fix detects poisoned data before
caching/propagation.
### Step 2.4: Fix quality
**Record:**
- Obviously correct: `0xFF` fill is a standard “unread” sentinel;
`memchr_inv()` is used elsewhere in the kernel for this pattern (e.g.
`amd_pmf` policy buffer validation).
- Minimal (4 lines), no API changes.
- Low regression risk: only triggers on fully-`0xFF` prefix; legitimate
metrics are unaffected.
- `-EHWPOISON` is already used in amdgpu for hardware data integrity
failures.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `smu_v13_0_6_get_metrics_table()` at lines 750–778 is
present in this tree; blame points to merge commit `5d324e5159d9e`
(history is flattened through merges). The vulnerable function exists in
v6.18.43.
### Step 3.2: Fixes tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related file history
**Record:** Recent PM commits in this tree include `75849e13e428e` (xgmi
max speed reporting) and `33c3a4db31719` (invalid energy_accumulator on
smu v13.0.x). No duplicate integrity-check fix found. This commit is not
in this tree yet (`git log --grep` returned nothing).
### Step 3.4: Author context
**Record:** Lijo Lazar is an active AMD PM contributor (`75849e13e428e`
xgmi fix in this tree). Patch reviewed by fellow AMD engineer Asad Kamal
and maintainer Alex Deucher.
### Step 3.5: Dependencies
**Record:** Standalone. `memchr_inv()` and `-EHWPOISON` are available.
Backport inserts after the local copy call (`memcpy`), not upstream’s
`smu_cmn_vram_cpy`.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:** Patch submitted to amd-gfx on 2026-04-18 by Lijo Lazar.
Thread: https://lists.freedesktop.org/archives/amd-
gfx/2026-April/143042.html (also mirrored at yhbt.net). Included in Alex
Deucher’s drm-next-7.2 pull. `b4 dig -c` could not be run (commit not in
this checkout). lore.kernel.org direct fetch blocked (bot protection).
### Step 4.2: Reviewers
**Record:** CC’d Hawking.Zhang, Alexander.Deucher, Asad.Kamal. Asad
Kamal replied 2026-04-20 (Reviewed-by in final commit). No NAKs found.
### Step 4.3: Bug report
**Record:** No public bug report, syzbot, or Bugzilla link. Likely
internal AMD testing discovery.
### Step 4.4: Series context
**Record:** Standalone 1-patch fix, not part of a multi-patch series.
### Step 4.5: Stable list discussion
**Record:** No stable@ discussion found (UNVERIFIED beyond search; no
stable nomination seen in available sources).
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `smu_v13_0_6_get_metrics_table()` (modified).
### Step 5.2: Callers
**Record:** Direct callers in this tree:
- `smu_v13_0_6_get_pm_metrics()` — sysfs PM metrics (checks `ret`)
- `smu_v13_0_6_setup_driver_pptable()` — DPM init, power/clock limits
(checks `ret` in retry loop; caller at line 1088 ignores return — pre-
existing)
- `smu_v13_0_6_get_smu_metrics_data()` — clock/power/thermal sysfs
(checks `ret`)
- Partition metrics paths at lines 2657, 2758 (check `ret`)
- `smu_v13_0_12_ppt.c:258` — XGMI max speed/width fallback (checks
`ret`)
### Step 5.3: Callees
**Record:** `smu_cmn_send_smc_msg()`, HDP invalidate, `memcpy()` from
driver table CPU address.
### Step 5.4: Reachability
**Record:** Reachable from GPU init (DPM table setup) and runtime
sysfs/metrics queries on SMU IP 13.0.6 and 13.0.12 hardware (MI300-class
datacenter GPUs). Not a syscall path, but reachable from normal driver
operation on affected hardware.
### Step 5.5: Similar patterns
**Record:** `amd_pmf` uses `memchr_inv(dev->policy_buf, 0xff, ...)` for
the same invalid-read detection pattern. No existing `memchr_inv` +
`0xff` check in amdgpu PM code in this tree.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE (v6.18.43)
### Step 6.1: Buggy code present?
**Record:** **Yes.** `smu_v13_0_6_get_metrics_table()` at lines 750–778
lacks integrity check. SMU 13.0.6/12 support is wired in `amdgpu_smu.c`
(cases `IP_VERSION(13, 0, 6)` and `IP_VERSION(13, 0, 12)`).
### Step 6.2: Backport difficulty
**Record:** **Clean apply with trivial context adjustment.** Insert
after:
```768:769:drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
amdgpu_asic_invalidate_hdp(smu->adev, NULL);
memcpy(smu_table->metrics_table, table->cpu_addr,
table_size);
```
### Step 6.3: Related fixes already present?
**Record:** **No.** `grep` found no `memchr_inv` + `0xff` in amdgpu PM.
Commit not in tree history.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem and criticality
**Record:** `drivers/gpu/drm/amd/pm` — **IMPORTANT** (AMDGPU power
management for datacenter GPUs; affects power/thermal/clock behavior,
not core kernel).
### Step 7.2: Activity
**Record:** Actively maintained; recent stable-relevant PM fixes in this
tree (xgmi reporting, energy_accumulator invalidation).
---
## PHASE 8: IMPACT AND RISK
### Step 8.1: Who is affected
**Record:** Users of AMD GPUs with SMU firmware IP 13.0.6 or 13.0.12
(MI300/MI325X-class hardware). Config: `CONFIG_DRM_AMDGPU`.
### Step 8.2: Trigger conditions
**Record:** SMU metrics table VRAM read fails or returns uninitialized
`0xFF` data while SMC message succeeds. Can occur during init or runtime
metrics refresh. Not user-triggerable from syscalls; hardware/firmware
timing dependent. Plausible during error recovery or SMU communication
issues.
### Step 8.3: Failure mode severity
**Record:** Without fix: corrupt power limits, clock frequency tables,
thermal/activity metrics, and XGMI parameters derived from `0xFF` data —
risk of incorrect DPM behavior, bogus sysfs readings, and potential
hardware stress. **Severity: HIGH** (incorrect power/clock configuration
from poisoned data). Not a kernel oops, but can cause real hardware
misbehavior.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH for affected datacenter deployments — prevents
silent use of completely invalid SMU metrics.
- **Risk:** LOW — 4-line defensive check, AMD-reviewed, established
errno pattern.
- **Ratio:** Strong benefit, minimal risk.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Fixes real bug (silent consumption of unread `0xFF` metrics data)
- Can corrupt power/clock initialization in `setup_driver_pptable()`
- Small, surgical, AMD-maintainer-reviewed
- Code and affected hardware exist in v6.18.43
- Matches existing kernel/amdgpu integrity-check patterns
- Clean backport to this tree
**AGAINST backport:**
- No public bug report or crash trace
- Hardware-specific (MI300-class, niche vs consumer GPUs)
- `setup_driver_pptable()` return still ignored at one call site (pre-
existing; fix still prevents writing garbage into `pptable`)
- Severity is misconfiguration rather than kernel panic
**Unresolved:** Exact production trigger frequency; no syzbot/user
reports.
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — simple sentinel check;
Reviewed-by from AMD engineer; maintainer SOB.
2. Fixes real bug affecting users? **PASS** — invalid metrics used for
PM decisions on real hardware.
3. Important issue? **PASS** — incorrect power/clock limits from
poisoned SMU data on datacenter GPUs (HIGH severity
misconfiguration).
4. Small and contained? **PASS** — 4 lines, one function, one file.
5. No new features/APIs? **PASS** — error-path validation only.
6. Can apply to local tree? **PASS** — code present; minor context
adjustment for `memcpy` vs `smu_cmn_vram_cpy`.
### Step 9.3: Exception categories
**Record:** N/A (not device ID, DT, build fix, or docs). Standard bug
fix.
### Step 9.4: Decision rationale
This patch prevents the driver from silently building power-management
state from completely invalid SMU metrics. On MI300-class hardware in
the 6.18.y tree, a failed metrics read currently produces `0xFF` data
that can populate `pptable` power and clock limits. The fix is minimal,
low-risk, AMD-reviewed, and directly applicable to this checkout.
---
## Verification
- **[Phase 1]** Parsed commit message and tags from user-provided diff
- **[Phase 2]** Read `smu_v13_0_6_get_metrics_table()` at lines 750–778;
confirmed missing integrity check
- **[Phase 2]** Traced `setup_driver_pptable()` lines 873–942; confirmed
garbage `0xFF` metrics can populate power/clock limits
- **[Phase 3]** `git describe HEAD` → `v6.18.43`
- **[Phase 3]** `git blame -L 750,778` → function present, no integrity
check
- **[Phase 3]** `git log --grep="metrics integrity"` → no match (commit
not in tree)
- **[Phase 3]** `grep memchr_inv.*0xff drivers/gpu/drm/amd/pm` → no
matches
- **[Phase 4]** Web search found amd-gfx submission (2026-04-18) and
drm-next-7.2 pull inclusion
- **[Phase 4]** lore.kernel.org fetch failed (bot protection); Asad
Kamal reply noted via search snippet
- **[Phase 4]** `b4 dig` without commit hash unavailable; commit not in
local tree
- **[Phase 5]** `grep smu_v13_0_6_get_metrics_table` → 6 call sites in
`smu_v13_0_6_ppt.c`, 1 in `smu_v13_0_12_ppt.c`
- **[Phase 5]** Verified callers check `ret` (except
`smu_v13_0_6_setup_driver_pptable()` at line 1088)
- **[Phase 5]** `grep EHWPOISON drivers/gpu/drm/amd` → used in amdgpu
core (ras, cs, job, kms, xgmi)
- **[Phase 5]** Found `memchr_inv(..., 0xff, ...)` pattern in
`drivers/platform/x86/amd/pmf/tee-if.c`
- **[Phase 6]** Confirmed `IP_VERSION(13, 0, 6)` and `IP_VERSION(13, 0,
12)` in `amdgpu_smu.c`
- **[Phase 6]** Confirmed upstream diff context differs
(`smu_cmn_vram_cpy` vs local `memcpy`); fix placement is equivalent
- **[Phase 7]** `git log --oneline -20 -- drivers/gpu/drm/amd/pm/` →
active PM maintenance
- **UNVERIFIED:** Exact hardware SKU list beyond IP version 13.0.6/12;
production incident frequency; full Asad Kamal review thread content
**YES****Verdict: YES** — backport to this tree (`v6.18.43`).
The commit adds a 4-line check in `smu_v13_0_6_get_metrics_table()` so
unread SMU metrics (all `0xFF`) return `-EHWPOISON` instead of being
used for power limits, clock tables, and sysfs metrics on SMU 13.0.6/12
hardware (MI300-class). The buggy code is present in this tree; the
patch applies cleanly after the existing `memcpy()` call.
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index 43965b1135fe7..0d065e4073655 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -768,6 +768,10 @@ int smu_v13_0_6_get_metrics_table(struct smu_context *smu, void *metrics_table,
amdgpu_asic_invalidate_hdp(smu->adev, NULL);
memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
+ if (!memchr_inv(smu_table->metrics_table, 0xff,
+ min(16, table_size)))
+ return -EHWPOISON;
+
smu_table->metrics_time = jiffies;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: avoid integer overflow in VA range check
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (25 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.6] drm/amd/pm: Check SMUv13.0.6/12 metrics integrity Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.1] drm/amd/pm: bound pp_dpm_set_pp_table() memcpy Sasha Levin
` (10 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Ce Sun, Tao Zhou, Alex Deucher, Sasha Levin, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Ce Sun <cesun102@amd.com>
[ Upstream commit cc768f4dd0bb9083c813683eeec44fc23921f771 ]
The original addition operation in 64-bit unsigned type may encounter
overflow situations. To prevent such issues and safely reject invalid
inputs, the check_add_overflow() function is used.
Signed-off-by: Ce Sun <cesun102@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:
## Phase 1: Commit Message Forensics
### Step 1.1: Subject Line
**Record:** `[drm/amdgpu]` `[avoid]` — prevent integer overflow in the
`AMDGPU_GEM_VA` ioctl VA range validation (`amdgpu_gem_va_ioctl`).
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Ce Sun `<cesun102@amd.com>` (author)
- **Reviewed-by:** Tao Zhou `<tao.zhou1@amd.com>`
- **Signed-off-by:** Alex Deucher `<alexander.deucher@amd.com>`
(maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`,
`Tested-by:`, or `Acked-by:` tags
- Notable: reviewed by AMD developer and merged by amdgpu maintainer; no
fuzzer or user bug report
### Step 1.3: Body Analysis
**Record:**
- **Bug:** `args->va_address + args->map_size` uses unchecked 64-bit
unsigned addition in the top-reserved VA range check.
- **Symptom/failure mode:** On overflow, the wrapped sum can be `<=
vm_size`, so invalid oversized VA ranges are not rejected at the ioctl
boundary.
- **Root cause:** Missing overflow-safe addition before comparing
against `vm_size`.
- **Version info:** None in the commit message.
### Step 1.4: Hidden Bug Fix?
**Record:** Yes. Although the subject says “avoid” rather than “fix,”
this is an input-validation bug in a userspace-reachable DRM ioctl. It
is not cosmetic cleanup.
---
## Phase 2: Diff Analysis
### Step 2.1: Inventory
**Record:**
- **Files:** `drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c` only (+2/-2, 4
lines touched)
- **Functions:** `amdgpu_gem_va_ioctl()`
- **Scope:** Single-file, surgical ioctl validation fix
### Step 2.2: Code Flow Change
**Record:**
- **Before:** `if (args->va_address + args->map_size > vm_size)` —
overflow wraps, check may pass incorrectly.
- **After:** `if (check_add_overflow(args->va_address, args->map_size,
&tmp) || tmp > vm_size)` — overflow is detected and rejected with
`-EINVAL`.
- **Path affected:** Early validation in `amdgpu_gem_va_ioctl()`, before
GEM lookup, fence handling, and VM locking.
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Integer overflow / input validation bug
- **Mechanism:** A malicious or buggy userspace caller can supply
`va_address` and `map_size` whose true sum exceeds `UINT64_MAX`.
Unchecked addition wraps to a small value, potentially bypassing the
reserved-top VA check. The fix uses `check_add_overflow()` to reject
such inputs.
### Step 2.4: Fix Quality
**Record:**
- Fix is minimal, idiomatic, and matches existing kernel/amdgpu style
(`check_add_overflow` is already used elsewhere in this file and in
`amdgpu_vm.c`).
- Regression risk is very low.
- Minor note: the `dev_dbg()` on the error path still prints
`args->va_address + args->map_size` without overflow protection; that
only affects debug logging on the failure path.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame
**Record:**
- Buggy check introduced in `c4aa8dff6091cc` (“drm/amdgpu: don't map BO
in reserved region”, Oct 2020).
- `vm_size -= AMDGPU_VA_RESERVED_TOP` added in `00a11f977beb75` (Jan
2024).
- This commit is an ancestor of the current tree; the buggy code is
present in v6.18.44.
### Step 3.2: Fixes Tag
**Record:** N/A — no `Fixes:` tag in the commit message.
### Step 3.3: Related File History
**Record:**
- Related upstream commits on master: `cc768f4dd0bb9`, cherry-picked as
`cd7cfcdb4dd45`.
- `98856136c485e` (“drm/amdgpu: validate the parameters of bo mapping
operations more clearly”, Apr 2024) added
`amdgpu_vm_verify_parameters()` with `check_add_overflow(saddr, size)`
for `amdgpu_vm_bo_map()`, `amdgpu_vm_bo_replace_map()`, and
`amdgpu_vm_bo_clear_mappings()`.
- `daf5d03ddb8cc` already backported a similar integer-overflow fix in
the same file (`amdgpu_gem_align_pitch()`).
- Standalone one-commit fix; not part of a series.
### Step 3.4: Author Context
**Record:** Ce Sun is an AMD contributor with multiple amdgpu stable-
relevant fixes (reset, leak, PM). Tao Zhou reviewed; Alex Deucher
merged.
### Step 3.5: Dependencies
**Record:** No prerequisites. `linux/overflow.h` is already included in
`amdgpu_gem.c` in this tree. `check_add_overflow()` exists in
`include/linux/overflow.h`. Patch should apply cleanly.
---
## Phase 4: Mailing List and External Research
### Step 4.1: Original Discussion
**Record:** `b4 dig -c cc768f4dd0bb9` and `b4 dig -c cd7cfcdb4dd45` both
failed — no lore match found. Manual lore search blocked by bot
protection.
### Step 4.2: Reviewers
**Record:** `b4 dig -w` unavailable due to failed match. From commit
metadata: Reviewed-by Tao Zhou; Signed-off-by Alex Deucher.
### Step 4.3: Bug Report
**Record:** No external bug report, syzbot report, or crash trace
referenced.
### Step 4.4: Related Patches
**Record:** Not part of a multi-patch series. Related prior work:
`98856136c485e` (downstream VA parameter validation).
### Step 4.5: Stable List Discussion
**Record:** Could not verify stable-list discussion; lore fetch blocked.
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `amdgpu_gem_va_ioctl()` modified.
### Step 5.2: Callers
**Record:** Registered in `amdgpu_drv.c` as:
`DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl,
DRM_AUTH|DRM_RENDER_ALLOW)`
Callable from authenticated DRM render clients — common userspace GPU VA
management path.
### Step 5.3: Callees
**Record:** After validation, ioctl may call `drm_gem_object_lookup()`,
`amdgpu_gem_add_input_fence()`, `drm_exec_*`, `amdgpu_vm_lock_pd()`, and
depending on operation:
- `amdgpu_vm_bo_map()`
- `amdgpu_vm_bo_unmap()`
- `amdgpu_vm_bo_clear_mappings()`
- `amdgpu_vm_bo_replace_map()`
### Step 5.4: Reachability / Downstream Mitigation
**Record:**
- **MAP / REPLACE / CLEAR:** All call `amdgpu_vm_verify_parameters()`,
which already rejects `saddr + size` overflow via
`check_add_overflow()`.
- **UNMAP:** Uses only `va_address`; `map_size` is not used in
`amdgpu_vm_bo_unmap()`.
- **Important nuance for this tree:** The downstream overflow check
means that for MAP/CLEAR/REPLACE, overflowed inputs would eventually
fail at `amdgpu_vm_verify_parameters()` rather than creating a
mapping. However, without this ioctl fix they still proceed through
GEM lookup, fence setup, and VM locking first.
- The ioctl-level check also enforces the reserved-top region (`vm_size`
subtracts `AMDGPU_VA_RESERVED_TOP`), which is stricter than
`verify_parameters()`’s `lpfn >= max_pfn` check. Overflow cannot
bypass into the reserved-top region for MAP operations because
overflow is rejected downstream.
### Step 5.5: Similar Patterns
**Record:** `check_add_overflow()` already used in:
- `amdgpu_gem.c` (`amdgpu_gem_align_pitch()`)
- `amdgpu_vm.c` (`amdgpu_vm_verify_parameters()`)
- Other amdgpu files (vcn, etc.)
---
## Phase 6: Cross-Reference Against Local Tree (v6.18.44)
### Step 6.1: Buggy Code Present?
**Record:** Yes. Current tree at
`drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:845` still has:
`if (args->va_address + args->map_size > vm_size)`
Bug present since 2020; not introduced after the 6.18 branch.
### Step 6.2: Backport Complications
**Record:** Expected clean apply — 4-line change, `overflow.h` already
included, no structural conflicts observed.
### Step 6.3: Related Fixes Already Present?
**Record:** Downstream mitigation `amdgpu_vm_verify_parameters()` from
`98856136c485e` is already in this tree. The ioctl-level overflow fix
itself is **not** yet present. Similar overflow fix `daf5d03ddb8cc` in
the same file is already backported.
---
## Phase 7: Subsystem Context
### Step 7.1: Subsystem / Criticality
**Record:** `drivers/gpu/drm/amd/amdgpu` — GPU/DRM driver. **IMPORTANT**
for AMDGPU users; not universal core-kernel code, but ioctl validation
is security-sensitive.
### Step 7.2: Activity
**Record:** Actively maintained; recent stable-relevant amdgpu fixes in
this tree include overflow, lock leak, and NULL-check patches.
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** Users of AMDGPU with `CONFIG_DRM_AMDGPU` and render-node
access (games, compute, desktop compositors, ML workloads).
### Step 8.2: Trigger Conditions
**Record:** Userspace issues `DRM_IOCTL_AMDGPU_GEM_VA` with `va_address`
and `map_size` whose sum overflows `uint64_t`. Unprivileged users can
trigger ioctl validation if they have DRM render access (normal for GPU
users).
### Step 8.3: Failure Mode Severity
**Record:**
- **Without fix in this tree:** Overflow can bypass the ioctl reserved-
top check; for MAP/CLEAR/REPLACE, operation later fails at
`amdgpu_vm_verify_parameters()`. Primary consequence is incorrect
early validation and unnecessary work (GEM lookup, fence handling, VM
locking) on malformed input.
- **Severity:** **MEDIUM** for correctness and fail-fast behavior; **not
CRITICAL** for crash/corruption in this tree because downstream
validation already blocks dangerous MAP/CLEAR/REPLACE outcomes.
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** Correct ioctl input validation; fail-fast before
expensive locking; consistent with other amdgpu overflow backports
already in 6.18.y.
- **Risk:** Very low — 4 lines, standard helper, no API changes.
- **Ratio:** Moderate benefit, very low risk. Less urgent than fixes
with demonstrated crash/corruption, but appropriate for stable.
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Summary
**FOR backport:**
- Real integer-overflow bug in userspace-reachable ioctl validation
- Small, obviously correct, self-contained
- Buggy code present since 2020 in this tree
- `linux/overflow.h` already included; patch applies cleanly
- Precedent: similar amdgpu integer-overflow fixes already backported to
this tree (`daf5d03ddb8cc` in same file)
- Reviewed and merged by amdgpu maintainers
**AGAINST backport:**
- No user report, syzbot, or CVE cited
- Downstream `amdgpu_vm_verify_parameters()` already catches overflow
for MAP/CLEAR/REPLACE
- Practical security/corruption impact in v6.18.44 appears limited to
fail-late rather than fail-open mapping
- No lore/stable discussion found to confirm maintainer intent
**Unresolved:**
- No mailing-list thread retrieved (`b4 dig` failed; lore blocked)
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — standard overflow helper;
reviewed by AMD engineer; no Tested-by.
2. Fixes a real bug affecting users? **PASS** — real validation bug on
reachable ioctl path.
3. Important issue? **PASS (moderate)** — input-validation overflow on
DRM ioctl; not demonstrated crash/corruption in this tree, but
incorrect validation on a security-sensitive path.
4. Small and contained? **PASS** — 4 lines, one function.
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS**
### Step 9.3: Exception Category
**Record:** None of the automatic exception categories (device ID,
quirk, DT, build fix, docs). This is a runtime input-validation bug fix.
### Step 9.4: Decision Rationale
For **v6.18.44**, the buggy unchecked addition exists and should be
fixed. Although `amdgpu_vm_verify_parameters()` already prevents
overflowed MAP/CLEAR/REPLACE operations from succeeding, the ioctl
boundary should validate inputs correctly and reject malformed VA ranges
before acquiring VM locks and doing GEM work. The patch is tiny, low-
risk, and consistent with other amdgpu overflow fixes already present in
this stable tree. It does not depend on newer code and does not add
features.
---
## Verification
- [Phase 1] Parsed subject, tags, and body from provided commit message
and `git show cd7cfcdb4dd45`
- [Phase 2] Read diff and current `amdgpu_gem.c` ioctl validation code
- [Phase 3] `git describe HEAD` → `v6.18.44`
- [Phase 3] `git blame -L 843,850` → buggy check from `c4aa8dff6091cc`
(2020)
- [Phase 3] `git merge-base --is-ancestor c4aa8dff6091cc HEAD` → buggy
code is in tree
- [Phase 3] `git show 98856136c485e` → downstream
`amdgpu_vm_verify_parameters()` with `check_add_overflow`
- [Phase 3] `git merge-base --is-ancestor 98856136c485e HEAD` →
downstream mitigation present
- [Phase 3] `git log --oneline -20 -- amdgpu_gem.c` → related amdgpu
fixes in tree
- [Phase 3] `git show daf5d03ddb8cc` → similar overflow fix already
backported to this tree
- [Phase 4] `b4 dig -c cc768f4dd0bb9` → no lore match
- [Phase 4] `b4 dig -c cd7cfcdb4dd45` → no lore match
- [Phase 4] WebFetch lore search → blocked by bot protection
- [Phase 5] `grep amdgpu_gem_va_ioctl` → ioctl registered with
`DRM_AUTH|DRM_RENDER_ALLOW`
- [Phase 5] Read `amdgpu_vm_bo_map()`, `amdgpu_vm_bo_replace_map()`,
`amdgpu_vm_bo_clear_mappings()`, `amdgpu_vm_bo_unmap()` → verified
downstream validation behavior
- [Phase 5] Read `struct drm_amdgpu_gem_va` → `va_address` and
`map_size` are `__u64`
- [Phase 6] Confirmed current tree still has unchecked addition at line
845
- [Phase 6] Confirmed `#include <linux/overflow.h>` already present at
line 30
- [Phase 6] Confirmed `check_add_overflow` exists in
`include/linux/overflow.h`
- [Phase 8] Assessed failure mode: downstream catches overflow for
MAP/CLEAR/REPLACE; primary remaining issue is incorrect early
validation / unnecessary work
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 5fc9a6b1ec722..71038f4de7f9c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -818,7 +818,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
struct dma_fence_chain *timeline_chain = NULL;
struct dma_fence *fence;
struct drm_exec exec;
- uint64_t vm_size;
+ uint64_t vm_size, tmp;
int r = 0;
/* Validate virtual address range against reserved regions. */
@@ -842,7 +842,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
vm_size -= AMDGPU_VA_RESERVED_TOP;
- if (args->va_address + args->map_size > vm_size) {
+ if (check_add_overflow(args->va_address, args->map_size, &tmp) || tmp > vm_size) {
dev_dbg(dev->dev,
"va_address 0x%llx is in top reserved area 0x%llx\n",
args->va_address + args->map_size, vm_size);
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] drm/amd/pm: bound pp_dpm_set_pp_table() memcpy
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (26 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] drm/amdgpu: avoid integer overflow in VA range check Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: check find_first_zero_bit before __set_bit on kfd->doorbell_bitmap Sasha Levin
` (9 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Asad Kamal, Yang Wang, Alex Deucher, Sasha Levin, kenneth.feng,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Asad Kamal <asad.kamal@amd.com>
[ Upstream commit f193e71fa9fab2e68ef85201b106e8f580d3a25b ]
The powerplay path allocates hardcode_pp_table once with kmemdup(...,
soft_pp_table_size). memcpy(..., size) used the sysfs store count (up to
PAGE_SIZE) with no upper bound, causing heap overflow. Reject
writes where size exceeds soft_pp_table_size.
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@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:
# Stable Backport Analysis: `drm/amd/pm: bound pp_dpm_set_pp_table()
memcpy`
**Local tree:** `v6.18.44` (`stable/linux-6.18.y`, `VERSION=6`,
`PATCHLEVEL=18`, `SUBLEVEL=44`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amd/pm]` `[bound]` — bounds-check `memcpy` in
`pp_dpm_set_pp_table()` to prevent heap overflow when uploading a
powerplay table via sysfs.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Asad Kamal `<asad.kamal@amd.com>` (author)
- **Reviewed-by:** Yang Wang `<kevinyang.wang@amd.com>` (AMD reviewer)
- **Signed-off-by:** Alex Deucher `<alexander.deucher@amd.com>`
(subsystem maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`,
`Tested-by:`, or `Acked-by:`
Notable: maintainer sign-off and AMD internal review; no syzbot report.
### Step 1.3: Body analysis
**Record:**
- **Bug:** `hardcode_pp_table` is allocated once via `kmemdup(...,
soft_pp_table_size)`, but `memcpy(..., size)` uses the sysfs write
length (`count`, up to `PAGE_SIZE`) with no upper bound.
- **Symptom:** Heap buffer overflow in kernel memory.
- **Trigger:** Writing more bytes than `soft_pp_table_size` to the
`pp_table` sysfs attribute on the legacy powerplay DPM path.
- **Root cause:** Mismatch between allocation size and copy size.
- **Version info:** None in commit message.
### Step 1.4: Hidden bug fix?
**Record:** Yes — despite “bound” wording rather than “fix”, this is a
clear memory-safety bug fix (heap overflow / out-of-bounds write), not
cleanup or optimization.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c` (+3 / -0)
- **Function:** `pp_dpm_set_pp_table()`
- **Scope:** Single-file, surgical fix (3 lines)
### Step 2.2: Code flow change
**Record:**
- **Before:** After basic `hwmgr`/`pm_en` validation, code allocates (if
needed) `hardcode_pp_table` sized to `soft_pp_table_size`, then
unconditionally `memcpy(hwmgr->hardcode_pp_table, buf, size)`.
- **After:** Rejects writes where `size > hwmgr->soft_pp_table_size`
with `-EINVAL` before allocation/copy.
- **Path affected:** Sysfs write → `amdgpu_set_pp_table()` →
`amdgpu_dpm_set_pp_table()` → `pp_dpm_set_pp_table()`.
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Buffer overflow / out-of-bounds heap write (memory
safety).
- **Mechanism:** `kmemdup` allocates `soft_pp_table_size` bytes;
`memcpy` can copy up to `PAGE_SIZE` (4096) bytes from sysfs `count`.
When `size > soft_pp_table_size`, writes past the kmalloc buffer. On
subsequent writes, the buffer is not reallocated (only allocated once
when `!hardcode_pp_table`), so overflow persists.
### Step 2.4: Fix quality
**Record:**
- Fix is obviously correct and minimal.
- Mirrors the intent of the SMU-path fix in commit `1abb2648698bf`
(“avoid buffer overflow … in `smu_sys_set_pp_table()`”), which added
size validation and reallocation logic.
- Low regression risk: only rejects invalid oversized writes; legitimate
writes matching the existing table size continue to work.
- No API or structural changes.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:**
- `pp_dpm_set_pp_table()` introduced in `f3898ea12fc1f` (Eric Huang,
2015-12-11).
- Unbounded `memcpy` introduced in `4dcf9e6f2e33fe` (Eric Huang,
2016-06-01): “add uploading pptable and resetting powerplay support”.
- Bug has existed since mid-2016; present in this 6.18.y tree.
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag in commit message.
### Step 3.3: Related file history
**Record:**
- Related stable-worthy fix already in tree: `1abb2648698bf` (Feb 2025)
— SMU `smu_sys_set_pp_table()` overflow fix, with `Cc:
stable@vger.kernel.org`.
- Candidate fix (`bound pp_dpm_set_pp_table`) is **not** in this tree;
buggy code confirmed at lines 660–676 without the bounds check.
- Standalone one-patch fix, not part of a series.
### Step 3.4: Author context
**Record:** Asad Kamal is an active AMD contributor (`drm/amdgpu`,
`drm/amd/pm`). Patch reviewed by Yang Wang and committed by Alex Deucher
(AMD DRM maintainer).
### Step 3.5: Dependencies
**Record:** No prerequisites. Adds a simple validation before existing
logic. Applies cleanly to current `amd_powerplay.c` in this tree.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- `b4 dig -c 6f5c27bdc1e91` failed (commit not in local object
database).
- Web search found submission: [amd-gfx May
2026](https://lists.freedesktop.org/archives/amd-
gfx/2026-May/145636.html) by Asad Kamal, May 29, 2026.
- Review reply from Yang Wang referenced in thread index.
- No explicit stable nomination found in available search results.
- No NAKs found in available summaries.
### Step 4.2: Reviewers
**Record:** CC list included AMD maintainers (Deucher, Lazar, etc.).
`Reviewed-by: Yang Wang`; `Signed-off-by: Alex Deucher`.
### Step 4.3: Bug report
**Record:** No external bug report or syzbot link. Bug identified by
code inspection / internal AMD review.
### Step 4.4: Related patches
**Record:** Direct parallel: `1abb2648698bf` for
`smu_sys_set_pp_table()` — same sysfs interface, same class of overflow,
already in this tree and nominated for stable.
### Step 4.5: Stable list history
**Record:** lore.kernel.org blocked by bot protection; could not search
stable@ list directly. SMU sibling fix explicitly had `Cc:
stable@vger.kernel.org`.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `pp_dpm_set_pp_table()`, callers:
`amdgpu_dpm_set_pp_table()`, `amdgpu_set_pp_table()`.
### Step 5.2: Callers
**Record:**
- `amdgpu_set_pp_table()` — sysfs store for `pp_table`
(`AMDGPU_DEVICE_ATTR_RW(pp_table, ...)`)
- `amdgpu_dpm_set_pp_table()` — dispatches via `pp_funcs->set_pp_table`
under `adev->pm.mutex`
- Powerplay path: `pp_dpm_funcs.set_pp_table = pp_dpm_set_pp_table`
(legacy DPM GPUs)
- SMU path: `smu_sys_set_pp_table` (Navi+ and newer) — separate code
path, already has size checks
### Step 5.3: Callees
**Record:** `kmemdup()`, `memcpy()`, `amd_powerplay_reset()`, optional
`avfs_control()`.
### Step 5.4: Reachability
**Record:**
- Reachable from userspace via `/sys/class/drm/card*/device/pp_table`
write.
- Requires `amdgpu_pm_get_access()` (device runtime-resumed); sysfs
write typically requires root/CAP_SYS_ADMIN.
- Affects systems using legacy powerplay DPM (pre-SMU path GPUs:
Polaris, Vega, older APUs, etc.) — still common in stable/LTS
deployments.
### Step 5.5: Similar patterns
**Record:** SMU path (`smu_sys_set_pp_table`) validates
`header->usStructureSize != size` and reallocates when needed
(`1abb2648698bf`). Powerplay path lacked any size validation —
inconsistent and vulnerable.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE
### Step 6.1: Buggy code exists?
**Record:** **Yes.** Current tree at `v6.18.44` has unbounded `memcpy`
in `pp_dpm_set_pp_table()` (lines 668–676). No `size >
soft_pp_table_size` check. Bug introduced 2016; long-standing.
### Step 6.2: Backport complications
**Record:** Clean apply expected — 3-line insertion with no surrounding
churn in the function. Recent file history is handle-pointer refactors
unrelated to this hunk.
### Step 6.3: Related fixes already present?
**Record:** SMU overflow fix (`1abb2648698bf`) is an ancestor of HEAD.
Powerplay-path equivalent is **not** present.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/gpu/drm/amd/pm` — **IMPORTANT** (AMD GPU driver
power management). Not universal core kernel, but widely deployed on
desktop, laptop, and server GPUs.
### Step 7.2: Subsystem activity
**Record:** Actively maintained; recent commits in `amd_powerplay.c` and
related PM code.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Users of AMD GPUs on the legacy powerplay DPM path who write
custom powerplay tables via `pp_table` sysfs. Config/driver-specific,
but covers many still-supported Polaris/Vega-era devices.
### Step 8.2: Trigger conditions
**Record:** Write to `pp_table` with `count > soft_pp_table_size` (and
`count` up to `PAGE_SIZE`). Requires sysfs write access (typically
root). Trigger is straightforward for anyone intentionally uploading a
table.
### Step 8.3: Failure mode severity
**Record:** Heap buffer overflow → potential kernel crash, memory
corruption, possible security impact. **Severity: HIGH** (memory safety;
kernel integrity).
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH — closes a real, long-standing heap overflow on a
reachable sysfs path; aligns powerplay path with already-stable-
nominated SMU fix.
- **Risk:** VERY LOW — 3-line bounds check, rejects only invalid inputs.
- **Ratio:** Strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real heap overflow bug, present since 2016
- Reachable via `pp_table` sysfs on legacy powerplay GPUs
- Small (3 lines), obviously correct, maintainer-reviewed
- Parallel SMU fix already in this tree with stable nomination
- Prevents crash/corruption
**AGAINST backport:**
- Only affects legacy powerplay path (not Navi+/SMU GPUs)
- Sysfs write typically requires elevated privileges
- No syzbot/CVE report (but bug mechanism is clear from code)
**Unresolved:** Full lore review thread content (bot protection); no
explicit `Cc: stable` on this specific patch (but sibling fix had it).
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — trivial bounds check;
`Reviewed-by` AMD engineer; maintainer sign-off.
2. Fixes a real bug affecting users? **PASS** — heap overflow on sysfs
upload path.
3. Important issue? **PASS** — memory safety / potential crash and
corruption (**HIGH**).
4. Small and contained? **PASS** — 3 lines, one function.
5. No new features or APIs? **PASS** — validation only.
6. Can apply to local tree? **PASS** — buggy code present; patch applies
cleanly.
### Step 9.3: Exception categories
**Record:** None (not device ID, quirk, DT, build, or docs). Qualifies
as a standard security/stability bug fix.
### Step 9.4: Decision rationale
This commit fixes a genuine heap buffer overflow in
`pp_dpm_set_pp_table()` that has existed in the 6.18.y tree since the
powerplay table upload feature was added. The fix is minimal, correct,
and consistent with the already-backported SMU-path overflow fix. For
stable users running legacy AMD GPUs who use `pp_table` sysfs, this
prevents kernel memory corruption and potential crashes.
---
## Verification
- **[Phase 1]** `git describe HEAD` → `v6.18.44`; parsed commit message
tags and body from user-provided diff
- **[Phase 2]** Read `amd_powerplay.c:660-688` — confirmed missing
bounds check and unbounded `memcpy`
- **[Phase 2]** Traced call chain via grep: `amdgpu_set_pp_table` →
`amdgpu_dpm_set_pp_table` → `pp_dpm_set_pp_table`
- **[Phase 3]** `git blame -L 660,690` — function from 2015, `memcpy`
from `4dcf9e6f2e33fe` (2016-06-01)
- **[Phase 3]** `git show 4dcf9e6f2e33fe` — introduced upload/reset
support with unbounded copy
- **[Phase 3]** `git show 1abb2648698bf` — SMU sibling overflow fix with
`Cc: stable`; confirmed ancestor of HEAD
- **[Phase 3]** `git log --grep="bound pp_dpm"` — no match; fix not in
tree
- **[Phase 4]** `b4 dig -c 6f5c27bdc1e91` — failed (commit not in repo)
- **[Phase 4]** Web search — found amd-gfx submission May 29, 2026;
Reviewed-by Yang Wang in thread
- **[Phase 4]** lore.kernel.org fetch — blocked (bot protection);
stable@ search UNVERIFIED
- **[Phase 5]** Read `amdgpu_pm.c:581-601`, `amdgpu_dpm.c:1717-1733` —
sysfs write path confirmed
- **[Phase 5]** Read `amdgpu_smu.c:633-659` — SMU path has size
validation; powerplay path does not
- **[Phase 5]** Grep `set_pp_table` — two implementations: powerplay and
SMU
- **[Phase 6]** `git describe HEAD` → v6.18.44 on `stable/linux-6.18.y`
- **[Phase 6]** Confirmed buggy code at lines 668-676 without fix
- **[Phase 8]** Failure mode: heap OOB write → crash/corruption,
severity HIGH
**YES**
drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
index 554492dfa3c00..ec95faa6edcf8 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
@@ -665,6 +665,9 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
if (!hwmgr || !hwmgr->pm_en)
return -EINVAL;
+ if (size > hwmgr->soft_pp_table_size)
+ return -EINVAL;
+
if (!hwmgr->hardcode_pp_table) {
hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
hwmgr->soft_pp_table_size,
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: check find_first_zero_bit before __set_bit on kfd->doorbell_bitmap
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (27 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.1] drm/amd/pm: bound pp_dpm_set_pp_table() memcpy Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] drm/amdgpu/ras: add ras_suspend callback and use it for cp_ecc_error_irq Sasha Levin
` (8 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Xiaogang Chen, Alex Deucher, Sasha Levin, Felix.Kuehling,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Xiaogang Chen <xiaogang.chen@amd.com>
[ Upstream commit 516bf737a5602875f6c28d1028967837c8edf2c0 ]
If inx from find_first_zero_bit is beyond range not need set doorbell_bitmap.
Signed-off-by: Xiaogang Chen <xiaogang.chen@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 2664ce9143d174651a793d96a6a2326050c4f45a)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `drm/amdkfd: check find_first_zero_bit
before __set_bit on kfd->doorbell_bitmap`
**Local tree:** `v6.18.44` (Linux 6.18.44)
**Fix commit:** `2664ce9143d174651a793d96a6a2326050c4f45a` — **not** in
this tree; buggy code is still present.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amdkfd]` `[check]` — validate `find_first_zero_bit`
result before calling `__set_bit` on `kfd->doorbell_bitmap`.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Xiaogang Chen `<xiaogang.chen@amd.com>` (author)
- **Reviewed-by:** Alex Deucher `<alexander.deucher@amd.com>` (AMD DRM
maintainer)
- **Signed-off-by:** Alex Deucher `<alexander.deucher@amd.com>`
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable`, `Tested-by:`, or
`Acked-by:` tags
- `(cherry picked from commit 2664ce9143d1...)` — pipeline marker;
ignored per instructions
### Step 1.3: Body analysis
**Record:**
- **Bug:** When `find_first_zero_bit` finds no free bit, it returns `nb`
(the search size). The old code called `__set_bit(inx, ...)` before
checking whether `inx` is in range.
- **Symptom:** Out-of-bounds bitmap write when the bitmap is exhausted;
on large-page systems, also leaks bitmap slots on the error path (set
bit, then return NULL).
- **Root cause:** Range check was placed after `__set_bit` instead of
before it.
### Step 1.4: Hidden bug fix?
**Record:** Yes. Despite the terse message, this is a memory-safety /
resource-management fix, not cosmetic cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c` (+5 / -3 lines)
- **Function:** `kfd_get_kernel_doorbell()`
- **Scope:** Single-file, surgical fix
### Step 2.2: Code flow change
**Record:**
- **Before:** lock → `find_first_zero_bit` → `__set_bit` → unlock → if
`inx >= 1024` return NULL
- **After:** lock → `find_first_zero_bit` → if `inx >= 1024` unlock and
return NULL → `__set_bit` → unlock
- **Affected path:** Error path when no kernel doorbell slot is
available
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Out-of-bounds access / bitmap resource leak
- **Mechanism:** `doorbell_bitmap` is allocated with
`bitmap_zalloc(PAGE_SIZE / sizeof(u32))` (1024 bits on 4 KiB pages).
`find_first_zero_bit(..., PAGE_SIZE / sizeof(u32))` returns `1024`
when full. `__set_bit(1024, ...)` writes past the end of a 1024-bit
bitmap. On larger pages, indices 1024..(PAGE_SIZE/4-1) could be set
and then discarded via `return NULL`, leaking slots.
### Step 2.4: Fix quality
**Record:**
- Obviously correct; mirrors the process-doorbell pattern in
`kfd_device_queue_manager.c` (check before `set_bit`)
- Minimal change, no API changes
- **Regression risk:** Very low — only affects the exhaustion error path
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:**
- Function dates to 2014 (`19f6d2a660340d`, Oded Gabbay)
- `find_first_zero_bit` with `PAGE_SIZE / sizeof(u32)` added in
`c31866651086fc` (Jul 2023, Shashank Sharma)
- The check-after-set pattern predates 2023; the 2023 change did not
introduce the ordering bug, but kept it
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag present.
### Step 3.3: Related file history
**Record:**
- Recent `kfd_doorbell.c` changes are doorbell-manager refactors (2023)
- No related fix for this issue already in the tree
- Part of a 3-patch series per b4; patch 1 is unrelated
(`AMDKFD_IOC_GET_DMABUF_INFO`)
### Step 3.4: Author context
**Record:** Xiaogang Chen is an AMD contributor; Alex Deucher
(maintainer) reviewed and committed.
### Step 3.5: Dependencies
**Record:** Standalone — no prerequisite commits required. Applies
cleanly to current `kfd_doorbell.c`.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- **b4 dig URL:**
https://patch.msgid.link/20260528184656.123149-2-xiaogang.chen@amd.com
- **Series:** `[PATCH 2/3]` — patch 1 is unrelated ioctl work
- Lore fetch blocked by bot protection; thread content not directly
readable
### Step 4.2: Reviewers
**Record:** CC'd to `amd-gfx@lists.freedesktop.org`; Reviewed-by Alex
Deucher (maintainer).
### Step 4.3: Bug reports
**Record:** No external bug report, syzbot report, or crash trace
referenced.
### Step 4.4: Related patches
**Record:** Patch 2/3 is independent of patches 1 and 3 for this fix's
correctness.
### Step 4.5: Stable list history
**Record:** Not searched separately; no stable nomination found in
commit metadata.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `kfd_get_kernel_doorbell()`, `kfd_release_kernel_doorbell()`
### Step 5.2: Callers
**Record:**
- `kfd_kernel_queue.c:76` — `kernel_queue_init()` for HIQ/DIQ queues
- Typically 1–2 kernel queues per KFD device (HIQ + optional DIQ)
- Error path at line 78–80 handles NULL return
### Step 5.3: Callees
**Record:** `mutex_lock/unlock`, `find_first_zero_bit`, `__set_bit`,
`amdgpu_doorbell_index_on_bar`
### Step 5.4: Reachability
**Record:**
- Triggered during KFD device init / debug-queue setup (`CONFIG_HSA_AMD`
/ AMDGPU KFD)
- Not directly userspace-syscall reachable, but reachable during GPU
compute driver init
- Exhaustion requires ~1024 allocations without release — unrealistic in
normal use (~2 kernel queues), but possible with a doorbell leak
### Step 5.5: Similar patterns
**Record:** Process doorbells in `kfd_device_queue_manager.c:484–490`
already check `found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS` **before**
`set_bit`. This fix aligns kernel doorbells with that correct pattern.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE
### Step 6.1: Buggy code present?
**Record:** **Yes.** Current tree at lines 155–162 still has check-
after-set:
```155:162:drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
mutex_lock(&kfd->doorbell_mutex);
inx = find_first_zero_bit(kfd->doorbell_bitmap, PAGE_SIZE /
sizeof(u32));
__set_bit(inx, kfd->doorbell_bitmap);
mutex_unlock(&kfd->doorbell_mutex);
if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
return NULL;
```
Bitmap allocation at line 75: `bitmap_zalloc(PAGE_SIZE / sizeof(u32))` —
1024 bits on 4 KiB pages. `KFD_MAX_NUM_OF_QUEUES_PER_PROCESS` = 1024
(`kfd_priv.h:97`).
### Step 6.2: Backport difficulty
**Record:** Clean apply expected — 8-line hunk, no conflicts observed.
### Step 6.3: Related fixes already present?
**Record:** None. `git merge-base --is-ancestor 2664ce9143d1 HEAD` →
NOT_IN_TREE.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/gpu/drm/amd/amdkfd` — **PERIPHERAL** (AMD GPU
compute / ROCm users with `CONFIG_HSA_AMD`)
### Step 7.2: Activity
**Record:** Actively maintained; recent doorbell-manager refactoring in
2023.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** AMD GPU users with KFD/ROCm enabled — not universal, but
real production users.
### Step 8.2: Trigger conditions
**Record:**
- All doorbell bitmap slots consumed (1024 on 4 KiB pages)
- Normal operation uses ~2 kernel doorbells per device
- **Likelihood:** Very low without a resource leak; **possible** with a
leak bug
### Step 8.3: Failure mode severity
**Record:**
- **OOB `__set_bit`:** Memory corruption adjacent to bitmap → potential
crash or unpredictable behavior — **HIGH** if triggered
- **Bitmap leak (large pages):** Gradual exhaustion — **MEDIUM**
- **Practical impact today:** Low due to unlikely trigger
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** Prevents OOB write and bitmap leaks on error path; aligns
with existing correct pattern
- **Risk:** Minimal — 5-line reorder/addition on error path only
- **Ratio:** Favorable — near-zero risk, real correctness fix
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real out-of-bounds bitmap write when exhausted
- Obviously correct; maintainer-reviewed
- Small, self-contained, clean apply
- Matches established pattern in same subsystem
- Buggy code confirmed present in v6.18.44
- Memory-safety class of fix
**AGAINST backport:**
- No user reports or fuzzer findings
- Trigger extremely unlikely in normal kernel-queue usage (~2 doorbells)
- Bug present since 2014 without known incidents
- Config/driver-specific (AMD KFD only)
**Unresolved:** None affecting the decision.
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — logic verified; maintainer
reviewed (no runtime test cited)
2. Fixes a real bug? **PASS** — OOB `__set_bit` on exhaustion
3. Important issue? **PASS** — memory corruption (severity high if
triggered; trigger rare)
4. Small and contained? **PASS** — 8 lines, one function
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** — code exists; fix not yet applied
### Step 9.3: Exception categories
**Record:** None (not a quirk, device ID, DT, build, or docs fix).
### Step 9.4: Decision rationale
This is a small, maintainer-reviewed memory-safety fix for a genuine
ordering bug: `__set_bit` was called before validating the index
returned by `find_first_zero_bit`. When the bitmap is full, that is an
out-of-bounds write. The trigger is rare for kernel doorbells (only
HIQ/DIQ, typically ~2 per device), but the fix is trivial, matches the
correct pattern already used for process doorbells in the same driver,
and has essentially no regression risk. For the 6.18.y stable tree where
the buggy code is present and the fix is absent, this meets stable
kernel criteria.
---
## Verification
- **[Phase 1]** `git show 2664ce9143d1` — parsed message and tags
- **[Phase 2]** Read `kfd_doorbell.c:149–176` — confirmed check-after-
set bug; analyzed diff
- **[Phase 2]** `kfd_priv.h:97` — `KFD_MAX_NUM_OF_QUEUES_PER_PROCESS` =
1024
- **[Phase 2]** `kfd_doorbell.c:75` — bitmap sized `PAGE_SIZE /
sizeof(u32)` bits
- **[Phase 3]** `git blame -L 150,176 kfd_doorbell.c` — function history
since 2014
- **[Phase 3]** `git show c31866651086fc` — 2023 doorbell-mgr refactor
- **[Phase 3]** `git show 19f6d2a660340d` — original code had same
ordering bug
- **[Phase 3]** `git log --oneline -15 -- kfd_doorbell.c` — no duplicate
fix
- **[Phase 4]** `b4 dig -c 2664ce9143d1` — lore URL found; patch 2/3 of
series
- **[Phase 4]** `b4 dig -w` — amd-gfx list CC'd
- **[Phase 4]** `b4 dig -a` — v1 series identified
- **[Phase 5]** `grep kfd_get_kernel_doorbell` — caller in
`kfd_kernel_queue.c:76`
- **[Phase 5]** Read `kfd_kernel_queue.c:76–80, 191, 224` — NULL
handled; release on cleanup
- **[Phase 5]** Read `kfd_device_queue_manager.c:484–490` — correct
check-before-set pattern
- **[Phase 6]** `git describe HEAD` — v6.18.44
- **[Phase 6]** `git merge-base --is-ancestor 2664ce9143d1 HEAD` —
NOT_IN_TREE
- **[Phase 6]** Read current `kfd_doorbell.c` — buggy code confirmed
present
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
index 05c74887fd6fd..fdcf7f2d1b5b4 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
@@ -153,14 +153,16 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
u32 inx;
mutex_lock(&kfd->doorbell_mutex);
+
inx = find_first_zero_bit(kfd->doorbell_bitmap, PAGE_SIZE / sizeof(u32));
+ if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) {
+ mutex_unlock(&kfd->doorbell_mutex);
+ return NULL;
+ }
__set_bit(inx, kfd->doorbell_bitmap);
mutex_unlock(&kfd->doorbell_mutex);
- if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
- return NULL;
-
*doorbell_off = amdgpu_doorbell_index_on_bar(kfd->adev,
kfd->doorbells,
inx,
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu/ras: add ras_suspend callback and use it for cp_ecc_error_irq
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (28 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: check find_first_zero_bit before __set_bit on kfd->doorbell_bitmap Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdkfd: fix SMI event cross-process information leak Sasha Levin
` (7 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Yunxiang Li, Alex Deucher, Sasha Levin, christian.koenig, airlied,
simona, amd-gfx, dri-devel, linux-kernel
From: Yunxiang Li <Yunxiang.Li@amd.com>
[ Upstream commit e3829992dd9fa0a82511af4f01733fc854cd15a5 ]
cp_ecc_error_irq is acquired in amdgpu_gfx_ras_late_init() but
released in gfx_v9_0_hw_fini(), so the put site has to query
amdgpu_irq_enabled() because the get is skipped on SR-IOV VF.
ras_late_init / ras_fini have no suspend counterpart, so move the
put to amdgpu_gfx_ras_suspend() / amdgpu_gfx_ras_fini() and add a
matching ras_suspend callback that is invoked from
amdgpu_ras_suspend() before disable_all_features(). The get and
put now sit in the same place and check the same condition (not
VF, funcs registered), no refcount querying needed.
An active flag gates ras_fini so the
suspend-then-unload-without-resume path falls into
amdgpu_ras_block_late_fini_default() instead of double-releasing
what ras_suspend already cleaned up.
Drop the cp_ecc_error_irq put from gfx_v9_0_hw_fini(). gfx_v8_0
manages cp_ecc_error_irq locally and is unaffected; no other GFX
generation has this IRQ.
Signed-off-by: Yunxiang Li <Yunxiang.Li@amd.com>
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:
# Stable Backport Analysis: `drm/amdgpu/ras: add ras_suspend callback
and use it for cp_ecc_error_irq`
**Local tree:** Linux **6.18.44** (`git describe HEAD` → `v6.18.44`)
**Upstream commit:** `e3829992dd9fa` (not present in this tree; cherry-
pick applies cleanly)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1 — Subject parse**
Record: `[drm/amdgpu/ras]` — **add** (lifecycle fix disguised as
infrastructure) — add `ras_suspend` callback and relocate
`cp_ecc_error_irq` put to match its get site.
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Yunxiang Li <Yunxiang.Li@amd.com>` (author)
- `Acked-by: Alex Deucher <alexander.deucher@amd.com>` (subsystem
maintainer)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (committer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`,
`Tested-by:`, or `Reviewed-by:`
Notable: maintainer Ack from Alex Deucher is a strong quality signal.
**Step 1.3 — Body analysis**
Record:
- **Bug:** `cp_ecc_error_irq` is acquired in
`amdgpu_gfx_ras_late_init()` but released in `gfx_v9_0_hw_fini()`,
with mismatched conditions (get skipped on SR-IOV VF; put uses broader
RAS-support check).
- **Symptom:** `amdgpu_irq_put()` called when IRQ was never acquired →
`WARN_ON(!amdgpu_irq_enabled())` in `amdgpu_irq.c:637`.
- **Root cause:** No suspend counterpart to `ras_late_init`/`ras_fini`;
get/put live in different subsystems with different guards.
- **Fix approach:** Add `ras_suspend` callback, move put to
`amdgpu_gfx_ras_suspend()`/`amdgpu_gfx_ras_fini()` with matching `!VF
&& funcs` condition; add `active` flag to avoid double-release on
suspend-then-unload path.
**Step 1.4 — Hidden bug fix?**
Record: **Yes.** Despite "add callback" wording, this is a reference-
counting / lifecycle bug fix. It corrects asymmetric IRQ get/put that
can trigger kernel warnings and incorrect teardown ordering.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1 — Inventory**
Record:
| File | Change |
|------|--------|
| `amdgpu_gfx.c` | +26/-4 |
| `amdgpu_gfx.h` | +3/-1 |
| `amdgpu_ras.c` | +32/-4 |
| `amdgpu_ras.h` | +1 |
| `gfx_v9_0.c` | -2 |
| **Total** | +53/-11, 5 files |
Functions modified: `amdgpu_gfx_ras_late_init`, new
`amdgpu_gfx_ras_suspend`, new `amdgpu_gfx_ras_fini`,
`amdgpu_gfx_ras_sw_init`, `amdgpu_ras_suspend`, `amdgpu_ras_late_init`,
`amdgpu_ras_fini`, `gfx_v9_0_hw_fini`.
Scope: **single-subsystem, surgical** (amdgpu RAS/GFX9).
**Step 2.2 — Code flow per hunk**
| Hunk | Before → After |
|------|----------------|
| `amdgpu_gfx_ras_late_init` | VF early-return then separate `irq_get` →
combined `!VF && funcs` guard for `irq_get` |
| New `amdgpu_gfx_ras_suspend` | No suspend cleanup → `irq_put` with
same guard as get |
| New `amdgpu_gfx_ras_fini` | No gfx-specific fini (header-only orphan
declaration) → `irq_put` + `amdgpu_ras_block_late_fini` |
| `amdgpu_gfx_ras_sw_init` | Only sets `ras_late_init` → also sets
default `ras_suspend` and `ras_fini` |
| `amdgpu_ras_suspend` | Only disables RAS features → iterates blocks,
calls `ras_suspend`, clears `active` |
| `amdgpu_ras_late_init` | No tracking → sets `node->active = true`
after successful late_init |
| `amdgpu_ras_fini` | Always calls custom `ras_fini` if supported →
gated by `ras_node->active` to avoid double-cleanup after suspend |
| `gfx_v9_0_hw_fini` | `irq_put(cp_ecc_error_irq)` if RAS supported →
removed (now handled in RAS layer) |
**Step 2.3 — Bug mechanism**
Record: **Reference counting / resource lifecycle bug.**
- Get: `amdgpu_irq_get()` in `amdgpu_gfx_ras_late_init()` — only when
`!amdgpu_sriov_vf(adev) && cp_ecc_error_irq.funcs`.
- Put (current tree): `amdgpu_irq_put()` in `gfx_v9_0_hw_fini()` — when
`amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)` only.
- On SR-IOV VF with RAS telemetry enabled, late_init runs (see
`amdgpu_ras_late_init` VF check) but gfx `irq_get` is skipped; hw_fini
still calls `irq_put` before the VF early-return → `WARN_ON` in
`amdgpu_irq_put()`.
**Step 2.4 — Fix quality**
Record: Fix is **obviously correct** — symmetric get/put with identical
conditions, proper suspend hook, `active` flag prevents double-release.
Minimal regression risk: no blocks currently register custom `ras_fini`
in this tree (verified via grep), so the `active` flag behavior only
affects the newly registered gfx callbacks.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1 — Blame**
Record:
- `gfx_v9_0_hw_fini` put lines: `d97b02bb9c7aa` (May 2023) — prior fix
for put-without-get when legacy GFX RAS disabled; did not fix VF
condition mismatch.
- `irq_get` in `amdgpu_gfx_ras_late_init`: `6caeee7a708c0` (Sep 2019).
- Buggy asymmetric lifecycle present since **v5.x** era; still present
in **6.18.44**.
**Step 3.2 — Fixes: tag**
Record: Not applicable (no `Fixes:` tag). Related prior fix
`d97b02bb9c7aa` is in this tree but incomplete for the VF/get-put
mismatch.
**Step 3.3 — File history**
Record: Part of 2-patch series `[PATCH 0/2] drm/amdgpu: balance GFX IRQ
get/put across init/suspend/fini`. This commit is **patch 1/2** and is
**self-contained** for `cp_ecc_error_irq`. Patch 2/2 (`9117d8be850ba` on
master) addresses fault/EOP IRQs separately and is **not a
prerequisite**.
**Step 3.4 — Author context**
Record: Yunxiang Li is an AMD contributor. Alex Deucher (maintainer)
Acked and committed.
**Step 3.5 — Dependencies**
Record: **Standalone.** Cherry-pick to 6.18.44 applies cleanly with
auto-merge. No prerequisite commits required.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1 — Original discussion**
Record:
- URL:
https://patch.msgid.link/20260527233504.1830940-2-Yunxiang.Li@amd.com
- Series: v1 only (no v2/v3 revisions found)
- Patch 1/2 of 2-patch series
**Step 4.2 — Reviewers**
Record: CC'd to `amd-gfx@lists.freedesktop.org`, Alex Deucher, Christian
König. Alex Deucher Acked.
**Step 4.3 — Bug report**
Record: No external bug report or syzbot link. Mechanism is documented
in commit message; similar prior bug (`d97b02bb9c7aa`) had stack trace
from `gfx_v9_0_hw_fini` → `amdgpu_irq_put` during suspend.
**Step 4.4 — Related patches**
Record: Patch 2/2 (`drm/amdgpu/gfx: move fault and EOP IRQ get/put to
hw_init/hw_fini`) is independent. Not required for this fix.
**Step 4.5 — Stable list history**
Record: No `Cc: stable` nomination found in thread. Not a negative
signal per instructions.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1 — Key functions**
Record: `amdgpu_gfx_ras_late_init`, `amdgpu_gfx_ras_suspend`,
`amdgpu_gfx_ras_fini`, `amdgpu_ras_suspend`, `amdgpu_ras_late_init`,
`amdgpu_ras_fini`, `gfx_v9_0_hw_fini`, `amdgpu_irq_get`,
`amdgpu_irq_put`.
**Step 5.2 — Callers**
Record:
- `amdgpu_ras_suspend` ← `amdgpu_device_suspend()` (line 5261) —
**system suspend path**
- `gfx_v9_0_hw_fini` ← `gfx_v9_0_suspend` ← `amdgpu_ip_block_suspend` ←
`amdgpu_device_ip_suspend_phase2` — **suspend and driver unload**
- `amdgpu_ras_late_init` ← `amdgpu_device_ip_late_init` — boot and
**resume** (line 5365)
- `amdgpu_ras_fini` ← `amdgpu_device_ip_fini` — driver unload
**Step 5.3 — Key callees**
Record: `amdgpu_irq_get/put` (atomic refcount on `enabled_types`),
`amdgpu_ras_block_late_fini`, `amdgpu_ras_disable_all_features`.
**Step 5.4 — Reachability**
Record: **Yes, reachable from normal operations:**
- System suspend/resume (laptop, server)
- SR-IOV VF with RAS telemetry
- Driver unload after suspend (no resume)
- Config: `CONFIG_DRM_AMDGPU` + GFX9 hardware + RAS enabled
**Step 5.5 — Similar patterns**
Record: Prior fix `d97b02bb9c7aa` addressed same `amdgpu_irq_put` WARN
class for different condition (`amdgpu_ras_is_supported` vs actually
enabled). Patch 2/2 in the series addresses similar get/put split for
other GFX IRQs.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE
**Step 6.1 — Buggy code exists?**
Record: **Yes.** Current 6.18.44 tree has:
- `irq_get` in `amdgpu_gfx_ras_late_init` with VF skip (lines 937-943)
- `irq_put` in `gfx_v9_0_hw_fini` with only `amdgpu_ras_is_supported`
guard (lines 4087-4088)
- No `ras_suspend` callback infrastructure
- Orphan `amdgpu_gfx_ras_fini` declaration in header with no
implementation
**Step 6.2 — Backport complications**
Record: **Clean apply** — tested via `git cherry-pick --no-commit
e3829992dd9fa`, auto-merged all 5 files.
**Step 6.3 — Related fixes already present?**
Record: `d97b02bb9c7aa` (partial fix) is in tree. This commit is not
duplicated; it completes the lifecycle fix.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1 — Subsystem criticality**
Record: `drivers/gpu/drm/amd/amdgpu` — **IMPORTANT** (AMD GPU driver,
widely deployed on desktops, laptops, servers, cloud VF).
**Step 7.2 — Activity**
Record: Actively maintained; RAS subsystem receives regular fixes in
6.18.y.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1 — Who is affected**
Record: Users of **AMD GFX9 GPUs** with **RAS enabled** — especially
**SR-IOV virtual functions** with RAS telemetry, and any system using
suspend/resume with RAS.
**Step 8.2 — Trigger conditions**
Record:
- SR-IOV VF + RAS telemetry + suspend → **high likelihood** of
`amdgpu_irq_put` WARN
- Suspend → unload without resume with new `ras_fini` → potential double
`irq_put` without `active` flag
- Non-VF suspend/resume works today but has architectural fragility
**Step 8.3 — Failure mode severity**
Record: `WARN_ON` in `amdgpu_irq_put` during suspend — **MEDIUM**
(kernel warning, incorrect IRQ state; not typically a panic but
indicates broken refcounting). Suspend-then-unload double-release —
**MEDIUM-HIGH** (refcount underflow / further WARNs).
**Step 8.4 — Risk-benefit**
Record:
- **Benefit:** HIGH for enterprise VF/cloud; MEDIUM for general amdgpu
suspend users
- **Risk:** LOW — 53 lines, localized, maintainer-acked, applies
cleanly, no custom `ras_fini` handlers exist in tree to be disrupted
- **Ratio:** Favorable
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1 — Evidence summary**
| FOR backport | AGAINST backport |
|---|---|
| Fixes real refcounting/lifecycle bug | Part of 2-patch series (but
patch 1 is self-contained) |
| Triggerable on suspend (common path) | No syzbot/user report attached
|
| SR-IOV VF path clearly broken in current code | WARN severity, not
panic |
| Maintainer Acked-by Alex Deucher | |
| Applies cleanly to 6.18.44 | |
| Small, contained (53 lines) | |
| Similar prior fix (`d97b02`) was stable material | |
| Resume path re-acquires via `amdgpu_ras_late_init` in
`amdgpu_device_resume` | |
**Step 9.2 — Stable rules checklist**
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — symmetric lifecycle,
maintainer ack; no explicit Tested-by |
| 2. Fixes real bug affecting users? | **PASS** — VF suspend WARN,
suspend/unload edge case |
| 3. Important issue? | **PASS** — MEDIUM severity (WARN, IRQ refcount
corruption class) |
| 4. Small and contained? | **PASS** — 5 files, 53 insertions |
| 5. No new features/APIs? | **PASS** — internal driver callback only |
| 6. Can apply to local tree? | **PASS** — clean cherry-pick verified |
**Step 9.3 — Exception categories**
Record: None (not device ID, quirk, DT, build fix, or docs).
**Step 9.4 — Decision rationale**
This commit fixes a longstanding asymmetric IRQ lifecycle in the amdgpu
RAS/GFX9 path that can trigger `WARN_ON` during system suspend on SR-IOV
VFs and creates fragile teardown on suspend-then-unload. The fix is
small, maintainer-reviewed, applies cleanly to 6.18.44, and the affected
code is present in this tree. The benefit outweighs the low regression
risk.
---
## Verification
- [Phase 1] Parsed subject, tags, body; identified hidden refcounting
bug
- [Phase 2] Analyzed all 5 file diffs; classified as reference-
counting/lifecycle fix
- [Phase 3] `git blame` on `gfx_v9_0.c:4087-4088` → `d97b02bb9c7aa`
(2023); `irq_get` introduced `6caeee7a708c0` (2019); both ancestors in
tree
- [Phase 3] `git log --grep` found commit `e3829992dd9fa` on
`origin/master`; not ancestor of HEAD (not in 6.18.44)
- [Phase 3] Confirmed patch 1/2 is standalone; patch 2/2
(`9117d8be850ba`) is separate
- [Phase 4] `b4 dig -c e3829992dd9fa` →
https://patch.msgid.link/20260527233504.1830940-2-Yunxiang.Li@amd.com
- [Phase 4] `b4 dig -a` → v1 only
- [Phase 4] `b4 dig -w` → CC: amd-gfx, Alex Deucher, Christian König
- [Phase 4] No stable nomination in thread
- [Phase 5] Traced callers: `amdgpu_device_suspend` →
`amdgpu_ras_suspend`; `gfx_v9_0_suspend` → `gfx_v9_0_hw_fini`
- [Phase 5] Read `amdgpu_irq_put` at `amdgpu_irq.c:637` —
`WARN_ON(!amdgpu_irq_enabled())`
- [Phase 5] Grep: no `.ras_fini =` assignments in tree (no custom
ras_fini handlers)
- [Phase 6] `git describe HEAD` → v6.18.44; buggy code confirmed at
`amdgpu_gfx.c:937-943`, `gfx_v9_0.c:4087-4088`
- [Phase 6] `git cherry-pick --no-commit e3829992dd9fa` → clean auto-
merge on all 5 files
- [Phase 6] `amdgpu_device_resume` calls `amdgpu_device_ip_late_init` →
`amdgpu_ras_late_init` (re-acquires IRQ on resume)
- [Phase 8] Failure mode: WARN_ON during VF suspend — MEDIUM severity
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 26 ++++++++++++++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 3 ++-
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 32 +++++++++++++++++++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 1 +
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 --
5 files changed, 53 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 40e7482980692..46c0b986db51d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -934,10 +934,7 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
if (r)
return r;
- if (amdgpu_sriov_vf(adev))
- return r;
-
- if (adev->gfx.cp_ecc_error_irq.funcs) {
+ if (!amdgpu_sriov_vf(adev) && adev->gfx.cp_ecc_error_irq.funcs) {
r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
if (r)
goto late_fini;
@@ -952,6 +949,21 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
return r;
}
+void amdgpu_gfx_ras_suspend(struct amdgpu_device *adev,
+ struct ras_common_if *ras_block)
+{
+ if (!amdgpu_sriov_vf(adev) && adev->gfx.cp_ecc_error_irq.funcs)
+ amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
+}
+
+void amdgpu_gfx_ras_fini(struct amdgpu_device *adev,
+ struct ras_common_if *ras_block)
+{
+ if (!amdgpu_sriov_vf(adev) && adev->gfx.cp_ecc_error_irq.funcs)
+ amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
+ amdgpu_ras_block_late_fini(adev, ras_block);
+}
+
int amdgpu_gfx_ras_sw_init(struct amdgpu_device *adev)
{
int err = 0;
@@ -980,6 +992,12 @@ int amdgpu_gfx_ras_sw_init(struct amdgpu_device *adev)
if (!ras->ras_block.ras_late_init)
ras->ras_block.ras_late_init = amdgpu_gfx_ras_late_init;
+ if (!ras->ras_block.ras_suspend)
+ ras->ras_block.ras_suspend = amdgpu_gfx_ras_suspend;
+
+ if (!ras->ras_block.ras_fini)
+ ras->ras_block.ras_fini = amdgpu_gfx_ras_fini;
+
/* If not defined special ras_cb function, use default ras_cb */
if (!ras->ras_block.ras_cb)
ras->ras_block.ras_cb = amdgpu_gfx_process_ras_data_cb;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index fb5f7a0ee029f..8949037b62a43 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -603,7 +603,8 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable);
void amdgpu_gfx_off_ctrl_immediate(struct amdgpu_device *adev, bool enable);
int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value);
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
-void amdgpu_gfx_ras_fini(struct amdgpu_device *adev);
+void amdgpu_gfx_ras_suspend(struct amdgpu_device *adev, struct ras_common_if *ras_block);
+void amdgpu_gfx_ras_fini(struct amdgpu_device *adev, struct ras_common_if *ras_block);
int amdgpu_get_gfx_off_entrycount(struct amdgpu_device *adev, u64 *value);
int amdgpu_get_gfx_off_residency(struct amdgpu_device *adev, u32 *residency);
int amdgpu_set_gfx_off_residency(struct amdgpu_device *adev, bool value);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 4c1a65fffede7..16ae44e131ad4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -92,6 +92,9 @@ struct amdgpu_ras_block_list {
struct list_head node;
struct amdgpu_ras_block_object *ras_obj;
+
+ /* set by ras_late_init, cleared by ras_suspend/ras_fini */
+ bool active;
};
const char *get_ras_block_str(struct ras_common_if *ras_block)
@@ -4392,10 +4395,23 @@ void amdgpu_ras_resume(struct amdgpu_device *adev)
void amdgpu_ras_suspend(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+ struct amdgpu_ras_block_list *node;
+ struct amdgpu_ras_block_object *obj;
if (!adev->ras_enabled || !con)
return;
+ /* run per-block ras_suspend before tearing down the RAS context */
+ list_for_each_entry(node, &adev->ras_list, node) {
+ if (!node->active)
+ continue;
+
+ obj = node->ras_obj;
+ if (obj && obj->ras_suspend)
+ obj->ras_suspend(adev, &obj->ras_comm);
+ node->active = false;
+ }
+
amdgpu_ras_disable_all_features(adev, 0);
/* Make sure all ras objects are disabled. */
if (AMDGPU_RAS_GET_FEATURES(con->features))
@@ -4449,8 +4465,15 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
obj->ras_comm.name, r);
return r;
}
- } else
- amdgpu_ras_block_late_init_default(adev, &obj->ras_comm);
+ } else {
+ r = amdgpu_ras_block_late_init_default(adev, &obj->ras_comm);
+ if (r) {
+ dev_err(adev->dev, "%s failed to execute ras_block_late_init_default! ret:%d\n",
+ obj->ras_comm.name, r);
+ return r;
+ }
+ }
+ node->active = true;
}
return 0;
@@ -4487,11 +4510,12 @@ int amdgpu_ras_fini(struct amdgpu_device *adev)
list_for_each_entry_safe(ras_node, tmp, &adev->ras_list, node) {
if (ras_node->ras_obj) {
obj = ras_node->ras_obj;
- if (amdgpu_ras_is_supported(adev, obj->ras_comm.block) &&
- obj->ras_fini)
+ /* fall back to default cleanup if ras_suspend already ran */
+ if (ras_node->active && obj->ras_fini)
obj->ras_fini(adev, &obj->ras_comm);
else
amdgpu_ras_block_late_fini_default(adev, &obj->ras_comm);
+ ras_node->active = false;
}
/* Clear ras blocks from ras_list and free ras block list node */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
index 6cf0dfd38be8b..8160c4d598543 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -731,6 +731,7 @@ struct amdgpu_ras_block_object {
int (*ras_block_match)(struct amdgpu_ras_block_object *block_obj,
enum amdgpu_ras_block block, uint32_t sub_block_index);
int (*ras_late_init)(struct amdgpu_device *adev, struct ras_common_if *ras_block);
+ void (*ras_suspend)(struct amdgpu_device *adev, struct ras_common_if *ras_block);
void (*ras_fini)(struct amdgpu_device *adev, struct ras_common_if *ras_block);
ras_ih_cb ras_cb;
const struct amdgpu_ras_block_hw_ops *hw_ops;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index c5549a5abcd43..9d7214bcaadb9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -4084,8 +4084,6 @@ static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
- amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdkfd: fix SMI event cross-process information leak
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (29 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] drm/amdgpu/ras: add ras_suspend callback and use it for cp_ecc_error_irq Sasha Levin
@ 2026-08-31 13:29 ` Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu: add first record offset check Sasha Levin
` (6 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:29 UTC (permalink / raw)
To: patches, stable
Cc: Yongqiang Sun, Alex Deucher, Sasha Levin, Felix.Kuehling,
christian.koenig, airlied, simona, amd-gfx, dri-devel,
linux-kernel
From: Yongqiang Sun <Yongqiang.Sun@amd.com>
[ Upstream commit 92a8dba246d371fe268280e5fd74b0955688e6df ]
kfd_smi_ev_enabled() skips the suser privilege check when pid=0.
PROCESS_START, PROCESS_END, and VMFAULT events are emitted with
pid=0 while carrying another process's PID and command name, so any
/dev/kfd user in the render group can monitor all GPU workloads.
Pass the target process PID into kfd_smi_event_add() for these events
so the existing per-client filter restricts delivery to the owning
process or CAP_SYS_ADMIN subscribers.
Signed-off-by: Yongqiang Sun <Yongqiang.Sun@amd.com>
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:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
Record: `[drm/amdkfd] [fix] SMI event cross-process information leak`
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Yongqiang Sun <Yongqiang.Sun@amd.com>` (author)
- `Acked-by: Alex Deucher <alexander.deucher@amd.com>` (AMD DRM
maintainer)
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (committer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Link:`, or `Cc:
stable@vger.kernel.org`
Notable: maintainer Acked-by; no syzbot or user bug report tags.
**Step 1.3 — Body analysis**
Record:
- **Bug:** `kfd_smi_ev_enabled()` does not apply per-client PID
filtering when the filter PID argument is `0`. `PROCESS_START`,
`PROCESS_END`, and `VMFAULT` events are emitted with filter PID `0`
but carry another process's PID and command name in the event payload.
- **Symptom:** Any `/dev/kfd` user in the render group can monitor all
GPU workloads (other processes' PIDs and command names).
- **Root cause:** `kfd_smi_event_add(0, ...)` bypasses the `if (pid &&
...)` guard in `kfd_smi_ev_enabled()`.
- **Fix:** Pass `task_info->tgid` into `kfd_smi_event_add()` so the
existing filter restricts delivery to the owning process or
`CAP_SYS_ADMIN` subscribers (`client->suser`).
**Step 1.4 — Hidden bug fix?**
Record: No — this is an explicit security/privacy bug fix, not disguised
cleanup.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
Record:
- **File:** `drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c` (+5 / -3
lines)
- **Functions modified:** `kfd_smi_event_update_vmfault()`,
`kfd_smi_event_process()`
- **Scope:** Single-file surgical fix
**Step 2.2 — Code flow changes**
Record:
- **Hunk 1 (`kfd_smi_event_update_vmfault`):** Before:
`kfd_smi_event_add(0, dev, VMFAULT, ...)` → all subscribed clients
receive VM fault events with other processes' PID/comm. After:
`kfd_smi_event_add(task_info->tgid, dev, VMFAULT, ...)` → only
matching client or admin receives it.
- **Hunk 2 (`kfd_smi_event_process`):** Before: `kfd_smi_event_add(0,
pdd->dev, PROCESS_START/END, ...)` → broadcast. After:
`kfd_smi_event_add(task_info->tgid, pdd->dev, ...)` → per-process
filtering.
**Step 2.3 — Bug mechanism**
Record: **Information leak / missing access control.** Category (d)
memory-safety adjacent — logic/correctness in security filtering.
`pid=0` is intentional for system-wide events (GPU reset, thermal
throttle); using it for per-process events defeats isolation.
**Step 2.4 — Fix quality**
Record: Obviously correct — uses `task_info->tgid`, which matches
`client->pid = current->tgid` set in `kfd_smi_event_open()`. Minimal
change. Low regression risk; system-wide events still use `pid=0`.
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
Record:
- `kfd_smi_ev_enabled()` filter: Philip Yang, 2022-01-13
(`163a5a58437062`); superuser logic simplified by Eric Huang,
2025-04-14 (`6b9d26089f56f`).
- VMFAULT with `pid=0`: since at least Shashank Sharma refactor,
2024-01-18 (`b8f67b9ddf4f8`); format-only change in 2024-02-16
(`663b0f1e141dc`).
- PROCESS_START/END with `pid=0`: introduced 2025-04-07
(`4172b556fd5bd`).
**Step 3.2 — Fixes: tag**
Record: Not applicable — no `Fixes:` tag. Buggy PROCESS events
introduced by `4172b556fd5bd`; VMFAULT leak predates that.
**Step 3.3 — Related file history**
Record: Recent related commits in this tree:
- `6b9d26089f56f` — superuser SMI filter fix (present)
- `4172b556fd5bd` — process start/end events (present, introduced leak)
- `9315860d05aa2` — NULL check fix for process SMI event
- `9fd86747daa6c` — queue restore string fix
- On master but not in 6.18.44: `92a8dba246d37` / `3b347d011773d` (this
fix), `1142738572ef3` (container PID reporting — separate, larger
change)
**Step 3.4 — Author context**
Record: Yongqiang Sun has at least one other amdkfd fix in history. Alex
Deucher (maintainer) Acked and committed the fix.
**Step 3.5 — Dependencies**
Record: Standalone — uses `task_info->tgid` already present in `struct
amdgpu_task_info` since 2018 (`2aa37bf58838f`). No series prerequisites.
`git apply --check` passes cleanly on 6.18.44.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
Record: `b4 dig -c 3b347d011773d` found v1 only at
https://patch.msgid.link/20260527141014.567441-1-Yongqiang.Sun@amd.com.
Lore fetch blocked by Anubis bot protection; no thread replies
retrieved.
**Step 4.2 — Reviewers**
Record: `b4 dig -w` — sent to Yongqiang Sun and `amd-
gfx@lists.freedesktop.org`. Alex Deucher Acked in commit.
**Step 4.3 — Bug report**
Record: Not applicable — no `Reported-by:` or `Link:` tags. Bug
identified by code review / internal AMD analysis per commit message.
**Step 4.4 — Related patches**
Record: Container PID fix (`1142738572ef3`) is a separate follow-up on
master; not required for this security fix to function on non-container
or host-PID setups.
**Step 4.5 — Stable list**
Record: Not searched (lore blocked). No stable nomination found in
available sources.
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
Record: `kfd_smi_ev_enabled()`, `kfd_smi_event_add()`,
`kfd_smi_event_update_vmfault()`, `kfd_smi_event_process()`,
`kfd_smi_event_open()`
**Step 5.2 — Callers**
Record:
- `kfd_smi_event_update_vmfault()` ← `kfd_int_process_v9.c`,
`kfd_int_process_v11.c`, `cik_event_interrupt.c` (GPU fault interrupt
paths)
- `kfd_smi_event_process()` ← `kfd_process.c` (process start at line
~1727, end at ~1059)
- `kfd_smi_event_open()` ← `kfd_chardev.c` via `kfd_ioctl_smi_events()`
(userspace ioctl)
**Step 5.3 — Callees**
Record: `amdgpu_vm_get_task_info_pasid()`,
`amdgpu_vm_get_task_info_vm()`, `add_event_to_kfifo()` → iterates all
SMI clients and checks `kfd_smi_ev_enabled()`.
**Step 5.4 — Reachability**
Record: Userspace opens SMI event fd via KFD ioctl (`/dev/kfd`, render
group). GPU faults and process lifecycle events are triggered by normal
KFD compute workloads. **Reachable by unprivileged render-group users**
who can subscribe to SMI events and receive other users' process
metadata.
**Step 5.5 — Similar patterns**
Record: Other per-process events (`page_fault`, `migration`,
`queue_eviction`, etc.) already pass non-zero PID and are correctly
filtered. Only VMFAULT and PROCESS_START/END incorrectly used `pid=0`.
---
## Phase 6: Cross-Reference Against Local Tree (6.18.44)
**Step 6.1 — Buggy code present?**
Record: **Yes.** Local tree is `v6.18.44` on `stable/linux-6.18.y`.
Verified:
- Line 257: `kfd_smi_event_add(0, dev, KFD_SMI_EVENT_VMFAULT, ...)`
- Line 359: `kfd_smi_event_add(0, pdd->dev, PROCESS_START/END, ...)`
- Filter at lines 168-169 skips all PID checks when `pid==0`
- Fix commit `3b347d011773d` is **not** an ancestor of HEAD (`merge-
base` exit 1)
**Step 6.2 — Backport complications**
Record: **Clean apply** — `git show 3b347d011773d -p | git apply
--check` succeeded with no conflicts.
**Step 6.3 — Related fixes already present?**
Record: Superuser filter fix (`6b9d26089f56f`) is present but does not
address `pid=0` bypass. This specific information-leak fix is absent.
---
## Phase 7: Subsystem Context
**Step 7.1 — Subsystem**
Record: `drivers/gpu/drm/amd/amdkfd` — AMD KFD (ROCm/HSA GPU compute).
Criticality: **IMPORTANT** for AMD GPU compute users; config-dependent
(`CONFIG_HSA_AMD`).
**Step 7.2 — Activity**
Record: Actively maintained — multiple SMI event commits in 2024-2026 in
this file.
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
Record: Multi-user systems with AMD GPUs and KFD/ROCm enabled; any user
in the render group with `/dev/kfd` access.
**Step 8.2 — Trigger conditions**
Record: Another user's KFD process starts/ends or triggers a VM fault
while a malicious/co-resident user has an SMI event fd subscribed.
Common on shared GPU servers, HPC clusters, and multi-tenant
workstations.
**Step 8.3 — Failure mode severity**
Record: **Cross-process information disclosure** — other processes' PIDs
and command names exposed. Severity: **HIGH** (security/privacy; not
crash/corruption, but violates process isolation). Unprivileged render-
group users can trigger it.
**Step 8.4 — Risk vs benefit**
Record:
- **Benefit:** HIGH — closes a real cross-process monitoring hole on
shared GPU systems
- **Risk:** VERY LOW — 8-line change, uses existing fields and filtering
logic, maintainer-acked
- **Ratio:** Strongly favors backport
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence summary**
**FOR:**
- Real security/privacy bug (cross-process PID/comm leak)
- Small, surgical, maintainer-acked fix
- Applies cleanly to 6.18.44
- Buggy code confirmed present in this tree
- Unprivileged users in render group can exploit
- Aligns with stable policy for security fixes
**AGAINST:**
- Affects only AMD KFD users (not universal)
- No external bug report or syzbot confirmation
- Container PID correctness is a separate follow-up on master (not a
reason to reject this fix)
**UNRESOLVED:**
- Full lore thread discussion (Anubis blocked fetch)
- No explicit stable-list nomination found
**Step 9.2 — Stable rules checklist**
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — logic clear; Acked-by
maintainer |
| 2. Fixes real bug affecting users? | **PASS** — cross-process info
leak on shared GPUs |
| 3. Important issue? | **PASS** — security information disclosure
(HIGH) |
| 4. Small and contained? | **PASS** — 8 lines, 1 file |
| 5. No new features/APIs? | **PASS** — corrects existing event delivery
only |
| 6. Can apply to this tree? | **PASS** — clean apply verified |
**Step 9.3 — Exception categories**
Record: None (not a quirk/DT/build/doc fix) — qualifies on security bug-
fix merits.
**Step 9.4 — Decision rationale**
This commit fixes a genuine cross-process information leak in AMD KFD
SMI events. The buggy code is present in Linux 6.18.44, the fix is
minimal and obviously correct, and it restores the intended per-process
isolation that `kfd_smi_ev_enabled()` was designed to provide. Shared-
GPU and multi-user ROCm deployments on stable kernels should receive
this security fix.
---
## Verification
- [Phase 1] Parsed commit message and tags from user query and `git show
3b347d011773d`
- [Phase 2] Read current `kfd_smi_events.c` lines 163-366; confirmed
diff changes only VMFAULT and PROCESS paths
- [Phase 3] `git blame` on filter and event functions; identified
introducing commits `4172b556fd5bd`, `b8f67b9ddf4f8`, `6b9d26089f56f`,
`163a5a58437062`
- [Phase 3] `git merge-base --is-ancestor`: PROCESS events and superuser
fix present; info-leak fix absent
- [Phase 3] `git show 3b347d011773d -p | git apply --check`: clean apply
- [Phase 4] `b4 dig -c 3b347d011773d`: found lore URL; v1 only
- [Phase 4] `b4 dig -w`: amd-gfx list CC'd
- [Phase 4] `b4 dig -a`: single v1 revision
- [Phase 4] WebFetch lore URL: blocked by Anubis (no thread content)
- [Phase 5] `grep` callers of `kfd_smi_event_update_vmfault` and
`kfd_smi_event_process`
- [Phase 5] Read `kfd_smi_event_open()`: `client->pid = current->tgid`,
`client->suser = capable(CAP_SYS_ADMIN)`
- [Phase 5] Verified `task_info->tgid` populated in `amdgpu_vm.c:2543`
- [Phase 6] `git describe HEAD`: v6.18.44
- [Phase 6] Confirmed buggy `kfd_smi_event_add(0, ...)` at lines 257 and
359 in current tree
- [Phase 6] `git log stable/linux-6.18.y..master -- kfd_smi_events.c`:
fix on master, not in stable
- [Phase 8] Assessed severity as cross-process information disclosure
via render-group `/dev/kfd` access
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
index d2bc169e84b0b..fe4b936923854 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
@@ -254,8 +254,10 @@ void kfd_smi_event_update_vmfault(struct kfd_node *dev, uint16_t pasid)
if (task_info) {
/* Report VM faults from user applications, not retry from kernel */
if (task_info->task.pid)
- kfd_smi_event_add(0, dev, KFD_SMI_EVENT_VMFAULT, KFD_EVENT_FMT_VMFAULT(
- task_info->task.pid, task_info->task.comm));
+ kfd_smi_event_add(task_info->tgid, dev,
+ KFD_SMI_EVENT_VMFAULT,
+ KFD_EVENT_FMT_VMFAULT(task_info->task.pid,
+ task_info->task.comm));
amdgpu_vm_put_task_info(task_info);
}
}
@@ -356,7 +358,7 @@ void kfd_smi_event_process(struct kfd_process_device *pdd, bool start)
task_info = amdgpu_vm_get_task_info_vm(avm);
if (task_info) {
- kfd_smi_event_add(0, pdd->dev,
+ kfd_smi_event_add(task_info->tgid, pdd->dev,
start ? KFD_SMI_EVENT_PROCESS_START :
KFD_SMI_EVENT_PROCESS_END,
KFD_EVENT_FMT_PROCESS(task_info->task.pid,
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: add first record offset check
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (30 preceding siblings ...)
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdkfd: fix SMI event cross-process information leak Sasha Levin
@ 2026-08-31 13:29 ` Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.6] drm/amd/display: Fix DPMS using partially updated pipe context Sasha Levin
` (5 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:29 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 4073cdf6713b7c170e35bf055354580cc52085d6 ]
check the upper and lower limits of first record offset
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:
# Stable Backport Analysis: `drm/amdgpu: add first record offset check`
**Local tree:** `v6.18.44` (`stable/linux-6.18.y`, `VERSION = 6`,
`PATCHLEVEL = 18`, `SUBLEVEL = 44`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amdgpu]` `[add]` — validate `first_rec_offset` bounds
in RAS EEPROM header parsing during init.
### Step 1.2: Tags
**Record:**
- `Signed-off-by: Gangliang Xie <ganglxie@amd.com>` — author
- `Reviewed-by: Tao Zhou <tao.zhou1@amd.com>` — AMD reviewer
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` — amdgpu
maintainer
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable`, or `Tested-by:`
tags
- Notable: maintainer sign-off and internal AMD review, but no external
bug report
### Step 1.3: Body analysis
**Record:**
- **Bug described:** `first_rec_offset` from the RAS EEPROM header is
not bounds-checked.
- **Symptom/failure mode:** Not spelled out in the message; code
analysis shows invalid `first_rec_offset` yields an invalid `ras_fri`
(first record index), breaking circular-buffer read logic.
- **Version info:** None in message.
- **Root cause (from code):** `RAS_OFFSET_TO_INDEX()` does unsigned
arithmetic; a `first_rec_offset` below `ras_record_offset` wraps to a
huge index, and values above the record region produce `ras_fri >=
ras_max_record_count`.
### Step 1.4: Hidden bug fix detection
**Record:** Yes — despite the neutral “add check” wording, this is a
defensive bug fix completing RAS header validation started by
`5df0d6addb7e9` (“Add basic validation for RAS header”). Invalid
`ras_fri` can cause out-of-bounds EEPROM reads and bad arithmetic in
`amdgpu_ras_eeprom_read()`.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c` (+8 lines)
- **Function:** `amdgpu_ras_eeprom_init()`
- **Scope:** Single-file, surgical validation on an error path
### Step 2.2: Code flow change
**Record:**
- **Before:** After validating `ras_num_recs`, code unconditionally sets
`control->ras_fri = RAS_OFFSET_TO_INDEX(control,
hdr->first_rec_offset)` and returns success.
- **After:** Rejects headers where `first_rec_offset <
ras_record_offset` or `ras_fri >= ras_max_record_count`, logging an
error and returning `-EINVAL`.
- **Path affected:** GPU probe / RAS EEPROM init (error-handling path
for corrupt EEPROM data).
### Step 2.3: Bug mechanism
**Record:** **Memory safety / logic correctness fix**
- `RAS_OFFSET_TO_INDEX` is `((offset - ras_record_offset) / 24)` using
unsigned math.
- Corrupt `first_rec_offset` below `ras_record_offset` (e.g. `0` when
minimum is `20`) wraps to a huge `ras_fri`.
- `ras_fri` drives circular-buffer indexing in
`amdgpu_ras_eeprom_read()`; with invalid `ras_fri`, `g0`/`g1`
arithmetic can produce read counts far larger than the allocated
buffer (e.g. buffer sized for `ras_num_recs` but
`__amdgpu_ras_eeprom_read()` asked to read underflow-derived huge
counts).
- No validation existed for this field; only `ras_num_recs` was checked
(since `5df0d6addb7e9`).
### Step 2.4: Fix quality
**Record:**
- **Quality:** Obviously correct — mirrors existing header validation
style.
- **Minimal:** 8 lines, no API changes.
- **Regression risk:** Very low; only rejects already-invalid headers.
On failure, `amdgpu_ras_init_badpage_info()` already sets
`is_eeprom_valid = false` and skips EEPROM loading.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:**
- `ras_fri` assignment and `ras_num_recs` check introduced together in
`5df0d6addb7e9` (Lijo Lazar, 2025-03-26) — “Add basic validation for
RAS header”.
- That commit validated record count but not `first_rec_offset`.
- Bug present since `5df0d6addb7e9` in this tree; `ras_fri` usage is
much older.
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag. Natural follow-up to `5df0d6addb7e9`,
which is already in this tree.
### Step 3.3: Related file history
**Record:**
- `5df0d6addb7e9` — basic RAS header validation (in tree)
- `660261df61fb7` — checksum validation on unload (in tree)
- `89232d0db3ca9` — return on checksum error (in tree)
- `4073cdf6713b7` — this fix (on `master`, **not** in `6.18.y`)
- `c83e4a45ff9a0` — `tbl_size` validation (on `master`, not in tree;
separate issue)
- Standalone one-commit fix, not part of a multi-patch series.
### Step 3.4: Author context
**Record:** Gangliang Xie is an active amdgpu contributor (RAS EEPROM
work: checksum checks, bad-page loading, threshold handling). Alex
Deucher is amdgpu maintainer.
### Step 3.5: Dependencies
**Record:**
- Depends on `amdgpu_ras_eeprom_init()` and fields from `5df0d6addb7e9`
— all present in `6.18.y`.
- `git apply --check` on `4073cdf6713b7` succeeds cleanly against
current tree.
- Applies standalone.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:** `b4 dig -c 4073cdf6713b7` returned no match. Lore search
blocked (Anubis bot protection). Commit is on `master` as
`4073cdf6713b7` (committed 2026-05-19).
### Step 4.2: Reviewers
**Record:** `b4 dig -w` also failed. From commit metadata: Reviewed-by
Tao Zhou (AMD), Signed-off-by Alex Deucher (maintainer).
### Step 4.3: Bug reports
**Record:** No `Reported-by:` or `Link:` tags. No syzbot/fuzzer report.
Bug inferred from code path and prior validation commit rationale
(“corrupted EEPROM header”).
### Step 4.4: Related patches
**Record:** Related mainline follow-up `c83e4a45ff9a0` (tbl_size guard)
is separate; not required for this patch.
### Step 4.5: Stable list discussion
**Record:** Could not search lore stable list (bot protection). No
evidence found that this was explicitly rejected for stable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `amdgpu_ras_eeprom_init()` (modified); downstream consumers
of `ras_fri`: `amdgpu_ras_eeprom_read()`, `__amdgpu_ras_eeprom_read()`,
EEPROM write paths.
### Step 5.2: Callers
**Record:**
- `amdgpu_ras_eeprom_init()` ← `amdgpu_ras_init_badpage_info()` ←
`amdgpu_ras_recovery_init()` / `amdgpu_xgmi.c`
- Called during GPU probe/RAS init on AMD hardware with RAS EEPROM
support (not VF, not SR-IOV guest).
### Step 5.3: Callees
**Record:** `amdgpu_eeprom_read()`, `__decode_table_header_from_buf()`,
`RAS_OFFSET_TO_INDEX` macro.
### Step 5.4: Reachability
**Record:**
- Triggered at boot/probe when reading physical GPU EEPROM over I2C.
- Not directly userspace-triggerable, but affects every boot on affected
AMD GPUs with corrupted EEPROM.
- Corruption can arise from hardware wear, firmware bugs, or prior bad
writes.
### Step 5.5: Similar patterns
**Record:** Same validation pattern as `ras_num_recs >
ras_max_record_count` check added in `5df0d6addb7e9`. Part of a series
of RAS EEPROM hardening commits already present in `6.18.y`.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE
### Step 6.1: Buggy code in tree?
**Record:** **Yes.** At line 1441 in `amdgpu_ras_eeprom.c`, `ras_fri` is
set without bounds checking. Fix commit `4073cdf6713b7` is not an
ancestor of HEAD (`git merge-base --is-ancestor` exit 1). Gap introduced
when `5df0d6addb7e9` landed in this tree (2025-03).
### Step 6.2: Backport complications
**Record:** Clean apply confirmed (`git apply --check` passes). No
conflicts expected.
### Step 6.3: Related fixes already present?
**Record:** Prior validation (`5df0d6addb7e9`, `660261df61fb7`,
`89232d0db3ca9`) is in tree, but not this `first_rec_offset` check. No
duplicate fix found (`git log --grep="first record offset" HEAD` empty).
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/gpu/drm/amd/amdgpu` — **IMPORTANT** (AMD GPU
driver, RAS reliability/memory-error tracking). Not core-kernel-wide,
but affects production AMD GPU deployments (datacenter, workstation).
### Step 7.2: Subsystem activity
**Record:** Actively maintained; multiple RAS EEPROM validation commits
in 2025–2026 in this file.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** AMD GPUs with RAS EEPROM support and corrupted/invalid
`first_rec_offset` in EEPROM header. Config/driver-specific, not
universal.
### Step 8.2: Trigger conditions
**Record:** Corrupt EEPROM header on boot/RAS init. Uncommon but
realistic (EEPROM corruption is exactly why `5df0d6addb7e9` was added).
Not userspace-exploitable in the usual sense.
### Step 8.3: Failure mode severity
**Record:** Invalid `ras_fri` breaks circular-buffer arithmetic in
`amdgpu_ras_eeprom_read()`:
- Unsigned underflow when `ras_fri > ras_max_record_count` → `g0 =
ras_max_record_count - ras_fri` wraps to a huge value
- `__amdgpu_ras_eeprom_read()` may attempt reads far exceeding the
`kcalloc(num, ...)` buffer
- **Severity: HIGH** — potential buffer overrun, I2C read errors, driver
malfunction; graceful `-EINVAL` path exists with the fix
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH for affected hardware — prevents invalid EEPROM
parsing and dangerous downstream reads
- **Risk:** VERY LOW — 8-line bounds check, same style as existing
validation
- **Ratio:** Strongly favors backport
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Fixes real gap in RAS EEPROM header validation left by `5df0d6addb7e9`
- Invalid `ras_fri` can cause dangerous read arithmetic / buffer sizing
mismatch
- Small, surgical, maintainer-reviewed
- Applies cleanly to `6.18.y`
- Prerequisites already in tree
- Consistent with other RAS EEPROM hardening already backported to this
tree
**AGAINST backport:**
- Commit message lacks explicit crash/reproducer description
- Requires corrupted EEPROM (hardware-specific edge case)
- No syzbot or user bug report
**Unresolved:** Lore discussion and stable-list nomination could not be
verified (b4/lore unavailable).
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — straightforward bounds
check; AMD-reviewed, maintainer-acked (no runtime test cited).
2. Fixes a real bug? **PASS** — unvalidated `first_rec_offset` yields
invalid `ras_fri`.
3. Important issue? **PASS** — HIGH severity: potential buffer overrun /
driver malfunction on corrupt EEPROM.
4. Small and contained? **PASS** — 8 lines, one function.
5. No new features/APIs? **PASS** — validation only.
6. Can apply to local tree? **PASS** — clean apply, prerequisites
present.
### Step 9.3: Exception categories
**Record:** None (not device ID, quirk, DT, build, or docs). Standard
bug fix.
### Step 9.4: Decision rationale
This completes RAS EEPROM header validation already started in this
`6.18.y` tree. Without it, a corrupt `first_rec_offset` can slip past
existing checks and produce an invalid `ras_fri`, leading to broken
circular-buffer read logic and potential memory safety issues during
bad-page loading. The fix is minimal, obviously correct, low-risk, and
directly addresses a real failure mode on AMD RAS-capable hardware.
---
## Verification
- **[Phase 1]** Parsed commit message and tags from user-provided diff
and `git show 4073cdf6713b7`
- **[Phase 2]** Read `amdgpu_ras_eeprom_init()` at lines 1373–1444;
analyzed `RAS_OFFSET_TO_INDEX` macro (lines 135–136) and
`amdgpu_ras_eeprom_read()` (lines 962–1028)
- **[Phase 2]** Traced buffer overflow scenario: invalid `ras_fri` → bad
`g0`/`g1` in `amdgpu_ras_eeprom_read()`
- **[Phase 3]** `git blame -L 1434,1444`: `5df0d6addb7e9` introduced
unchecked `ras_fri` assignment
- **[Phase 3]** `git show 5df0d6addb7e9`: prior validation commit
rationale (corrupt EEPROM → huge allocation)
- **[Phase 3]** `git merge-base --is-ancestor 4073cdf6713b7 HEAD` → exit
1 (fix not in tree)
- **[Phase 3]** `git merge-base --is-ancestor 5df0d6addb7e9 HEAD` → in
tree; `660261df61fb7` → in tree
- **[Phase 3]** `git apply --check` on `4073cdf6713b7` → applies cleanly
- **[Phase 4]** `b4 dig -c 4073cdf6713b7` → no result (exit 1)
- **[Phase 4]** Lore.kernel.org fetch → blocked by Anubis
- **[Phase 5]** `grep amdgpu_ras_eeprom_init`: callers in
`amdgpu_ras.c:3590`, `amdgpu_xgmi.c:1674`
- **[Phase 5]** `amdgpu_ras_init_badpage_info()` sets `is_eeprom_valid =
!ret` on init failure (line 3591)
- **[Phase 6]** `git describe HEAD` → `v6.18.44`; tree is
`stable/linux-6.18.y`
- **[Phase 6]** Buggy code confirmed at line 1441 without bounds check
- **[Phase 6]** `git log --grep="first record offset" HEAD` → empty (fix
absent)
- **[Phase 8]** Constants verified: `RAS_TABLE_HEADER_SIZE=20`,
`RAS_RECORD_START=20`, `RAS_TABLE_RECORD_SIZE=24`,
`RAS_MAX_RECORD_COUNT≈10922`
---
**YES**The background check on `stable/linux-6.18.y` confirmed:
- **Related validation is present:** `5df0d6addb7e9` ("Add basic
validation for RAS header") is in the tree.
- **This fix is not:** no commit matching "first record offset" was
found on the stable branch.
That matches the earlier analysis: the gap remains in `6.18.y`, the
patch applies cleanly, and the backport recommendation stands at
**YES**.
drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index dafa46a9656ca..652aa085b6263 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -1439,6 +1439,14 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
}
control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset);
+ if (hdr->first_rec_offset < control->ras_record_offset ||
+ control->ras_fri >= control->ras_max_record_count) {
+ dev_err(adev->dev,
+ "RAS header invalid, ras_fri: %u, first_rec_offset:0x%x",
+ control->ras_fri, hdr->first_rec_offset);
+ return -EINVAL;
+ }
+
control->ras_num_mca_recs = 0;
control->ras_num_pa_recs = 0;
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.6] drm/amd/display: Fix DPMS using partially updated pipe context
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (31 preceding siblings ...)
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu: add first record offset check Sasha Levin
@ 2026-08-31 13:29 ` Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Find link encoder for flexible DIG mapping cases Sasha Levin
` (4 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:29 UTC (permalink / raw)
To: patches, stable
Cc: Dominik Kaszewski, Wenjing Liu, Chenyu Chen, Alex Deucher,
Sasha Levin, harry.wentland, sunpeng.li, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Dominik Kaszewski <dominik.kaszewski@amd.com>
[ Upstream commit 6fd45b5d8955bbc362ac3dfe181529f7b1cfd224 ]
[Why & How]
DPMS functions should not use partially updated pipe context passed
as argument of commit_planes_do_stream_update, and instead use the
one in current_state, which is guaranteed to be the most recently
programmed HW config.
Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Dominik Kaszewski <dominik.kaszewski@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@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:
# Stable Backport Analysis: `drm/amd/display: Fix DPMS using partially
updated pipe context`
**Local tree:** `v6.18.43` (Makefile: 6.18.43, `DC_VER` "3.2.351")
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject Line
**Record:** `[drm/amd/display]` `[Fix]` — DPMS operations must not use a
partially updated `pipe_ctx` from the in-flight commit `context`; they
should use the pipe context from `current_state` (last programmed HW
config).
### Step 1.2: Tags
**Record:**
| Tag | Value |
|-----|-------|
| Reviewed-by | Wenjing Liu \<wenjing.liu@amd.com\> |
| Signed-off-by | Dominik Kaszewski, Chenyu Chen, Alex Deucher |
| Fixes: | **Not present** (expected for candidate review) |
| Reported-by: | **Not present** |
| Cc: stable | **Not present** (not a negative signal) |
| Link: | **Not present** |
Notable: AMD display reviewer sign-off; no syzbot/user bug report.
### Step 1.3: Body Analysis
**Record:**
- **Bug:** `commit_planes_do_stream_update()` receives `context`
(new/partial state). DPMS handlers were passed `pipe_ctx` from that
partial state instead of the HW-backed state.
- **Symptom:** DPMS off/on and related link blanking can target wrong or
unprogrammed hardware resources during commits that also update stream
state.
- **Root cause:** DPMS manipulates live hardware (blank stream, disable
audio, link training) but was using a pipe context that may not yet
reflect programmed HW — the same class of problem the adjacent test-
pattern comment already documents.
- **Version info:** Patch submitted April 15, 2026 as part of "DC
Patches Apr 20 2026" (patch 17/19).
### Step 1.4: Hidden Bug Fix?
**Record:** No — explicitly labeled a fix. Correctness bug in display
power-management path, not cosmetic cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/display/dc/core/dc.c` (+14 / −7)
- **Function:** `commit_planes_do_stream_update()`
- **Scope:** Single-file, surgical fix in one function
### Step 2.2: Code Flow Change
**Record:**
| Hunk | Before | After |
|------|--------|-------|
| DPMS off | `set_dpms_off(pipe_ctx)` from `context` |
`set_dpms_off(dpms_pipe_ctx)` from `dc->current_state` |
| Audio disable | `az_disable` via `context` pipe_ctx | via
`current_state` pipe_ctx (with local `audio` pointer) |
| DPMS on | `set_dpms_on(dc->current_state, pipe_ctx)` |
`set_dpms_on(dc->current_state, dpms_pipe_ctx)` |
| OCS workaround | `set_dpms_on` + link checks on `context` pipe_ctx |
same operations on `current_state` pipe_ctx |
**Execution path:** Stream update commits where
`stream_update->dpms_off` is set, or the `blank_stream_on_ocs_change` DP
workaround fires — during `commit_planes_for_stream()` before front-end
programming completes.
### Step 2.3: Bug Mechanism
**Record:** **Logic / correctness fix** — wrong data source for hardware
operations.
`link_set_dpms_off()` and `link_set_dpms_on()` dereference
`pipe_ctx->stream_res` (stream encoders, timing generator),
`pipe_ctx->link_res`, and `pipe_ctx->link_config` to blank streams,
disable audio, and manage DP links. When `context` is only partially
built, those fields may not match what's actually programmed. The test-
pattern block immediately above already states front-end changes are not
yet applied at this stage.
### Step 2.4: Fix Quality
**Record:**
- **Obviously correct:** Yes — `set_dpms_on()` already takes
`dc->current_state`; only the `pipe_ctx` argument was wrong. Fix
aligns DPMS with that intent.
- **Minimal:** Yes — one new pointer, no API changes.
- **Regression risk:** Very low — uses the same pipe index `j` already
being iterated; reviewed by AMD display engineer.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** Buggy DPMS lines (3693–3714) blame to `5d324e5159d9e`
(shallow tree limits deeper history). Function and buggy pattern are
present in this checkout.
### Step 3.2: Fixes: Tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related File History
**Record:** Repo is shallow (~11,547 commits). `dc.c` shows only two
recent commits in this clone. Patch is **17/19** in "DC Patches Apr 20
2026" but this specific change only touches the DPMS block in `dc.c` and
does not depend on other series entries (dcn42 clock gating, power
module, etc.).
### Step 3.4: Author Context
**Record:** Dominik Kaszewski (AMD display). Reviewed by Wenjing Liu
(AMD). Signed off by Alex Deucher (AMD DRM maintainer). Author has other
DC display work in the broader ecosystem.
### Step 3.5: Dependencies
**Record:** **Standalone.** No prerequisite commits required; only
changes which `pipe_ctx` pointer DPMS uses. Applies cleanly against
current `dc.c` at lines 3693–3714.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original Discussion
**Record:** Found at https://lists.freedesktop.org/archives/amd-
gfx/2026-April/142846.html (patch 17/19). No replies on that page; no
explicit stable nomination found.
### Step 4.2: Reviewers
**Record:** Cover letter CC'd AMD display maintainers (Harry Wentland,
Leo Li, Aurabindo Pillai, Roman Li, etc.). Patch has `Reviewed-by:
Wenjing Liu`.
### Step 4.3: Bug Reports
**Record:** No external bug report, syzbot, or KASAN report. Internal
AMD correctness fix.
### Step 4.4: Series Context
**Record:** Part of 19-patch DC drop (Apr 2026). This patch is
independent — other series items (power module, dcn42 changes, double-
free fix) are separate. Patch 5 ("Align HWSS fast commit path with
legacy path") may increase exposure but is not a prerequisite for this
fix's correctness.
### Step 4.5: Stable List
**Record:** lore.kernel.org stable search blocked (bot protection). No
stable discussion found via cover letter or patch page.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key Functions
**Record:** `commit_planes_do_stream_update()` — modified. Calls
`link_set_dpms_off()` / `link_set_dpms_on()` via `dc->link_srv`.
### Step 5.2: Callers
**Record:** `commit_planes_do_stream_update()` called from
`commit_planes_for_stream()` (line 4201), which is invoked from
`update_planes_and_stream_v2()` / v3 commit paths — the standard display
commit pipeline used by `dc_commit_updates_for_stream()`.
### Step 5.3: Callees
**Record:** `set_dpms_off` → `link_set_dpms_off()` (blanks stream,
disables audio, DP link teardown). `set_dpms_on` → `link_set_dpms_on()`
(link enable, infoframes, stream attribute setup). Both require valid
`stream_res` and `link_res` from programmed HW.
### Step 5.4: Reachability
**Record:**
- `link_set_all_streams_dpms_off_for_link()` →
`dc_commit_updates_for_stream()` with `stream_update.dpms_off` (link
hotplug/detection paths)
- DPMS during atomic commits when stream updates include power-state
changes
- `blank_stream_on_ocs_change` workaround for DP output color-space
changes
**Userspace reachable:** Yes — display blank/unblank, suspend/resume,
hotplug, and mode commits on AMDGPU systems with `CONFIG_DRM_AMD_DC`.
### Step 5.5: Similar Patterns
**Record:** Test-pattern handling in the same function (lines 3670–3690)
explicitly documents that only `current_state` can be used for HW
operations at this commit stage. DPMS was inconsistent with that
established pattern.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE (v6.18.43)
### Step 6.1: Buggy Code Present?
**Record:** **YES.** Lines 3693–3714 in
`drivers/gpu/drm/amd/display/dc/core/dc.c` use `pipe_ctx` from `context`
for all DPMS operations. The fix is **not** yet applied in this tree.
### Step 6.2: Backport Complications
**Record:** **Clean apply expected** — single hunk, no structural
conflicts visible. Line numbers differ slightly from lore patch (3898 vs
3693) but code matches.
### Step 6.3: Related Fixes Already Present?
**Record:** No equivalent fix found via grep or log search in this tree.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem & Criticality
**Record:** `drivers/gpu/drm/amd/display` — **IMPORTANT** (AMD GPU
display stack; affects all AMDGPU users with DC enabled, not core
kernel).
### Step 7.2: Activity
**Record:** Actively maintained; recent commit in tree is DMUB aux
validation fix (`1ecde19bfce65`).
---
## PHASE 8: IMPACT AND RISK
### Step 8.1: Who Is Affected
**Record:** AMDGPU users with `CONFIG_DRM_AMD_DC` — laptops/desktops
with AMD GPUs using the modern display core (DCN2+).
### Step 8.2: Trigger Conditions
**Record:** Any commit that includes a `stream_update` with `dpms_off`
(or OCS color-space workaround) while `context` has partially updated
pipe state. Common during screen blank/unblank, link power events, and
combined stream updates.
### Step 8.3: Failure Mode Severity
**Record:**
- Display fails to blank or wake correctly
- Wrong encoder/link programmed → black screen, flicker
- Audio endpoint disable on wrong resource
- Potential NULL/invalid `stream_res` dereference if partial context
lacks populated resources
**Severity: HIGH** (user-visible display failures; possible oops on bad
pointers — not confirmed by report but plausible from code inspection of
`link_set_dpms_off()`).
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH — fixes real DPMS correctness on a widely used
driver path
- **Risk:** VERY LOW — 7-line logical change, AMD-reviewed, mirrors
existing in-function pattern
- **Ratio:** Strongly favors backport
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence Summary
**FOR backport:**
- Real correctness bug in DPMS HW programming path
- User-visible impact (screen power, suspend/resume, hotplug)
- Small, surgical, AMD-reviewed fix
- Buggy code confirmed present in v6.18.43
- Standalone — no series dependencies
- Consistent with documented constraint in adjacent test-pattern code
**AGAINST backport:**
- No user/syzbot report (internal discovery)
- Part of larger DC patchset (but this hunk is independent)
- AMDGPU-specific, not universal kernel path
**Unresolved:** Exact kernel version that introduced the buggy DPMS-
in-`commit_planes_do_stream_update` pattern (shallow history). Does not
affect the decision for this tree where the bug exists.
### Step 9.2: Stable Rules Checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — logic is clear;
Reviewed-by from AMD display |
| 2. Fixes a real user-affecting bug? | **PASS** — DPMS uses wrong pipe
context during commits |
| 3. Important issue? | **PASS** — display blank/wake failures, possible
crash |
| 4. Small and contained? | **PASS** — 1 file, ~14 lines |
| 5. No new features/APIs? | **PASS** |
| 6. Applies to local tree? | **PASS** — buggy code present, clean apply
expected |
### Step 9.3: Exception Categories
**Record:** None (not a device ID, quirk, DT, build, or docs fix) —
standard bug fix.
### Step 9.4: Decision Rationale
For **v6.18.43**, the buggy DPMS path exists and the fix is a minimal,
obviously correct correction that ensures display power-management
operations use the hardware-backed `current_state` pipe context rather
than a partially built commit context. This prevents incorrect blanking,
wake failures, and potential resource dereference on a common AMDGPU
commit path. The fix is self-contained and low-risk.
---
## Verification
- **[Phase 1]** Parsed commit message and tags from user-provided diff
and lore page
- **[Phase 2]** Read diff hunks; verified `link_set_dpms_off/on` use
`pipe_ctx->stream_res` and `link_res` in `link_dpms.c`
- **[Phase 3]** `git describe HEAD` → v6.18.43; `git blame -L 3690,3715`
→ buggy lines present; shallow repo confirmed
- **[Phase 3]** `git log -S "set_dpms_off(pipe_ctx)" -- dc.c` → only
merge commit (limited by shallow history)
- **[Phase 4]** WebFetch lore patch 17/19 at
https://lists.freedesktop.org/archives/amd-gfx/2026-April/142846.html
- **[Phase 4]** WebFetch cover letter 00/19 — series context, no stable
nomination
- **[Phase 4]** lore.kernel.org stable search — blocked by bot
protection (UNVERIFIED for stable-list discussion)
- **[Phase 5]** `grep commit_planes_do_stream_update` — one call site at
line 4201 in `commit_planes_for_stream()`
- **[Phase 5]** Traced `dc_commit_updates_for_stream()` →
`update_planes_and_stream_v2/v3` → `commit_planes_for_stream()`
- **[Phase 5]** Read `link_set_all_streams_dpms_off_for_link()` — calls
`dc_commit_updates_for_stream` with `dpms_off`
- **[Phase 6]** Read `dc.c` lines 3587–3735 — confirmed buggy code
without fix
- **[Phase 6]** `DC_VER` in `dc.h` → "3.2.351"; fix not present
- **[Phase 7]** Subsystem path confirmed: `drivers/gpu/drm/amd/display`
- **[Phase 8]** Analyzed `link_set_dpms_off()` at line 2346 — uses
stream_enc, blank_stream, audio disable on pipe_ctx resources
**YES**
drivers/gpu/drm/amd/display/dc/core/dc.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 927837249479f..627a9fb4c551e 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3690,27 +3690,34 @@ static void commit_planes_do_stream_update(struct dc *dc,
resource_build_test_pattern_params(&context->res_ctx, pipe_ctx);
}
+ // DPMS should not use partially updated pipe context
+ struct pipe_ctx *dpms_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j];
+
if (stream_update->dpms_off) {
if (*stream_update->dpms_off) {
- dc->link_srv->set_dpms_off(pipe_ctx);
+ dc->link_srv->set_dpms_off(dpms_pipe_ctx);
/* for dpms, keep acquired resources*/
- if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
- pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+ if (dpms_pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) {
+ struct audio *audio = dpms_pipe_ctx->stream_res.audio;
+
+ audio->funcs->az_disable(audio);
+ }
dc->optimized_required = true;
} else {
if (get_seamless_boot_stream_count(context) == 0)
dc->hwss.prepare_bandwidth(dc, dc->current_state);
- dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
+ dc->link_srv->set_dpms_on(dc->current_state, dpms_pipe_ctx);
}
- } else if (pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && stream_update->output_color_space
- && !stream->dpms_off && dc_is_dp_signal(pipe_ctx->stream->signal)) {
+ } else if (dpms_pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change &&
+ stream_update->output_color_space &&
+ !stream->dpms_off && dc_is_dp_signal(dpms_pipe_ctx->stream->signal)) {
/*
* Workaround for firmware issue in some receivers where they don't pick up
* correct output color space unless DP link is disabled/re-enabled
*/
- dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
+ dc->link_srv->set_dpms_on(dc->current_state, dpms_pipe_ctx);
}
if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Find link encoder for flexible DIG mapping cases
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (32 preceding siblings ...)
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.6] drm/amd/display: Fix DPMS using partially updated pipe context Sasha Levin
@ 2026-08-31 13:29 ` Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu/pm: fix SmartShift bias sysfs store PM refcount on parse error Sasha Levin
` (3 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:29 UTC (permalink / raw)
To: patches, stable
Cc: Ovidiu Bunea, Wenjing Liu, James Lin, Alex Deucher, Sasha Levin,
harry.wentland, sunpeng.li, christian.koenig, airlied, simona,
amd-gfx, dri-devel, linux-kernel
From: Ovidiu Bunea <ovidiu.bunea@amd.com>
[ Upstream commit 74ef54e656e7006cfc215e960b0cf2720a7a3d48 ]
[why & how]
link->link_enc can only be used to identify the link's link encoder
when the link is not permitted to use flexible link encoder
assignments.
Use the correct function for identifying link encoder and add
function pointer guards before calling them.
Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Ovidiu Bunea <ovidiu.bunea@amd.com>
Signed-off-by: James Lin <pinglei.lin@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:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
Record: `[drm/amd/display]` `[Find]` — Correct link-encoder lookup in
`power_down_encoders()` for flexible DIG mapping.
**Step 1.2 — Tags**
Record:
- Reviewed-by: Wenjing Liu \<wenjing.liu@amd.com\>
- Signed-off-by: Ovidiu Bunea, James Lin, Alex Deucher
- No Fixes:, Reported-by:, Tested-by:, Link:, or Cc: stable tags
**Step 1.3 — Body**
Record:
- Bug: `link->link_enc` is only valid when the link does not use
flexible link-encoder assignment.
- Symptom: Wrong encoder used (or dereferenced) during encoder power-
down.
- Root cause: `power_down_encoders()` used `link->link_enc` instead of
the dynamic lookup API.
- Fix: Use `link_enc_cfg_get_link_enc(link)` and guard function pointers
before calling them.
**Step 1.4 — Hidden bug fix?**
Record: Yes. Although the subject does not say "fix", the body and diff
clearly address incorrect encoder identification and missing NULL guards
— a real correctness/crash bug, not cleanup.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
Record:
- File: `drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c` (+7
/ -5)
- Function: `power_down_encoders()`
- Scope: Single-file, surgical fix
**Step 2.2 — Code flow**
Record:
- Hunk 1: `link->link_enc` → `link_enc_cfg_get_link_enc(link)` — uses
dynamically assigned encoder for flexible-mapping links.
- Hunk 2: `disable_output` only called when `link_enc` is non-NULL.
- Hunk 3: FEC disable wrapped in checks for `link_enc`,
`fec_set_enable`, and `fec_set_ready`.
**Step 2.3 — Bug mechanism**
Record:
- Category: Logic/correctness + NULL pointer dereference.
- For `is_dig_mapping_flexible` links (USB4/DPIA), `link->link_enc` is
not the assigned encoder; DPIA link construction even has `/* TODO:
Create link encoder */` and never sets `link->link_enc`.
- FEC disable added by commit `5f0c5775d4eeb` calls
`link_enc->funcs->...` without NULL checks on a potentially NULL/wrong
encoder.
**Step 2.4 — Fix quality**
Record: Obviously correct; matches the pattern already used at line 1163
in the same file and throughout the DC subsystem. Minimal regression
risk — for non-flexible links, `link_enc_cfg_get_link_enc()` returns
`link->link_enc`.
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
Record: Lines 1734–1748 introduced/modified by `5f0c5775d4eeb` ("Disable
FEC when powering down encoders", Jan 2026). Earlier
`power_down_encoders()` structure dates to `19eef1d98eeda`. The FEC
addition created the vulnerable path in this tree.
**Step 3.2 — Fixes: tag**
Record: N/A — no Fixes: tag present.
**Step 3.3 — Related file history**
Record: FEC commit `5f0c5775d4eeb` (upstream `8cee62904caf9`) is in this
6.18.y tree and is the direct prerequisite/introducer of the buggy code.
`link_enc_cfg_get_link_enc()` and `is_dig_mapping_flexible`
infrastructure are present.
**Step 3.4 — Author context**
Record: Ovidiu Bunea also authored the FEC power-down commit. Alex
Deucher is AMD DRM maintainer. Patch is standalone within a 17-patch AMD
DC batch series.
**Step 3.5 — Dependencies**
Record: No code dependencies on other patches in the series. Uses
existing `link_enc_cfg_get_link_enc()` from `link_enc_cfg.h`, which is
already included in `dce110_hwseq.c`. Standalone backport.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
Record: [PATCH 12/17] on amd-gfx, Apr 29 2026 —
https://lists.freedesktop.org/archives/amd-gfx/2026-April/143792.html.
Part of "DC Patches May 4 2026" series
(https://lists.freedesktop.org/archives/amd-gfx/2026-April/143780.html).
No replies or stable nominations found in the thread.
**Step 4.2 — Reviewers**
Record: Reviewed-by Wenjing Liu (AMD display). Signed-off-by Alex
Deucher (maintainer). `b4 dig -c 8cee62904caf9` found no lore match for
the related FEC commit.
**Step 4.3 — Bug report**
Record: No external bug report. Related FEC commit describes "no light
up" when FEC disable targets the wrong DIG encoder — same underlying
class of failure.
**Step 4.4 — Series context**
Record: Patch 12/17 in a 17-patch AMD internal batch (121 files total).
This patch alone touches one function in one file and is independent of
the larger series changes.
**Step 4.5 — Stable list**
Record: lore.kernel.org/stable search blocked by bot protection; no
stable discussion found.
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
Record: `power_down_encoders()`, `link_enc_cfg_get_link_enc()`,
`dce110_power_down()`.
**Step 5.2 — Callers**
Record: `power_down_encoders()` ← `power_down_all_hw_blocks()` ← display
mode-commit path (~line 2013) and `dce110_power_down()` (~line 2678).
`dce110_power_down` is the `.power_down` hook for all DCN generations
(dcn10 through dcn401).
**Step 5.3 — Callees**
Record: `link_enc_cfg_get_link_enc()`, `blank_dp_stream()`,
`disable_output()`, `fec_set_enable()`, `fec_set_ready()`.
**Step 5.4 — Reachability**
Record: Triggered on display mode changes, suspend/resume, and DC power-
down — common user-visible paths. Affects systems with USB4/DPIA or
other flexible DIG-mapping links.
**Step 5.5 — Similar patterns**
Record: Same file line 1163, `link_dp_phy.c` lines 149–187, and many
other DC paths already use `link_enc_cfg_get_link_enc()` with NULL
guards. `power_down_encoders()` was an outlier.
---
## Phase 6: Cross-Reference Against Local Tree (6.18.43)
**Step 6.1 — Buggy code present?**
Record: Yes. Current tree at lines 1734–1748 still uses `link->link_enc`
without NULL guards. `is_dig_mapping_flexible`,
`link_enc_cfg_get_link_enc()`, and FEC power-down code are all present.
**Step 6.2 — Backport difficulty**
Record: Clean apply expected. `link_enc_cfg.h` already included; no
structural conflicts.
**Step 6.3 — Related fixes already present?**
Record: FEC power-down commit `5f0c5775d4eeb` is present; this follow-up
fix is not.
---
## Phase 7: Subsystem Context
**Step 7.1 — Subsystem/criticality**
Record: `drivers/gpu/drm/amd/display` — IMPORTANT (AMD GPU display
driver, affects display output on affected hardware).
**Step 7.2 — Activity**
Record: Actively maintained; recent FEC power-down commit in this tree.
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
Record: AMD GPU users with flexible DIG link-encoder mapping (USB4/DPIA
links confirmed; `is_dig_mapping_flexible` set in `construct_dpia()`).
All DCN-based AMD GPUs use `dce110_power_down`.
**Step 8.2 — Trigger conditions**
Record: Display power-down during mode changes, suspend/resume, or DC
teardown when FEC was enabled or a flexible-mapping link needs encoder
operations. Moderately common on affected hardware.
**Step 8.3 — Failure mode**
Record:
- Wrong encoder → FEC not disabled on correct DIG → display fails to
light up (documented in related FEC commit).
- NULL `link_enc` on DPIA links → kernel oops from
`link_enc->funcs->...`.
- Severity: HIGH (display failure or crash).
**Step 8.4 — Risk/benefit**
Record: Benefit HIGH for affected hardware. Risk LOW — 12-line change,
follows established API, backward-compatible for fixed-mapping links.
---
## Phase 9: Final Synthesis
**Evidence FOR backport:**
- Fixes real display bug and potential NULL dereference
- Small, surgical, obviously correct
- Prerequisites (`link_enc_cfg_get_link_enc`, FEC power-down) exist in
6.18.y
- Reviewed by AMD display engineer; signed off by maintainer
- Follow-up to an already-backported FEC fix (`5f0c5775d4eeb`)
- Matches established patterns throughout the same subsystem
**Evidence AGAINST:**
- Only affects flexible DIG-mapping hardware (primarily USB4/DPIA), not
all AMD users
- Part of a large AMD batch series (but this patch is self-contained)
**Stable rules checklist:**
1. Obviously correct and tested? **PASS** (code review by AMD; pattern
used elsewhere; no runtime test tag)
2. Fixes a real bug? **PASS**
3. Important issue? **PASS** (display failure / possible oops)
4. Small and contained? **PASS** (one function, one file)
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS**
**Exception category:** Not applicable (hardware quirk/workaround
category does not apply; this is a driver logic fix).
---
## Problem Summary
Commit `5f0c5775d4eeb` added FEC disable logic to
`power_down_encoders()` using `link->link_enc` directly. For links with
flexible DIG encoder assignment, that field is not the currently
assigned encoder — and for USB4/DPIA links it is never created at all
(`construct_dpia()` has a "TODO: Create link encoder" comment). The
result is either operating on the wrong hardware block (display does not
light up) or dereferencing NULL (kernel oops). This commit corrects the
lookup and adds the guards that other DC code paths already use.
For the 6.18.y tree specifically: the buggy code and all prerequisites
are present, the FEC fix is already backported, and this small follow-up
completes that fix for flexible-mapping cases.
---
## Verification
- [Phase 1] Parsed commit message and tags from user-provided diff and
lore page
- [Phase 2] Read current `power_down_encoders()` at lines 1728–1753 in
`dce110_hwseq.c`
- [Phase 3] `git blame -L 1734,1748`: FEC commit `5f0c5775d4eeb`
introduced vulnerable lines
- [Phase 3] `git show 5f0c5775d4eeb` and `git show 8cee62904caf9`: FEC
commit present in tree
- [Phase 3] `git log --oneline -5 -- dce110_hwseq.c`: confirmed FEC
commit is most recent change to this function
- [Phase 4] Fetched amd-gfx lore pages for patch 12/17 and series cover
letter
- [Phase 4] `b4 dig -c 8cee62904caf9`: no lore match (tool limitation,
not analysis blocker)
- [Phase 5] `grep
power_down_encoders/power_down_all_hw_blocks/dce110_power_down`:
traced call chain
- [Phase 5] `grep link_enc_cfg_get_link_enc`: confirmed widespread use
of correct API in subsystem
- [Phase 5] Read `construct_dpia()` in `link_factory.c` lines 760–827:
DPIA links set `is_dig_mapping_flexible = true`, no `link_enc` created
- [Phase 5] Read `link_enc_cfg_get_link_enc()` in `dc_link_enc_cfg.c`
lines 550–568: flexible vs fixed logic verified
- [Phase 5] Read `dp_set_fec_enable()` in `link_dp_phy.c` lines 180–188:
NULL guard pattern confirmed
- [Phase 6] `git describe HEAD`: v6.18.43-1-gc7f0dac02d232 (6.18.y
stable tree)
- [Phase 6] Confirmed fix not yet applied (line 1734 still uses
`link->link_enc`)
- [Phase 6] Confirmed `link_enc_cfg.h` included at line 49 of
`dce110_hwseq.c`
- [Phase 6] `grep .power_down = dce110_power_down`: all DCN init files
use this path
- [Phase 8] Read FEC commit message: "no light up" failure mode
documented for wrong DIG encoder
**YES****Verdict: YES** — this commit should be backported to the 6.18.y
tree.
It fixes a real bug in `power_down_encoders()` where `link->link_enc` is
used directly instead of `link_enc_cfg_get_link_enc()`. On flexible DIG-
mapping links (notably USB4/DPIA), that can mean the wrong encoder is
targeted or a NULL pointer is dereferenced during power-down — causing
display failures or a kernel oops. The fix is small, self-contained, and
the prerequisite FEC power-down commit (`5f0c5775d4eeb`) is already in
this tree.
.../drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index 8f86177de48dc..0841b1d0b7775 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -1731,20 +1731,22 @@ static void power_down_encoders(struct dc *dc)
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
- struct link_encoder *link_enc = link->link_enc;
+ struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link);
enum signal_type signal = link->connector_signal;
dc->link_srv->blank_dp_stream(link, false);
if (signal != SIGNAL_TYPE_EDP)
signal = SIGNAL_TYPE_NONE;
- if (link->ep_type == DISPLAY_ENDPOINT_PHY)
+ if (link->ep_type == DISPLAY_ENDPOINT_PHY && link_enc)
link_enc->funcs->disable_output(link_enc, signal);
if (link->fec_state == dc_link_fec_enabled) {
- link_enc->funcs->fec_set_enable(link_enc, false);
- link_enc->funcs->fec_set_ready(link_enc, false);
- link->fec_state = dc_link_fec_not_ready;
+ if (link_enc && link_enc->funcs->fec_set_enable && link_enc->funcs->fec_set_ready) {
+ link_enc->funcs->fec_set_enable(link_enc, false);
+ link_enc->funcs->fec_set_ready(link_enc, false);
+ link->fec_state = dc_link_fec_not_ready;
+ }
}
link->link_status.link_active = false;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu/pm: fix SmartShift bias sysfs store PM refcount on parse error
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (33 preceding siblings ...)
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Find link encoder for flexible DIG mapping cases Sasha Levin
@ 2026-08-31 13:29 ` Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu: Bound GPIO I2C table entry count from VBIOS Sasha Levin
` (2 subsequent siblings)
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:29 UTC (permalink / raw)
To: patches, stable
Cc: Candice Li, Hawking Zhang, Alex Deucher, Sasha Levin,
kenneth.feng, christian.koenig, airlied, simona, amd-gfx,
dri-devel, linux-kernel
From: Candice Li <candice.li@amd.com>
[ Upstream commit a4b0c3f5d2287997876d8f711a40d3c0418458d8 ]
Return the parse error before acquiring PM access.
Signed-off-by: Candice Li <candice.li@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:
# Stable Backport Analysis: drm/amdgpu/pm: fix SmartShift bias sysfs
store PM refcount on parse error
**Local tree:** `stable/linux-6.18.y` at **v6.18.44** (`make
kernelversion` = 6.18.44)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject Line
**Record:** `[drm/amdgpu/pm]` `[fix]` — Corrects SmartShift bias sysfs
store handler so PM runtime refcount is not touched on `kstrtoint()`
parse failure.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Candice Li \<candice.li@amd.com\> (author)
- **Reviewed-by:** Hawking Zhang \<Hawking.Zhang@amd.com\> (AMD
reviewer)
- **Signed-off-by:** Alex Deucher \<alexander.deucher@amd.com\>
(drm/amdgpu maintainer)
- No Fixes:, Reported-by:, Tested-by:, Link:, or Cc: stable tags
- Notable: maintainer-reviewed AMD driver fix; no syzbot/fuzzer report
### Step 1.3: Body Analysis
**Record:**
- **Bug:** On invalid sysfs input, `amdgpu_set_smartshift_bias()` calls
`amdgpu_pm_put_access()` without a matching `amdgpu_pm_get_access()`.
- **Symptom:** Runtime PM usage-count underflow; kernel emits `Runtime
PM usage count underflow!` via `dev_warn()`.
- **Root cause (author):** Parse error should be returned before
acquiring PM access.
- **Version info:** None in message; bug introduced in this tree by
commit `55aa33c3fe3876` (Feb 2025 refactor).
### Step 1.4: Hidden Bug Fix?
**Record:** No — this is an explicit refcount/PM pairing bug fix, not
disguised cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Change Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/pm/amdgpu_pm.c` (+3 / −5)
- **Function:** `amdgpu_set_smartshift_bias()` only
- **Scope:** Single-file, surgical fix in one sysfs store handler
### Step 2.2: Code Flow Change
**Before (buggy code in v6.18.44):**
```1865:1886:drivers/gpu/drm/amd/pm/amdgpu_pm.c
r = kstrtoint(buf, 10, &bias);
if (r)
goto out;
r = amdgpu_pm_get_access(adev);
if (r < 0)
return r;
// ... clamp bias, set amdgpu_smartshift_bias ...
out:
amdgpu_pm_put_access(adev);
return r;
```
**After (fixed):**
- Parse error → `return r` immediately (no PM access)
- Success path → `get_access` → work → `put_access` → `return count`
**Record:**
- **Hunk 1:** `kstrtoint` failure: `goto out` + spurious `put_access` →
early `return r`
- **Hunk 2:** Success path: remove `out:` label; always `return count`
after balanced get/put
- **Affected path:** Sysfs store error path on invalid input; normal
path unchanged
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Reference counting / resource management bug
- **Mechanism:** Commit `55aa33c3fe3876` moved `kstrtoint()` before
`amdgpu_pm_get_access()` but kept the `out:` label that
unconditionally calls `amdgpu_pm_put_access()`. On parse failure,
`pm_runtime_put_autosuspend()` runs without a prior
`pm_runtime_resume_and_get()`, triggering `rpm_drop_usage_count()`
underflow handling:
```1079:1095:drivers/base/power/runtime.c
static int rpm_drop_usage_count(struct device *dev)
{
int ret;
ret = atomic_sub_return(1, &dev->power.usage_count);
if (ret >= 0)
return ret;
// ...
atomic_inc(&dev->power.usage_count);
dev_warn(dev, "Runtime PM usage count underflow!\n");
return -EINVAL;
}
```
### Step 2.4: Fix Quality
**Record:**
- Obviously correct: matches the pattern used by other sysfs stores in
the same file (e.g. `amdgpu_set_pp_force_performance_level()` at lines
388–408)
- Minimal, no unrelated changes
- Regression risk: very low; only reorders error handling on the parse-
failure path
- No API or behavior change on the success path
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:**
- `amdgpu_set_smartshift_bias()` introduced in `30d95a37f46d1`
(2021-05-30, v5.13 era)
- Original code called `pm_runtime_get_sync()` **before** `kstrtoint()`,
so `goto out` + `put` was correct
- Bug introduced in `55aa33c3fe3876` (2025-02-04, Lijo Lazar) — "Add
APIs for device access checks"
- Blame confirms lines 1865–1867 (`kstrtoint` + `goto out`) from
original commit; lines 1869–1871, 1884 (`get_access`/`put_access`)
from refactor commit
### Step 3.2: Fixes: Tag
**Record:** N/A — no Fixes: tag present.
### Step 3.3: Related File History
**Record:**
- `55aa33c3fe3876` — large PM access API refactor (616-line change in
this file)
- `494c1432542b3` — earlier SmartShift consistency work
- Fix is standalone; not part of a required multi-commit dependency for
this function
- Patch submitted as **[PATCH 2/8]** in a series, but this hunk is self-
contained
### Step 3.4: Author Context
**Record:**
- Candice Li: AMD engineer, regular amdgpu contributor
- Lijo Lazar: authored the refactor that introduced the bug
- Alex Deucher (maintainer) signed off on the fix
### Step 3.5: Dependencies
**Record:** No prerequisites. Fix applies cleanly to current v6.18.44
code; `amdgpu_pm_get_access()`/`amdgpu_pm_put_access()` already exist in
this tree.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original Discussion
**Record:**
- `b4 dig -c a4b0c3f5d2287`: **no match** (patch on freedesktop.org amd-
gfx, not lore.kernel.org)
- Fetched: https://lists.freedesktop.org/archives/amd-
gfx/2026-May/145516.html
- Part of 8-patch series by Candice Li (2026-05-28)
- No explicit stable nomination found in thread
- No NAKs observed in fetched content
### Step 4.2: Reviewers
**Record:** CC'd Hawking Zhang, Tao Zhou, Stanley Yang, Thomas Chai;
Reviewed-by Hawking Zhang; Signed-off-by Alex Deucher
### Step 4.3: Bug Report
**Record:** No external bug report, syzbot link, or user Reported-by.
Bug identified by code inspection during related PM cleanup work.
### Step 4.4: Series Context
**Record:** Patch 2/8 in series covering OD index validation, this
refcount fix, RAS EEPROM validation, etc. This fix is independent of
patches 1 and 3–8.
### Step 4.5: Stable List History
**Record:** lore.kernel.org/stable search blocked (bot protection). No
stable-list discussion found via other sources.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key Functions
**Record:** `amdgpu_set_smartshift_bias()`, `amdgpu_pm_get_access()`,
`amdgpu_pm_put_access()`
### Step 5.2: Callers
**Record:** `amdgpu_set_smartshift_bias` is registered as the `.store`
callback for `smartshift_bias` via
`AMDGPU_DEVICE_ATTR_RW(smartshift_bias, ...)` at line 2544. Invoked when
root (or privileged user) writes to
`/sys/class/drm/card*/device/smartshift_bias`.
### Step 5.3: Callees
**Record:**
- `kstrtoint()` — input parsing
- `amdgpu_pm_get_access()` → `amdgpu_pm_dev_state_check()` +
`pm_runtime_resume_and_get()`
- `amdgpu_pm_put_access()` → `pm_runtime_mark_last_busy()` +
`pm_runtime_put_autosuspend()`
### Step 5.4: Reachability
**Record:**
- Reachable from userspace via sysfs write (requires root/privileged
access)
- Only exposed on SmartShift-capable hardware (`ss_bias_attr_update()`
gates visibility)
- Trigger: writing non-integer value, e.g. `echo abc >
.../smartshift_bias`
### Step 5.5: Similar Patterns
**Record:** `amdgpu_set_smartshift_bias` is the **only** sysfs store in
this file that parses input (`kstrtoint`) before `get_access` while
retaining a `goto out` that unconditionally calls `put_access`. Other
`goto out` usages (gpu metrics, temp metrics, fan control) all occur
**after** successful `get_access`.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE
### Step 6.1: Buggy Code Present?
**Record:** **YES.** Buggy code confirmed at lines 1865–1886 in
v6.18.44. Introduced by `55aa33c3fe3876`, present since v6.18-rc1.
### Step 6.2: Backport Complications
**Record:** Clean apply expected. Current tree matches the diff base
exactly. No conflicting changes in this function since the refactor.
### Step 6.3: Fix Already Present?
**Record:** **NO.** Fix commit `a4b0c3f5d2287` exists in the repo object
database but is **not** an ancestor of HEAD (v6.18.44).
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem Criticality
**Record:** `drivers/gpu/drm/amd/pm` — **IMPORTANT** (AMD GPU power
management; affects laptop SmartShift systems)
### Step 7.2: Subsystem Activity
**Record:** Actively maintained; recent stable commits in this file
include torn gpu metrics reads, scpm read-only attrs, sysfs cleanup
fixes.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who Is Affected
**Record:** AMD SmartShift 2.0 laptop users (APU + dGPU power sharing)
who write to `smartshift_bias` sysfs. Narrow hardware scope, but real
production systems.
### Step 8.2: Trigger Conditions
**Record:**
- Invalid integer written to `smartshift_bias` sysfs
- Requires root/privileged sysfs write access
- Unlikely in normal use; plausible via scripting error or manual
experimentation
- Not security-relevant (privileged access required)
### Step 8.3: Failure Mode Severity
**Record:**
- **Failure:** Runtime PM usage-count underflow warning;
`pm_runtime_mark_last_busy()` called spuriously
- **Severity:** **MEDIUM** — no crash, panic, or data corruption; kernel
catches underflow and restores counter, but PM accounting is briefly
wrong and a `dev_warn` is emitted. Repeated triggers could affect
suspend/resume behavior.
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** MEDIUM — fixes real refcount bug on an error path in
production driver code present since 6.18.0
- **Risk:** VERY LOW — 3-line logic change, maintainer-reviewed, matches
established patterns in the same file
- **Ratio:** Benefit outweighs risk
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence Summary
**FOR backport:**
- Real refcount bug introduced by `55aa33c3fe3876` refactor, present in
v6.18.44
- Obviously correct, minimal fix (3 insertions, 5 deletions)
- Maintainer-reviewed and signed off by Alex Deucher
- Matches error-handling pattern used elsewhere in `amdgpu_pm.c`
- Reference counting bugs in PM paths are standard stable material
**AGAINST backport:**
- Only triggered by invalid sysfs input (root-only)
- Limited to SmartShift-capable AMD hardware
- Failure mode is WARN + counter correction, not crash/corruption
- No user reports or fuzzer findings
**Unresolved:** No stable-list nomination found; no user-reported
instances.
### Step 9.2: Stable Rules Checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — logic is clear;
Reviewed-by from AMD; no Tested-by |
| 2. Fixes a real bug affecting users? | **PASS** — refcount imbalance
on parse-error path |
| 3. Important issue? | **PASS** (borderline) — runtime PM underflow;
MEDIUM severity |
| 4. Small and contained? | **PASS** — 8 lines net, one function |
| 5. No new features/APIs? | **PASS** |
| 6. Can apply to local tree? | **PASS** — buggy code present; clean
apply |
### Step 9.3: Exception Categories
**Record:** None applicable (not device ID, quirk, DT, build, or docs
fix).
### Step 9.4: Decision Rationale
This is a clear bug introduced in v6.18 by the PM access API refactor
(`55aa33c3fe3876`). The original SmartShift bias handler correctly
acquired runtime PM before parsing; the refactor inverted that order but
left the unconditional `out:` cleanup, breaking get/put pairing. The fix
restores correct refcount semantics with zero functional change on the
success path.
While the trigger is narrow (invalid sysfs write on SmartShift hardware)
and the failure mode is a caught underflow warning rather than a crash,
reference-count bugs in GPU runtime PM are appropriate for stable
backport: the fix is trivial, obviously correct, maintainer-approved,
and the buggy code is present throughout the 6.18.y series.
---
## Verification
- [Phase 1] Parsed commit message and tags from user-provided diff and
mailing list
- [Phase 2] Read current `amdgpu_set_smartshift_bias()` at lines
1856–1887 in v6.18.44; confirmed buggy get/put pairing
- [Phase 2] Read `rpm_drop_usage_count()` at lines 1079–1095; confirmed
underflow warning behavior
- [Phase 3] `git blame -L 1856,1887`: bug introduced by
`55aa33c3fe3876`, original function by `30d95a37f46d1`
- [Phase 3] `git show 55aa33c3fe3876`: confirmed refactor moved
`kstrtoint` before `get_access` while keeping `goto out`
- [Phase 3] `git show 30d95a37f46d1`: original code had
`pm_runtime_get_sync` before `kstrtoint` (correct pairing)
- [Phase 3] `git merge-base --is-ancestor 55aa33c3fe3876 HEAD`: buggy
commit IS in v6.18.44
- [Phase 3] `git tag --contains 55aa33c3fe3876`: present since v6.18-rc1
- [Phase 4] `b4 dig -c a4b0c3f5d2287`: no lore match (patch on
freedesktop.org)
- [Phase 4] Fetched https://lists.freedesktop.org/archives/amd-
gfx/2026-May/145516.html: confirmed patch content and series context
- [Phase 5] Grep for `goto out` in `amdgpu_pm.c`: only smartshift_bias
has parse-before-get with unconditional put at `out`
- [Phase 5] Confirmed `AMDGPU_DEVICE_ATTR_RW(smartshift_bias)`
registration at line 2544
- [Phase 6] `git describe HEAD` = v6.18.44; `make kernelversion` =
6.18.44
- [Phase 6] `git merge-base --is-ancestor a4b0c3f5d2287 HEAD`: fix NOT
in current tree
- [Phase 6] Compared current code to provided diff: exact match, clean
apply expected
- [Phase 8] Confirmed failure mode via `rpm_drop_usage_count` underflow
path
- [UNVERIFIED] No runtime test of actual sysfs write triggering the
warning
**YES**The background searches finished and match the earlier analysis:
- The fix exists in the repo as `a4b0c3f5d2287` / `b9dcdc6fd5e2d`, but
it is **not** in the current `stable/linux-6.18.y` checkout at
v6.18.44.
- The buggy code from `55aa33c3fe3876` **is** present in this tree.
Verdict remains **YES** for backporting to this 6.18.y tree.
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 94c534c1d0bed..d253b974223c6 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -1859,12 +1859,12 @@ static ssize_t amdgpu_set_smartshift_bias(struct device *dev,
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
- int r = 0;
+ int r;
int bias = 0;
r = kstrtoint(buf, 10, &bias);
if (r)
- goto out;
+ return r;
r = amdgpu_pm_get_access(adev);
if (r < 0)
@@ -1876,14 +1876,12 @@ static ssize_t amdgpu_set_smartshift_bias(struct device *dev,
bias = AMDGPU_SMARTSHIFT_MIN_BIAS;
amdgpu_smartshift_bias = bias;
- r = count;
/* TODO: update bias level with SMU message */
-out:
amdgpu_pm_put_access(adev);
- return r;
+ return count;
}
static int ss_power_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr,
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: Bound GPIO I2C table entry count from VBIOS
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (34 preceding siblings ...)
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu/pm: fix SmartShift bias sysfs store PM refcount on parse error Sasha Levin
@ 2026-08-31 13:29 ` Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18] drm/amdgpu: use atomic operation to achieve lockless serialization Sasha Levin
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds on allocate_doorbell Sasha Levin
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:29 UTC (permalink / raw)
To: patches, stable
Cc: Candice Li, Tao Zhou, Alex Deucher, Sasha Levin, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Candice Li <candice.li@amd.com>
[ Upstream commit a99cd231cd924b7160fecb9fb3a94b801522323b ]
Reject undersized tables and cap the derived entry count
to AMDGPU_MAX_I2C_BUS so we do not overrun adev->i2c_bus[]
or walk an absurd number of entries on corrupt size fields.
Signed-off-by: Candice Li <candice.li@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:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
Record: `[drm/amdgpu]` `[Bound]` — Bound/cap GPIO I2C table entry count
parsed from VBIOS atom data tables.
**Step 1.2 — Tags**
Record:
- `Signed-off-by: Candice Li <candice.li@amd.com>` (author)
- `Reviewed-by: Tao Zhou <tao.zhou1@amd.com>`
- `Signed-off-by: Alex Deucher <alexander.deucher@amd.com>` (amdgpu
maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`, or
`Tested-by:` tags
- Notable: maintainer sign-off and AMD review, but no fuzzer/user report
**Step 1.3 — Body analysis**
Record:
- **Bug:** VBIOS-reported GPIO I2C table `size` is trusted without
validation; entry count is derived unchecked.
- **Symptoms:** Can overrun `adev->i2c_bus[]` (fixed size 16) and walk
an excessive number of entries on corrupt/undersized size fields.
- **Root cause:** `num_indices = (size - header) / entry_size` with no
lower/upper bound; `amdgpu_atom_parse_data_header()` only reads a
16-bit size from the BIOS image and does not validate it.
- **Version info:** None in the message.
**Step 1.4 — Hidden bug fix?**
Record: **Yes.** Despite no “fix” in the subject, this is a defensive
bounds-check fix for out-of-bounds array indexing and unbounded
iteration on corrupt VBIOS metadata.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
Record:
- **File:** `drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c` (+18 / -6)
- **Functions modified:** new helper
`amdgpu_atombios_gpio_i2c_num_entries()`; callers
`amdgpu_atombios_lookup_i2c_gpio()`, `amdgpu_atombios_i2c_init()`,
`amdgpu_atombios_oem_i2c_init()`
- **Scope:** Single-file, surgical fix
**Step 2.2 — Code flow per hunk**
Record:
- **New helper:** If `size < sizeof(ATOM_COMMON_TABLE_HEADER)` → return
0; else compute `bytes / sizeof(ATOM_GPIO_I2C_ASSIGMENT)` capped at
`AMDGPU_MAX_I2C_BUS` (16).
- **Before:** Three sites computed `num_indices` directly from unchecked
`size`.
- **After:** All three use the bounded helper.
- **Paths affected:**
- `amdgpu_atombios_i2c_init()` — probe-time I2C bus creation; indexes
`adev->i2c_bus[i]`
- `amdgpu_atombios_oem_i2c_init()` — Polaris OEM I2C path; same
indexing
- `amdgpu_atombios_lookup_i2c_gpio()` — encoder/router DDC lookup;
walks GPIO entries by pointer
**Step 2.3 — Bug mechanism**
Record: **Buffer overflow / out-of-bounds access + unbounded loop**
1. **Undersized `size` (< 4 bytes):** `(uint16_t)size - sizeof(header)`
underflows in unsigned arithmetic → enormous `num_indices` (e.g.
65534/entry_size ≈ thousands).
2. **Oversized/corrupt `size`:** `num_indices` can exceed
`AMDGPU_MAX_I2C_BUS` (16). In `amdgpu_atombios_i2c_init()` /
`oem_i2c_init()`, loop index `i` is used as `adev->i2c_bus[i]` →
**write past end of 16-element pointer array**.
3. **GPIO pointer walk:** Uncapped iteration reads past the actual VBIOS
table region.
**Step 2.4 — Fix quality**
Record:
- Fix is minimal, obviously correct, and matches driver limits
(`AMDGPU_MAX_I2C_BUS == 16`, `ATOM_MAX_SUPPORTED_DEVICE == 16`).
- Does not validate `size` against total BIOS image length (unlike the
related `drm/amd/display` fix), but still eliminates the array overrun
and caps iteration.
- **Regression risk:** Very low. Legitimate tables with ≤16 entries
behave identically; undersized tables fail closed (0 entries) instead
of crashing.
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
Record: Buggy `num_indices` calculation introduced in `d38ceaf99ed01`
(“drm/amdgpu: add core driver (v4)”, Alex Deucher, 2015-04-20). Present
throughout the life of amdgpu in this tree.
**Step 3.2 — Fixes: tag**
Record: N/A — no `Fixes:` tag in commit message.
**Step 3.3 — Related file history**
Record:
- `20f48be63d1ad` added `amdgpu_atombios_oem_i2c_init()` with the same
unchecked pattern.
- No prior bounds-check fix for GPIO I2C tables in this tree.
- Fix commit `a99cd231cd92` is **not** present locally
(`amdgpu_atombios_gpio_i2c_num_entries` not found).
**Step 3.4 — Author context**
Record: Candice Li has other amdgpu commits in this tree (RAS, SMU,
etc.). Patch reviewed by Tao Zhou and signed off by Alex Deucher.
**Step 3.5 — Dependencies**
Record: Mailing-list submission is **[PATCH 3/4]** in a hardening
series, but this patch is **standalone**:
- Patch 1/4: RAS CPER buffer bounds (different files)
- Patch 2/4: ATOM command table nesting depth (different code)
- Patch 4/4: PSP fw_pri_buf validation (different code)
No prerequisite commits needed for this hunk to apply and function.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
Record:
- `b4 dig -c a99cd231cd924b7160fecb9fb3a94b801522323b` → no lore match
(thread on freedesktop.org, not lore).
- Verified at https://lists.freedesktop.org/archives/amd-
gfx/2026-May/144648.html
- Series: [PATCH 3/4], May 18 2026
- No stable nomination found in the thread
- No NAKs observed in fetched content
**Step 4.2 — Reviewers**
Record: CC list includes Hawking Zhang, Tao Zhou, Stanley Yang, Thomas
Chai. `Reviewed-by: Tao Zhou`. `Signed-off-by: Alex Deucher`.
**Step 4.3 — Bug reports**
Record: None. No syzbot, bugzilla, or user crash reports referenced.
**Step 4.4 — Related patches**
Record: Related hardening in same series (RAS, ATOM nesting, PSP).
Separate mainline commit `86d2b20644b` (“drm/amd/display: Validate GPIO
pin LUT table size before iterating”) addresses the same class of VBIOS
table parsing bug in the display BIOS parser and was nominated with `Cc:
stable@vger.kernel.org`.
**Step 4.5 — Stable list**
Record: No stable-list discussion found for this specific patch (lore
blocked by bot protection; freedesktop thread has no stable CC).
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
Record: `amdgpu_atombios_gpio_i2c_num_entries()`,
`amdgpu_atombios_lookup_i2c_gpio()`, `amdgpu_atombios_i2c_init()`,
`amdgpu_atombios_oem_i2c_init()`.
**Step 5.2 — Callers**
Record:
- `amdgpu_atombios_i2c_init()` ← `amdgpu_i2c_init()` in `amdgpu_i2c.c`
- `amdgpu_atombios_oem_i2c_init()` ← `amdgpu_i2c_init()` (Polaris chips
with DC)
- `amdgpu_i2c_init()` ← `amdgpu_device.c` during device init when
`adev->bios` present and `!adev->is_atom_fw`
- `amdgpu_atombios_lookup_i2c_gpio()` ← `amdgpu_atombios.c`
encoder/router parsing (DDC/I2C routing during display setup)
**Step 5.3 — Callees**
Record: `amdgpu_atom_parse_data_header()`,
`amdgpu_atombios_get_bus_rec_for_i2c_gpio()`, `amdgpu_i2c_create()`,
`min_t()`.
**Step 5.4 — Reachability**
Record:
- **Probe path:** `amdgpu_i2c_init()` runs during GPU driver
initialization for legacy atombios (non-atom-fw) GPUs — common on pre-
GCN/older hardware and Polaris OEM path.
- **Display path:** `amdgpu_atombios_lookup_i2c_gpio()` runs during
encoder/connector parsing — broader reach on atom-bios GPUs.
- **Userspace trigger:** Not a direct syscall path; triggered by GPU
probe with VBIOS present. Corrupt/malicious VBIOS (flash corruption or
reflashing) can trigger it at module load / GPU init. Unprivileged
users cannot typically rewrite GPU VBIOS without root/hardware access.
**Step 5.5 — Similar patterns**
Record: Same unchecked `(size - header) / struct_size` pattern exists
elsewhere in `amdgpu_atombios.c` (e.g. spread-spectrum tables at lines
929+), but this commit does not touch those — scoped to GPIO I2C only. A
related display-side GPIO LUT bounds fix exists upstream.
---
## Phase 6: Cross-Reference Against Local Tree (v6.18.44)
**Step 6.1 — Buggy code present?**
Record: **Yes.** Local tree is `v6.18.44` (Makefile: 6.18.44). All three
unchecked `num_indices` calculations exist at lines 99–100, 130–131, and
161–162 of `amdgpu_atombios.c`. `adev->i2c_bus[AMDGPU_MAX_I2C_BUS]` is
defined in `amdgpu.h` with `AMDGPU_MAX_I2C_BUS = 16`. Bug dates to
original amdgpu import (2015).
**Step 6.2 — Backport complications**
Record: **Clean apply expected.** File structure and includes match the
patch context (`bif/bif_4_1_d.h` present, same three call sites). No
conflicting fix already applied.
**Step 6.3 — Related fixes already present?**
Record: **None** for GPIO I2C table bounding.
`amdgpu_atombios_gpio_i2c_num_entries` does not exist in tree.
---
## Phase 7: Subsystem and Maintainer Context
**Step 7.1 — Subsystem**
Record: `drm/amdgpu` display/GPU driver — **IMPORTANT** subsystem
(widely deployed AMD GPU driver).
**Step 7.2 — Activity**
Record: File actively maintained; recent commits include OEM I2C
support, vbios interfaces, PM cleanups.
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
Record: AMD GPU users on the legacy atombios path (`!adev->is_atom_fw`)
during I2C init; additionally any GPU using atom-bios encoder routing
that calls `amdgpu_atombios_lookup_i2c_gpio()`. Config-specific to
`CONFIG_DRM_AMDGPU` with affected hardware.
**Step 8.2 — Trigger conditions**
Record:
- Corrupt or malicious VBIOS with invalid GPIO I2C table `size` field
- Undersized table (`size < 4`) or oversized entry count (`> 16`)
- **Likelihood:** Low for legitimate factory VBIOS; non-zero for flash
corruption, bad flashing, or adversarial VBIOS
- **Unprivileged direct trigger:** Unlikely without ability to modify
GPU VBIOS
**Step 8.3 — Failure mode severity**
Record:
- `amdgpu_atombios_i2c_init()` / `oem_i2c_init()`: **out-of-bounds
write** to `adev->i2c_bus[]` → heap corruption, kernel oops, possible
security impact — **CRITICAL/HIGH**
- All three functions: **out-of-bounds read** past VBIOS mapping, very
long loops → probe hang/oops — **HIGH**
- Undersized table: previously could loop thousands of times instead of
zero — **HIGH** (boot hang)
**Step 8.4 — Risk vs benefit**
Record:
- **Benefit:** Prevents kernel crash/corruption during GPU probe on
corrupt VBIOS; aligns with AMD’s own hardening series and similar
stable-nominated display fix.
- **Risk:** Minimal — 15-line helper, caps at existing hardware limit of
16 buses.
- **Ratio:** High benefit, very low risk.
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence compile**
**FOR backport:**
- Real OOB write to `adev->i2c_bus[i]` when `i >= 16`
- Real OOB read / unbounded loop on corrupt `size`
- Small, maintainer-reviewed, obviously correct
- Bug present since 2015 in this tree
- Same vulnerability class as a related fix already nominated for stable
(display GPIO LUT)
- Applies cleanly to v6.18.44
**AGAINST backport:**
- No user bug report or syzbot reproduction
- Requires corrupt/malicious VBIOS — uncommon trigger
- Fix does not validate `size` against total BIOS image length (partial
mitigation only)
- Part of a 4-patch hardening series (though this patch is independent)
**Unresolved:** No runtime crash report confirming field failure on
production systems.
**Step 9.2 — Stable rules checklist**
1. Obviously correct and tested? **PASS** — logic is straightforward;
reviewed by AMD engineer and maintainer. No runtime test tag.
2. Fixes a real bug? **PASS** — verified OOB array indexing and
unbounded iteration in source.
3. Important issue? **PASS** — OOB write during driver probe
(crash/corruption potential).
4. Small and contained? **PASS** — 18 lines added, one file, three call
sites.
5. No new features/APIs? **PASS** — defensive bounds only.
6. Can apply to local tree? **PASS** — buggy code confirmed present;
patch not yet applied; clean apply expected.
**Step 9.3 — Exception category**
Record: Not a device-ID/quirk/DT/build/docs exception — standard bug-
fix/hardening.
**Step 9.4 — Decision rationale**
For **this** tree (v6.18.44), the unchecked VBIOS size parsing is a
long-standing defect that can cause out-of-bounds writes to a kernel
array during GPU initialization. The fix is minimal, self-contained,
maintainer-approved, and matches established stable practice for amdgpu
VBIOS table hardening. The lack of a user report is outweighed by the
severity of the failure mode and the negligible regression risk.
---
## Verification
- [Phase 1] Parsed subject, tags, body from provided commit message
- [Phase 2] Diff analysis: verified +18/-6 in `amdgpu_atombios.c`, three
call sites, new helper function
- [Phase 2] Read current `amdgpu_atombios.c` lines 82–175: confirmed
unchecked `num_indices` pattern
- [Phase 2] Read `amdgpu.h`: `i2c_bus[AMDGPU_MAX_I2C_BUS]` with
`AMDGPU_MAX_I2C_BUS = 16`
- [Phase 2] Read `atom.c` `amdgpu_atom_parse_data_header()`: `size` from
`CU16(idx)`, no bounds validation
- [Phase 3] `git blame`: buggy lines from `d38ceaf99ed01` (2015-04-20)
- [Phase 3] `git show d38ceaf99ed01`: original amdgpu core driver import
- [Phase 3] `grep amdgpu_atombios_gpio_i2c_num_entries`: not in tree
(fix absent)
- [Phase 3] Verified patch 3/4 is standalone; patches 1–2 are unrelated
subsystems (freedesktop.org)
- [Phase 4] `b4 dig -c a99cd23...`: no lore match
- [Phase 4] WebFetch freedesktop.org amd-gfx May 2026: confirmed [PATCH
3/4] content
- [Phase 4] Web search: mainline SHA
`a99cd231cd924b7160fecb9fb3a94b801522323b`; related display fix
`86d2b20` with `Cc: stable`
- [Phase 5] `grep` callers: `amdgpu_i2c_init` → `amdgpu_device.c:4771`;
lookup used in encoder parsing
- [Phase 5] Read `amdgpu_i2c.c:218–235`: init paths for legacy and
Polaris OEM
- [Phase 5] Read `amdgpu_device.c:4753–4772`: called when `adev->bios &&
!adev->is_atom_fw`
- [Phase 6] `git describe HEAD`: `v6.18.44`; Makefile confirms 6.18.44
- [Phase 6] Buggy code confirmed at lines 99, 130, 161 in local tree
- [Phase 6] `ATOM_MAX_SUPPORTED_DEVICE` = 16 (`atombios.h`), matches
`AMDGPU_MAX_I2C_BUS`
- [Phase 7/8] Assessed subsystem criticality and failure modes from
verified call paths
- UNVERIFIED: No end-user crash report for this specific GPIO I2C issue
- UNVERIFIED: Whether undersized-table underflow has been observed in
the field
**YES**The background search finished: the **Bound GPIO I2C** fix is
**not** in this tree (`v6.18.44`). Candice Li’s other amdgpu work is
present, but `amdgpu_atombios_gpio_i2c_num_entries()` is missing and the
unchecked `num_indices` logic is still at lines 99, 130, and 161 of
`amdgpu_atombios.c`.
**Verdict from the analysis:** backport **YES** — small, standalone
bounds-check fix that prevents OOB writes to `adev->i2c_bus[]` and
unbounded VBIOS table walks on corrupt GPIO I2C table sizes during GPU
init.
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 24 +++++++++++++++-----
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 763f2b8dcf13a..b8f7e3a18d324 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -36,6 +36,21 @@
#include "atombios_encoders.h"
#include "bif/bif_4_1_d.h"
+/* VBIOS-reported table size is unchecked against the image; cap iterations and
+ * adev->i2c_bus[] indexing to AMDGPU_MAX_I2C_BUS.
+ */
+static int amdgpu_atombios_gpio_i2c_num_entries(uint16_t size)
+{
+ u32 bytes;
+
+ if (size < sizeof(ATOM_COMMON_TABLE_HEADER))
+ return 0;
+
+ bytes = size - sizeof(ATOM_COMMON_TABLE_HEADER);
+ return (int)min_t(u32, bytes / sizeof(ATOM_GPIO_I2C_ASSIGMENT),
+ AMDGPU_MAX_I2C_BUS);
+}
+
static struct amdgpu_i2c_bus_rec amdgpu_atombios_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
{
struct amdgpu_i2c_bus_rec i2c;
@@ -96,8 +111,7 @@ struct amdgpu_i2c_bus_rec amdgpu_atombios_lookup_i2c_gpio(struct amdgpu_device *
if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
- num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
- sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+ num_indices = amdgpu_atombios_gpio_i2c_num_entries(size);
gpio = &i2c_info->asGPIO_Info[0];
for (i = 0; i < num_indices; i++) {
@@ -127,8 +141,7 @@ void amdgpu_atombios_i2c_init(struct amdgpu_device *adev)
if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
- num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
- sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+ num_indices = amdgpu_atombios_gpio_i2c_num_entries(size);
gpio = &i2c_info->asGPIO_Info[0];
for (i = 0; i < num_indices; i++) {
@@ -158,8 +171,7 @@ void amdgpu_atombios_oem_i2c_init(struct amdgpu_device *adev, u8 i2c_id)
if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
- num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
- sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+ num_indices = amdgpu_atombios_gpio_i2c_num_entries(size);
gpio = &i2c_info->asGPIO_Info[0];
for (i = 0; i < num_indices; i++) {
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18] drm/amdgpu: use atomic operation to achieve lockless serialization
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (35 preceding siblings ...)
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu: Bound GPIO I2C table entry count from VBIOS Sasha Levin
@ 2026-08-31 13:30 ` Sasha Levin
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds on allocate_doorbell Sasha Levin
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:30 UTC (permalink / raw)
To: patches, stable
Cc: Sunil Khatri, Alex Deucher, Sasha Levin, christian.koenig,
airlied, simona, amd-gfx, dri-devel, linux-kernel
From: Sunil Khatri <sunil.khatri@amd.com>
[ Upstream commit 4d50a14d346141e03a7c3905e496d91e048bc30c ]
In amdgpu_seq64_alloc there is a possibility that two difference cores
from two separate NODES can try to and could get the same free slot.
So this fixes that race here using atomic test_and_set clear operations.
Signed-off-by: Sunil Khatri <sunil.khatri@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:
# Stable Backport Analysis: `drm/amdgpu: use atomic operation to achieve
lockless serialization`
**Local tree:** `v6.18.43` (`VERSION = 6`, `PATCHLEVEL = 18`, `SUBLEVEL
= 43`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[drm/amdgpu]` — action verb implied **fix** (race) — use
atomic bitops in `amdgpu_seq64_alloc`/`amdgpu_seq64_free` for lockless
serialization of the seq64 slot bitmap.
### Step 1.2: Tags
**Record:**
| Tag | Value |
|-----|-------|
| Signed-off-by | Sunil Khatri `<sunil.khatri@amd.com>` |
| Reviewed-by | Alex Deucher `<alexander.deucher@amd.com>` |
| Signed-off-by | Alex Deucher `<alexander.deucher@amd.com>` |
**Notable patterns:** Maintainer review from Alex Deucher (amdgpu co-
maintainer). No `Fixes:`, `Reported-by:`, `Cc: stable`, or syzbot tags
(expected for manual review).
### Step 1.3: Body analysis
**Record:**
- **Bug described:** In `amdgpu_seq64_alloc`, two CPU cores on separate
nodes can race and obtain the same free seq64 slot.
- **Symptom/failure mode:** Duplicate slot assignment → two user-queue
fence drivers share the same 64-bit fence memory location → broken GPU
synchronization.
- **Root cause (author):** Non-atomic `find_first_zero_bit` +
`__set_bit` is not safe under concurrent access; fix uses
`test_and_set_bit` loop and `clear_bit`.
- **Version info:** None in commit message.
### Step 1.4: Hidden bug fix?
**Record:** Yes — explicitly a race-condition fix, not cosmetic cleanup.
Replacing `__set_bit`/`__clear_bit` with atomic
`test_and_set_bit`/`clear_bit` is the standard kernel pattern for
concurrently accessed bitmaps (`Documentation/atomic_bitops.txt`).
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c` (+8 / −5, 1
file)
- **Functions modified:** `amdgpu_seq64_alloc()`, `amdgpu_seq64_free()`
- **Scope:** Single-file surgical fix
### Step 2.2: Code flow per hunk
**Hunk 1 — `amdgpu_seq64_alloc`:**
- **Before:** `find_first_zero_bit` → early `-ENOSPC` → unconditional
`__set_bit`
- **After:** Loop: `find_first_zero_bit` → `-ENOSPC` if full →
`test_and_set_bit`; break only if bit was previously clear (successful
claim); otherwise retry
- **Path affected:** Normal allocation path for seq64 fence slots
**Hunk 2 — `amdgpu_seq64_free`:**
- **Before:** `__clear_bit` (non-atomic)
- **After:** `clear_bit` (atomic)
- **Path affected:** Slot release on fence-driver teardown
### Step 2.3: Bug mechanism
**Record:** **Category:** Race condition / incorrect non-atomic bitmap
access.
**Mechanism:** `__set_bit`/`__clear_bit` are explicitly non-atomic per
`Documentation/atomic_bitops.txt`. Concurrent alloc and free on
`adev->seq64.used` without atomic ops can corrupt the bitmap or allow a
TOCTOU between `find_first_zero_bit` and bit claim when another CPU
concurrently modifies the same bitmap.
### Step 2.4: Fix quality
**Record:** Fix is obviously correct — standard `test_and_set_bit`
allocator loop. Minimal, no API changes. Low regression risk; loop may
spin under contention but pool has 262144 slots
(`AMDGPU_MAX_SEQ64_SLOTS`), so retry pressure is low.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `amdgpu_seq64_alloc`/`free` bitmap logic introduced in
commit `a112b91dd6349` (stable-tree import). Buggy
`__set_bit`/`__clear_bit` pattern present in current `v6.18.43` tree at
lines 178–182 and 208.
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag in commit message.
### Step 3.3: Related file history
**Record:** `amdgpu_seq64.c` exists in this tree with the pre-fix code.
Fix commit is **not yet applied** (no `test_and_set_bit` in local file).
This stable tree's git history is flattened through bulk imports,
limiting per-file history granularity.
### Step 3.4: Author commits
**Record:** No commits by Sunil Khatri found in this stable checkout's
`git log`. Author is an AMD developer; patch reviewed by amdgpu
maintainer Alex Deucher.
### Step 3.5: Dependencies
**Record:** Standalone — no series markers, no prerequisite commits.
Applies directly to existing `amdgpu_seq64.c`.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- **URL:** https://lists.freedesktop.org/archives/amd-
gfx/2026-May/144553.html (v1 submission, May 14 2026)
- **Series revisions:** v1 only (no v2/v3 found)
- **Reviewer feedback:** Christian König questioned why concurrent calls
are possible: *"Why can those functions be called in concurrent from
multiple threads?"* (https://lists.freedesktop.org/archives/amd-
gfx/2026-May/144650.html)
- **Maintainer response:** Alex Deucher gave `Reviewed-by`
(https://lists.freedesktop.org/archives/amd-gfx/2026-May/144599.html)
- **Stable nominations:** None found in thread
- **NAKs:** None; question raised but patch still reviewed positively by
maintainer
`b4 dig -c <hash>` could not be run — fix commit hash not present in
this checkout.
### Step 4.2: Reviewers (b4 -w equivalent via lore)
**Record:** Patch submitted to amd-gfx list; reviewed by Alex Deucher
(subsystem maintainer). Christian König (also amdgpu maintainer) raised
concurrency question.
### Step 4.3: Bug report
**Record:** No external bug report, syzbot link, or crash trace.
Theoretical/concurrency-analysis fix from driver developer.
### Step 4.4: Related patches
**Record:** Standalone 1/1 patch, not part of a series.
### Step 4.5: Stable list
**Record:** Not searched on lore.kernel.org (blocked by bot protection).
No stable discussion found on freedesktop amd-gfx thread.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `amdgpu_seq64_alloc()`, `amdgpu_seq64_free()`
### Step 5.2: Callers
**Record:**
| Function | Callers | Context |
|----------|---------|---------|
| `amdgpu_seq64_alloc` | `amdgpu_userq_fence_driver_alloc()` only |
Called from `amdgpu_userq_create()` during `AMDGPU_USERQ_OP_CREATE`
ioctl |
| `amdgpu_seq64_free` | `amdgpu_userq_fence_driver_alloc()` error path;
`amdgpu_userq_fence_driver_destroy()` via `kref_put` | Destroy path from
queue teardown / refcount drop |
`amdgpu_userq_create()` holds `adev->userq_mutex` during alloc (line
518). `amdgpu_userq_destroy()` holds only per-client
`uq_mgr->userq_mutex`, **not** `adev->userq_mutex` (lines 394–420).
Therefore alloc and free **can run concurrently** from different DRM
clients/processes.
### Step 5.3: Callees
**Record:** `find_first_zero_bit`, `test_and_set_bit`/`__set_bit`,
`clear_bit`/`__clear_bit`, `amdgpu_seq64_get_va_base()`
### Step 5.4: Reachability
**Record:** Reachable from userspace via DRM ioctl
`AMDGPU_USERQ_OP_CREATE` / destroy on GPUs with user-mode queue support
(gfx11, gfx12, SDMA v6/v7 in this tree). Multi-process GPU compute
workloads are a realistic trigger.
### Step 5.5: Similar patterns
**Record:** Kernel bitmap allocators universally use `test_and_set_bit`
loops for concurrent access. Non-atomic `__set_bit` is only valid when
caller holds exclusive access.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE
### Step 6.1: Buggy code exists?
**Record:** **Yes.** Current `v6.18.43` tree has the buggy code:
```178:182:drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c
bit_pos = find_first_zero_bit(adev->seq64.used,
adev->seq64.num_sem);
if (bit_pos >= adev->seq64.num_sem)
return -ENOSPC;
__set_bit(bit_pos, adev->seq64.used);
```
```207:208:drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c
if (bit_pos < adev->seq64.num_sem)
__clear_bit(bit_pos, adev->seq64.used);
```
`amdgpu_seq64_init()` is called during GMC hw init; user-mode queues are
wired on modern ASICs.
### Step 6.2: Backport complications
**Record:** **Clean apply expected** — identical file and function
structure; no conflicts detected. 8-line change.
### Step 6.3: Related fixes already present?
**Record:** **No** — `test_and_set_bit` not present in `amdgpu_seq64.c`;
fix not yet in tree.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/gpu/drm/amd/amdgpu` — **IMPORTANT** (AMD GPU
driver). Affects user-mode queue fence synchronization on supported
hardware.
### Step 7.2: Subsystem activity
**Record:** Actively developed; user-mode queues and seq64 are
relatively recent features present in this 6.18.y tree.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Users of AMDGPU user-mode queues on gfx11/gfx12/SDMA-capable
GPUs running multi-process compute (ROCm, etc.). Config-dependent on
hardware with `userq_funcs` populated.
### Step 8.2: Trigger conditions
**Record:** Concurrent queue create (alloc under `adev->userq_mutex`)
and queue destroy/fence-driver teardown (free without
`adev->userq_mutex`) from different processes, potentially on different
CPU/NUMA nodes. Realistic in multi-tenant GPU workloads. Unprivileged
users can trigger via DRM ioctls (subject to device access permissions).
### Step 8.3: Failure mode severity
**Record:** Duplicate seq64 slot → two fence drivers alias the same
64-bit memory → **HIGH** severity: GPU synchronization corruption,
possible compute wrong-results or GPU hangs. Not a typical kernel oops,
but serious functional corruption.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH for affected userq users — prevents fence memory
aliasing
- **Risk:** VERY LOW — 8-line, idiomatic atomic bitmap fix, maintainer-
reviewed
- **Ratio:** Strong benefit, minimal risk
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real concurrent alloc/free paths verified (asymmetric mutex coverage)
- Non-atomic `__set_bit`/`__clear_bit` violate kernel bitmap concurrency
rules
- Standard, obviously-correct fix pattern
- Small, single-file, no new APIs
- Reviewed by amdgpu maintainer Alex Deucher
- Buggy code confirmed present in `v6.18.43`; fix not yet applied
- User-mode queues active on modern AMD GPUs in this tree
**AGAINST backport:**
- No crash report or syzbot reproduction
- Christian König questioned whether concurrency is possible (though
code analysis shows alloc/free overlap is real; two simultaneous
allocs are mutex-serialized)
- Affects only user-mode queue users, not all amdgpu users
**Unresolved:** Author's reply to Christian König's thread question not
found; exact "two nodes both allocating" scenario may be overstated, but
alloc/free concurrency is verified.
### Step 9.2: Stable rules checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — idiomatic atomic bitmap
fix; maintainer Reviewed-by; no runtime test cited |
| 2. Fixes a real bug affecting users? | **PASS** — concurrent bitmap
access verified in code paths |
| 3. Important issue? | **PASS** — HIGH: fence memory aliasing, GPU sync
corruption |
| 4. Small and contained? | **PASS** — 8 lines, 1 file |
| 5. No new features/APIs? | **PASS** — internal implementation change
only |
| 6. Can apply to local tree? | **PASS** — clean apply to existing
`amdgpu_seq64.c` |
### Step 9.3: Exception categories
**Record:** None (not a device ID, quirk, DT, build, or docs fix).
Standard race-condition bug fix.
### Step 9.4: Decision rationale
The commit fixes a genuine race in the seq64 slot allocator. While
`amdgpu_userq_create()` serializes allocations via `adev->userq_mutex`,
`amdgpu_seq64_free()` runs from fence-driver destruction without that
lock — `amdgpu_userq_destroy()` only takes the per-client mutex.
Concurrent alloc and free on the shared `adev->seq64.used` bitmap with
non-atomic `__set_bit`/`__clear_bit` is incorrect and can corrupt slot
tracking. The fix is minimal, maintainer-reviewed, and applies cleanly
to this `v6.18.43` tree where the buggy code is present and user-mode
queues are supported.
---
## Verification
- [Phase 1] Parsed subject, tags (SOB, Reviewed-by Alex Deucher), body;
no Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: 8 insertions, 5 deletions in `amdgpu_seq64_alloc` and
`amdgpu_seq64_free`
- [Phase 3] `git describe HEAD`: `v6.18.43`; blame shows buggy
`__set_bit`/`__clear_bit` in current tree
- [Phase 3] `git log --grep` for commit subject: not found in tree (not
yet merged)
- [Phase 4] Lore: v1 at https://lists.freedesktop.org/archives/amd-
gfx/2026-May/144553.html; Reviewed-by at 144599.html; Christian König
question at 144650.html
- [Phase 4] b4 dig by hash: N/A — commit not in checkout
- [Phase 5] `grep amdgpu_seq64_alloc`: single caller in
`amdgpu_userq_fence.c`
- [Phase 5] `grep amdgpu_seq64_free`: error path +
`amdgpu_userq_fence_driver_destroy`
- [Phase 5] Read `amdgpu_userq.c`: create holds `adev->userq_mutex`
(518); destroy does not (394–420)
- [Phase 5] Read `amdgpu_userq_fence.c`: destroy → `kref_put` →
`amdgpu_seq64_free`
- [Phase 6] Confirmed buggy code at lines 178–182, 208; no
`test_and_set_bit` present
- [Phase 6] `amdgpu_seq64_init` present in `amdgpu_device.c` GMC init
path
- [Phase 6] Userq support on gfx11/gfx12/SDMA via `userq_funcs`
assignment verified
- [Phase 8] `AMDGPU_MAX_SEQ64_SLOTS` = 2MiB/8 = 262144 slots per
`amdgpu_seq64.h`
- [Phase 8] `Documentation/atomic_bitops.txt`: `__` prefixed bitops are
non-atomic
- UNVERIFIED: Author's reply to Christian König's concurrency question
(not found in fetched threads)
- UNVERIFIED: Whether fix commit SHA exists on mainline (not in this
stable checkout)
**YES**
drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c
index a0b479d5fff19..f4be192235889 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c
@@ -175,11 +175,14 @@ int amdgpu_seq64_alloc(struct amdgpu_device *adev, u64 *va,
{
unsigned long bit_pos;
- bit_pos = find_first_zero_bit(adev->seq64.used, adev->seq64.num_sem);
- if (bit_pos >= adev->seq64.num_sem)
- return -ENOSPC;
+ for (;;) {
+ bit_pos = find_first_zero_bit(adev->seq64.used, adev->seq64.num_sem);
+ if (bit_pos >= adev->seq64.num_sem)
+ return -ENOSPC;
- __set_bit(bit_pos, adev->seq64.used);
+ if (!test_and_set_bit(bit_pos, adev->seq64.used))
+ break;
+ }
*va = bit_pos * sizeof(u64) + amdgpu_seq64_get_va_base(adev);
@@ -205,7 +208,7 @@ void amdgpu_seq64_free(struct amdgpu_device *adev, u64 va)
bit_pos = (va - amdgpu_seq64_get_va_base(adev)) / sizeof(u64);
if (bit_pos < adev->seq64.num_sem)
- __clear_bit(bit_pos, adev->seq64.used);
+ clear_bit(bit_pos, adev->seq64.used);
}
/**
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds on allocate_doorbell
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (36 preceding siblings ...)
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18] drm/amdgpu: use atomic operation to achieve lockless serialization Sasha Levin
@ 2026-08-31 13:31 ` Sasha Levin
37 siblings, 0 replies; 38+ messages in thread
From: Sasha Levin @ 2026-08-31 13:31 UTC (permalink / raw)
To: patches, stable
Cc: David Francis, Harish Kasiviswanathan, Alex Deucher, Sasha Levin,
Felix.Kuehling, christian.koenig, airlied, simona, amd-gfx,
dri-devel, linux-kernel
From: David Francis <David.Francis@amd.com>
[ Upstream commit 1f087bb8cf9e8797633da35c85435e557ef74d06 ]
allocated_doorbell has an option to set the doorbell id
to a specific value (used by CRIU). This value was not
bounds checked.
Check to confirm it's less than KFD_MAX_NUM_OF_QUEUES_PER_PROCESS.
Signed-off-by: David Francis <David.Francis@amd.com>
Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@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:
# Stable Backport Analysis: `drm/amdkfd: Check bounds on
allocate_doorbell`
**Local tree:** Linux 6.18.43 (`git describe HEAD` →
`v6.18.43-1-gc7f0dac02d232`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject Line
**Record:** `[drm/amdkfd]` `[Check]` — Add bounds validation on doorbell
ID during CRIU restore allocation in `allocate_doorbell()`.
### Step 1.2: Commit Tags
**Record:**
| Tag | Value |
|-----|-------|
| Signed-off-by | David Francis \<David.Francis@amd.com\> |
| Reviewed-by | Harish Kasiviswanathan
\<Harish.Kasiviswanathan@amd.com\> |
| Signed-off-by | Alex Deucher \<alexander.deucher@amd.com\>
(committer/maintainer) |
| Fixes: | None |
| Reported-by: | None |
| Cc: stable | None (expected for manual review) |
| Link: | None |
Notable: Reviewed by AMD colleague; committed by subsystem maintainer.
No syzbot or user bug reports.
### Step 1.3: Commit Body Analysis
**Record:**
- **Bug:** `allocate_doorbell()` accepts a user-specified doorbell ID
via `restore_id` (CRIU restore path) without validating it is within
`KFD_MAX_NUM_OF_QUEUES_PER_PROCESS`.
- **Symptom:** Out-of-bounds `__test_and_set_bit()` on
`qpd->doorbell_bitmap` → kernel memory corruption or crash.
- **Root cause:** CRIU restore copies `doorbell_id` from userspace
(`kfd_criu_queue_priv_data`) and passes it directly to
`allocate_doorbell()` with no upper-bound check.
- **Version info:** None in commit message.
### Step 1.4: Hidden Bug Fix Detection
**Record:** Not disguised — explicitly a missing bounds check. Same
class of bug as the parallel event-restore fix in `kfd_events.c` (`if
(*restore_id >= KFD_SIGNAL_EVENT_LIMIT)`).
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Change Inventory
**Record:**
| File | Changes |
|------|---------|
| `drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c` | +3 lines |
- **Function modified:** `allocate_doorbell()`
- **Scope:** Single-file, surgical fix (3 lines added)
### Step 2.2: Code Flow Change
**Record:**
- **Hunk (CP queues on SOC15, `restore_id` path):**
- **Before:** `__test_and_set_bit(*restore_id, qpd->doorbell_bitmap)`
called with no validation.
- **After:** Return `-EINVAL` if `*restore_id >=
KFD_MAX_NUM_OF_QUEUES_PER_PROCESS` (1024) before the bit operation.
- **Affected path:** CRIU queue restore on SOC15+ compute (CP) queues
only.
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Buffer out-of-bounds / memory safety.
- **Mechanism:** `qpd->doorbell_bitmap` is allocated with
`bitmap_zalloc(KFD_MAX_NUM_OF_QUEUES_PER_PROCESS, GFP_KERNEL)` (1024
bits). An out-of-range `restore_id` causes `__test_and_set_bit()` to
write beyond the allocation.
### Step 2.4: Fix Quality
**Record:**
- Obviously correct; mirrors existing pattern in
`allocate_event_notification_slot()`.
- Minimal, no unrelated changes.
- Low regression risk: only rejects invalid IDs that should never
succeed.
- No API or behavioral changes for valid inputs.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** Buggy `restore_id` path is present in this tree at lines
474–479. Git blame in this stable checkout is unreliable (squashed
history), but the vulnerable code is confirmed present.
### Step 3.2: Fixes: Tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related File History
**Record:**
- Commit on `master`: `a1d4b228e3dc5` (May 19, 2026), cherry-picked from
`1f087bb8cf9e`.
- Part of a 2-patch series; patch 2/2 (`6dc2c49a70519` on master) fixes
the same class of bug for `allocate_sdma_queue()` — separate,
standalone fix.
- Fix is **not** in the local 6.18.43 tree.
### Step 3.4: Author Context
**Record:** David Francis (AMD). Reviewed by Harish Kasiviswanathan;
committed by Alex Deucher (amdgpu/amdkfd maintainer).
### Step 3.5: Dependencies
**Record:** Standalone. No prerequisite commits. Applies cleanly to the
local tree.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original Discussion
**Record:**
- **URL:** https://patch.msgid.link/20260512192824.3682569-1-
David.Francis@amd.com
- **Series:** v1 only (no further revisions via `b4 dig -a`)
- **Review feedback:** No stable nominations, NAKs, or substantive
objections found in the mbox thread.
### Step 4.2: Reviewers
**Record:** CC'd to `amd-gfx@lists.freedesktop.org`. Reviewed-by on
commit.
### Step 4.3: Bug Reports
**Record:** N/A — no external bug report or syzbot link.
### Step 4.4: Related Patches
**Record:** Patch 2/2 bounds-checks `restore_sdma_id` in
`allocate_sdma_queue()`. Same bug class; also missing in this tree.
Independent backport candidate.
### Step 4.5: Stable List History
**Record:** Not searched; no stable-list discussion found in mbox.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key Functions
**Record:** `allocate_doorbell()` — only function modified.
### Step 5.2: Callers
**Record:**
- `create_queue_nocpsch()` → `allocate_doorbell(qpd, q, qd ?
&qd->doorbell_id : NULL)` (line 670)
- `create_queue_cpsch()` → same pattern (line 1991)
- Both reached from `pqm_create_queue()` → `kfd_criu_restore_queue()`
during CRIU restore
### Step 5.3: Callees
**Record:** `__test_and_set_bit()`, `find_first_zero_bit()`,
`set_bit()`, `amdgpu_doorbell_index_on_bar()`.
### Step 5.4: Call Chain / Reachability
**Record:**
```
userspace AMDKFD_IOC_CRIU_OP (restore)
→ criu_restore() → criu_restore_objects()
→ kfd_criu_restore_queue() [copy_from_user q_data including
doorbell_id]
→ pqm_create_queue(..., q_data, ...)
→ create_queue_*() → allocate_doorbell(..., &qd->doorbell_id)
```
Reachable from userspace via CRIU restore ioctl. Requires
`CAP_CHECKPOINT_RESTORE` or `CAP_SYS_ADMIN` (see `kfd_chardev.c` lines
3332–3337).
### Step 5.5: Similar Patterns
**Record:** `kfd_events.c:110` already bounds-checks `*restore_id >=
KFD_SIGNAL_EVENT_LIMIT` for CRIU event restore. This commit closes the
same gap for doorbells.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE
### Step 6.1: Buggy Code Present?
**Record:** **Yes.** Lines 474–479 in `kfd_device_queue_manager.c` lack
the bounds check. CRIU support (`kfd_criu_restore_queue`,
`AMDKFD_IOC_CRIU_OP`) is present. `KFD_MAX_NUM_OF_QUEUES_PER_PROCESS` is
1024.
### Step 6.2: Backport Complications
**Record:** Clean apply expected — 3-line addition with no conflicts.
File structure matches mainline.
### Step 6.3: Related Fixes Already Present?
**Record:** No. `git show master:a1d4b228e3dc5` has the fix; local HEAD
does not. SDMA bounds fix (patch 2/2) is also absent.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem Criticality
**Record:** `drivers/gpu/drm/amd/amdkfd` — AMDGPU KFD compute driver.
**IMPORTANT** (GPU compute users; not core kernel, but widely deployed
on AMD hardware).
### Step 7.2: Subsystem Activity
**Record:** Active — CRIU support and related hardening commits exist on
master for this subsystem.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who Is Affected
**Record:** Users of AMDGPU KFD with CRIU checkpoint/restore on SOC15+
hardware (CP compute queues). Narrow feature set, but real production
use (containers, HPC migration).
### Step 8.2: Trigger Conditions
**Record:**
- CRIU restore with `doorbell_id >= 1024` in checkpoint private data.
- Requires privileged capability (`CAP_CHECKPOINT_RESTORE` or
`CAP_SYS_ADMIN`).
- Corrupted or malicious checkpoint image during restore can trigger it.
- Not triggerable by unprivileged users directly.
### Step 8.3: Failure Mode Severity
**Record:** Out-of-bounds kernel heap write via `__test_and_set_bit()` →
memory corruption, potential kernel oops/panic. **Severity: HIGH**
(memory corruption); mitigated by privileged-only ioctl path.
### Step 8.4: Risk-Benefit
**Record:**
| | Assessment |
|--|------------|
| **Benefit** | Prevents kernel memory corruption on CRIU restore;
defense-in-depth for untrusted checkpoint data |
| **Risk** | Very low — 3-line bounds check, no behavior change for
valid IDs |
| **Ratio** | Favorable |
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence Summary
**FOR backport:**
- Real out-of-bounds bitmap access bug
- Kernel memory corruption possible
- Fix is minimal, obviously correct, maintainer-reviewed
- Buggy code and CRIU infrastructure exist in 6.18.43
- Matches existing bounds-check pattern in `kfd_events.c`
- Standalone, clean apply
**AGAINST backport:**
- CRIU is a niche feature
- Requires privileged capability (not unprivileged attack surface)
- No user reports or syzbot findings
- Patch 2/2 (SDMA) addresses a related gap but is separate
**Unresolved:** None affecting the decision.
### Step 9.2: Stable Rules Checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — trivial bounds check;
Reviewed-by present |
| 2. Fixes a real bug? | **PASS** — OOB `__test_and_set_bit()` on
1024-bit bitmap |
| 3. Important issue? | **PASS** — memory corruption (HIGH, privileged
path) |
| 4. Small and contained? | **PASS** — 3 lines, one function |
| 5. No new features/APIs? | **PASS** |
| 6. Can apply to local tree? | **PASS** — code present, fix absent |
### Step 9.3: Exception Categories
**Record:** None (not a device ID, quirk, DT, build, or docs fix).
Qualifies as a standard memory-safety bug fix.
### Step 9.4: Decision Rationale
For Linux **6.18.43**, the vulnerable CRIU restore path exists, the fix
is absent, and the patch prevents out-of-bounds kernel memory writes
from userspace-supplied `doorbell_id` values. Although CRIU restore
requires elevated privileges, stable trees routinely take such defense-
in-depth fixes — especially when they mirror an existing pattern
(`kfd_events.c`) and are three lines with no regression risk for valid
inputs.
**Note:** Patch 2/2 (`Check bounds for allocate_sdma_queue
restore_sdma_id`) fixes the same bug class for SDMA queues and is also
absent from this tree; it should be evaluated separately.
---
## Verification
- **[Phase 1]** Parsed commit message and tags from user query and `git
show a1d4b228e3dc5`
- **[Phase 1]** No Fixes:/Reported-by:/Cc: stable tags
- **[Phase 2]** Diff analysis: +3 lines in `allocate_doorbell()` before
`__test_and_set_bit()`
- **[Phase 3]** `git describe HEAD`: v6.18.43; `make kernelversion`
equivalent from Makefile: 6.18.43
- **[Phase 3]** `git show a1d4b228e3dc5`: commit exists on master, not
in HEAD
- **[Phase 3]** `b4 dig -c a1d4b228e3dc5`: found lore thread at
patch.msgid.link/20260512192824.3682569-1
- **[Phase 3]** `b4 dig -a`: v1 only, no further revisions
- **[Phase 3]** `b4 dig -w`: CC'd amd-gfx@lists.freedesktop.org
- **[Phase 4]** `b4 dig -m /tmp/doorbell_thread.mbox`: patch 2/2 content
retrieved; no stable Cc in thread
- **[Phase 5]** Grep callers: `allocate_doorbell` called from
`create_queue_nocpsch` and `create_queue_cpsch` with
`&qd->doorbell_id`
- **[Phase 5]** Traced CRIU path: `kfd_criu_restore_queue` →
`pqm_create_queue` → `allocate_doorbell`
- **[Phase 5]** `kfd_events.c:110`: confirmed analogous bounds check
exists for event restore
- **[Phase 6]** Read local `kfd_device_queue_manager.c:474-479`: bounds
check **missing**
- **[Phase 6]** `kfd_doorbell.c:259`: `doorbell_bitmap` allocated with
`KFD_MAX_NUM_OF_QUEUES_PER_PROCESS` (1024)
- **[Phase 6]** `kfd_priv.h:97`: `KFD_MAX_NUM_OF_QUEUES_PER_PROCESS` =
1024
- **[Phase 6]** `kfd_chardev.c:3332-3337`: CRIU ioctl requires
`CAP_CHECKPOINT_RESTORE` or `CAP_SYS_ADMIN`
- **[Phase 6]** CRIU infrastructure confirmed present
(`kfd_criu_restore_queue`, `AMDKFD_IOC_CRIU_OP`)
- **[Phase 8]** Failure mode: OOB bit operation → memory corruption;
privileged ioctl mitigates unprivileged exploitability
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 2f8df95382bc3..d9f09f25911a7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -472,6 +472,9 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
} else {
/* For CP queues on SOC15 */
if (restore_id) {
+ if (*restore_id >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
+ return -EINVAL;
+
/* make sure that ID is free */
if (__test_and_set_bit(*restore_id, qpd->doorbell_bitmap))
return -EINVAL;
--
2.53.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
end of thread, other threads:[~2026-08-31 13:52 UTC | newest]
Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: validate and share PSP fw_pri_buf copies via psp_copy_fw Sasha Levin
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Check for sharpening case when calculating max vtaps for scaler Sasha Levin
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18] drm/amdgpu: validate RAS EEPROM tbl_size before record count Sasha Levin
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18] drm/amd/ras: Fix CPER ring debugfs read overflow Sasha Levin
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18] drm/amd/display: Avoid DPMS-on for phantom stream Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Let driver decide buffer size at AMDKFD_IOC_GET_DMABUF_INFO ioctl Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Initialize dsc_caps to 0 Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] drm/amdkfd: Properly acquire queue buffers in CRIU restore Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: flush pending RCU callbacks on module unload Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Fix updating clock limits from power states Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/pm/si: Don't schedule thermal work when queue isn't initialized Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18] drm/amd/display: Fix 8K Mode Not Parsed by EDID Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] drm/amd/display: Fix CRC open failure during active rendering Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] drm/amdgpu: cap ATOM command table nesting depth Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] drm/amd/ras: reset CPER ring on corrupt entry size Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: Use system unbound workqueue for soft IH ring Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18] drm/amdgpu/userq: pin mqd and fw object bo to avoid eviction Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18] drm/amdgpu: check and drop invalid bad page records Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Fix OOB memory exposure in get_wave_state() Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdgpu: fix buffer overflow during vBIOS update Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: harden FRU PIA parsing with bounded helpers Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: Unwind debug trap enable on copy_to_user failure Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: fix UAF race in destroy_queue_cpsch Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.12] drm/amdgpu: Prefer ROM BAR for default VGA device Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds for allocate_sdma_queue restore_sdma_id Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.6] drm/amd/pm: Check SMUv13.0.6/12 metrics integrity Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] drm/amdgpu: avoid integer overflow in VA range check Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.1] drm/amd/pm: bound pp_dpm_set_pp_table() memcpy Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.6] drm/amdkfd: check find_first_zero_bit before __set_bit on kfd->doorbell_bitmap Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] drm/amdgpu/ras: add ras_suspend callback and use it for cp_ecc_error_irq Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdkfd: fix SMI event cross-process information leak Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu: add first record offset check Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.6] drm/amd/display: Fix DPMS using partially updated pipe context Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: Find link encoder for flexible DIG mapping cases Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu/pm: fix SmartShift bias sysfs store PM refcount on parse error Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] drm/amdgpu: Bound GPIO I2C table entry count from VBIOS Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18] drm/amdgpu: use atomic operation to achieve lockless serialization Sasha Levin
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-6.1] drm/amdkfd: Check bounds on allocate_doorbell Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox