* [PATCH AUTOSEL 6.18] perf/x86/intel/uncore: Guard against invalid box control address
[not found] <20260831133314.4125787-1-sashal@kernel.org>
@ 2026-08-31 13:20 ` Sasha Levin
2026-08-31 13:51 ` sashiko-bot
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-6.12] perf: Fix addr_filter_ranges lifetime Sasha Levin
1 sibling, 1 reply; 4+ messages in thread
From: Sasha Levin @ 2026-08-31 13:20 UTC (permalink / raw)
To: patches, stable
Cc: Zide Chen, Peter Zijlstra (Intel), Dapeng Mi, Sasha Levin, mingo,
acme, namhyung, tglx, bp, dave.hansen, x86, linux-perf-users,
linux-kernel
From: Zide Chen <zide.chen@intel.com>
[ Upstream commit 3c19ea24f02658c4b8ad364458fae4d77fdb3fae ]
Theoretically, intel_uncore_find_discovery_unit() could return NULL,
e.g., when a CPU die is offline during uncore enumeration and its PMU
units are not added to the discovery RB-tree.
Guard against a NULL return value and the resulting invalid box control
address (0) before accessing hardware.
Signed-off-by: Zide Chen <zide.chen@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://patch.msgid.link/20260602144908.263680-3-zide.chen@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `perf/x86/intel/uncore: Guard against
invalid box control address`
**Local tree:** Linux **6.18.44** (`git describe HEAD` → `v6.18.44`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Parse the subject line
**Record:** `[perf/x86/intel/uncore]` `[Guard]` — Add NULL/invalid-
address guards before accessing uncore box control hardware.
### Step 1.2: Parse all commit message tags
**Record:**
| Tag | Value |
|-----|-------|
| Signed-off-by | Zide Chen \<zide.chen@intel.com\> |
| Signed-off-by | Peter Zijlstra (Intel) \<peterz@infradead.org\> |
| Reviewed-by | Dapeng Mi \<dapeng1.mi@linux.intel.com\> |
| Link |
https://patch.msgid.link/20260602144908.263680-3-zide.chen@intel.com |
**Notable patterns:** No `Fixes:`, `Reported-by:`, `Cc: stable`, or
`Tested-by:`. Link is patch **3/3** of the same series as commit
`58cbb1c2aadf` (patch 2/3, already in this tree).
### Step 1.3: Analyze commit body
**Record:**
- **Bug:** `intel_uncore_find_discovery_unit()` can return NULL when a
die was offline during uncore enumeration and its PMU units were never
added to the discovery RB-tree.
- **Symptom:** `intel_generic_uncore_box_ctl()` returns 0; callers then
invoke `wrmsrq(0, …)` or `pci_write_config_dword(pdev, 0, …)` —
invalid hardware access.
- **Root cause:** Commit `58cbb1c2aadf` (already in 6.18.44) made per-
die lookup and removed `WARN_ON_ONCE`, explicitly documenting that
NULL is expected, but did not guard all hardware-access callers.
### Step 1.4: Detect hidden bug fixes
**Record:** Not disguised — this is an explicit defensive bug fix
preventing invalid MSR/PCI config writes. Hidden-bug patterns: N/A
(message is direct).
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory the changes
**Record:**
- **File:** `arch/x86/events/intel/uncore_discovery.c` only
- **Scope:** ~+25 / -10 lines; single-file surgical fix
- **Functions modified:**
- `intel_generic_uncore_msr_init_box`
- `intel_generic_uncore_msr_disable_box`
- `intel_generic_uncore_msr_enable_box`
- `intel_generic_uncore_pci_init_box`
- `intel_generic_uncore_pci_disable_box`
- `intel_generic_uncore_pci_enable_box`
### Step 2.2: Code flow change (per hunk)
**Record:**
| Function | Before | After |
|----------|--------|-------|
| `*_msr_init_box` | `wrmsrq(intel_generic_uncore_box_ctl(box), …)`
unconditionally | Cache `box_ctl`; return early if `!box_ctl` |
| `*_msr_disable/enable_box` | Same unconditional `wrmsrq` | Skip
`wrmsrq` when `!box_ctl` |
| `*_pci_init_box` | `pci_write_config_dword(pdev, box_ctl, …)` even
when `box_ctl==0` | Return early if `!box_ctl` |
| `*_pci_disable/enable_box` | Same unconditional PCI write | Skip write
when `!box_ctl` |
`intel_generic_uncore_assign_hw_event()` already had `if (!box_ctl)
return false` since `b1d9ea2e1ca4` — this patch extends the same pattern
to init/enable/disable paths.
### Step 2.3: Bug mechanism
**Record:** **Category:** NULL/invalid-address hardware access
(logic/correctness fix).
- `intel_generic_uncore_box_ctl()` returns 0 when
`intel_uncore_find_discovery_unit()` finds no unit (verified at lines
484–485).
- `unit->addr` is never 0 for valid units — `uncore_insert_box_info()`
rejects `!unit->ctl` before insertion (lines 229–234).
- `wrmsrq(0, val)` → write to MSR 0 (`native_write_msr` in `asm/msr.h`).
- `pci_write_config_dword(pdev, 0, val)` → write PCI config dword at
offset 0 (vendor/device ID region); `UNCORE_DISCOVERY_PCI_BOX_CTRL(0)`
= 0 per `uncore_discovery.h:36`.
### Step 2.4: Fix quality assessment
**Record:** Fix is minimal, mirrors existing `assign_hw_event` guard,
low regression risk. Early-return on missing discovery unit is
consistent with 58cbb1c2’s stated intent (“PMU box is not functional for
that die”). No lock-order or API changes.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame the changed lines
**Record:**
- `intel_generic_uncore_box_ctl()` introduced in `b1d9ea2e1ca4`
(2024-06-14, Kan Liang).
- Per-die lookup change in `58cbb1c2aadf` (2026-06-02, Zide Chen) —
**present in 6.18.44**.
- Unguarded `wrmsrq`/`pci_write_config_dword` callers date to 2021
(`d6c754130435ab`, `42839ef4a20a4b`).
- Guard commit itself: **not found** in this tree’s history.
### Step 3.2: Follow Fixes: tag
**Record:** No `Fixes:` tag. Functionally follows `58cbb1c2aadf`, which
is already in this tree.
### Step 3.3: Related file history
**Record:** Recent related commits in this tree:
- `58cbb1c2aadf` — Fix discovery unit lookup for multi-die systems
(prerequisite, in tree)
- `f34feda8e0c95` — Skip discovery table for offline dies (in tree;
`Reported-by: Steve Wahl`, real multi-die boot issue)
### Step 3.4: Author context
**Record:** Zide Chen authored both `f34feda8e0c95` and `58cbb1c2aadf`
on this file. Peter Zijlstra (perf maintainer) signed off. Dapeng Mi
(Intel) reviewed.
### Step 3.5: Dependencies
**Record:** Depends on `58cbb1c2aadf` (already in 6.18.44). No other
prerequisites. Patch 3/3 of series; patches 1–2 appear already applied.
Standalone and self-contained.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original patch discussion
**Record:** `b4 dig -c` failed (commit not in local tree).
Lore/patch.msgid.link fetch blocked by Anubis bot protection. Series
context inferred from `58cbb1c2aadf` Link (`263680-2`) and this patch’s
Link (`263680-3`).
### Step 4.2: Reviewers
**Record:** Reviewed-by Dapeng Mi; Signed-off-by Peter Zijlstra —
appropriate perf/x86 maintainers.
### Step 4.3: Bug report
**Record:** No user/syzbot report in this commit. Related
`f34feda8e0c95` documents real multi-die/offline-die scenarios
(`Reported-by: Steve Wahl`, WARNING at `uncore_pci_pmu_register`).
### Step 4.4: Series context
**Record:** Part of 3-patch series from Zide Chen (June 2026). Patch 2
(`58cbb1c2aadf`) explicitly states NULL discovery units are expected
after per-die lookup; this patch completes that work.
### Step 4.5: Stable mailing list
**Record:** Could not search lore (bot protection). No stable discussion
found locally.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** Six box init/enable/disable functions listed in Phase 2.1.
### Step 5.2: Callers
**Record:**
- `init_box` via `uncore_box_init()` (`uncore.h:538–543`):
- `uncore_pci_pmu_register()` at `uncore.c:1158` (PCI probe)
- `uncore_box_ref()` at `uncore.c:1602` (CPU online on a die)
- `enable_box` / `disable_box` via `uncore_pmu_enable()` /
`uncore_pmu_disable()` at `uncore.c:820–836` (perf PMU enable/disable)
### Step 5.3: Callees
**Record:** `wrmsrq()` → `native_write_msr()`;
`pci_write_config_dword()` → PCI config space write.
### Step 5.4: Call chain / reachability
**Record:**
1. Multi-die Intel server with generic discovery tables
(`CONFIG_PERF_EVENTS`, Intel uncore PMU).
2. Die offline during enumeration → discovery units not in RB-tree
(`f34feda8` + MSR path only parses online dies at
`uncore_discovery.c:415–426`).
3. Die later online or PCI box registered → `uncore_box_init` / PMU
enable runs.
4. `intel_generic_uncore_box_ctl()` returns 0 → unguarded path writes
MSR 0 or PCI offset 0.
Reachable from CPU hotplug and perf uncore use; requires root for perf
but init runs at probe/hotplug without user perf events.
### Step 5.5: Similar patterns
**Record:** `intel_generic_uncore_assign_hw_event()` already guards `if
(!box_ctl) return false` at lines 545–547. This patch applies the same
pattern to sibling functions — consistent, not novel logic.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE (6.18.44)
### Step 6.1: Does buggy code exist?
**Record:** **YES.** Current tree at `uncore_discovery.c:490–503` and
`567–589` calls `wrmsrq`/`pci_write_config_dword` without checking
`box_ctl`. Per-die NULL return path exists since `58cbb1c2aadf` (lines
482–485).
### Step 6.2: Backport complications
**Record:** Clean apply expected — single file, no conflicting changes
since `58cbb1c2aadf`. Minor style change (remove local `pdev` variable)
is cosmetic.
### Step 6.3: Related fixes already present?
**Record:** `58cbb1c2aadf` and `f34feda8e0c95` are in tree.
`assign_hw_event` guard present. **This specific guard commit is
absent.**
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `arch/x86/events/intel/` — perf uncore PMU on Intel x86.
**IMPORTANT** (not universal core, but affects Intel server/workstation
perf and hotplug paths).
### Step 7.2: Subsystem activity
**Record:** Active development in 2026 (multi-die discovery fixes).
Mature uncore framework with recent multi-die-related churn.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Intel x86 systems using generic uncore discovery (modern
server platforms — Sapphire Rapids and later class). Config-specific
(`CONFIG_PERF_EVENTS`, Intel uncore with discovery tables).
### Step 8.2: Trigger conditions
**Record:** Multi-die system where a die is offline during uncore
enumeration; die later comes online or box is initialized. Uncommon but
documented in the same author’s series. Not userspace-exploitable in a
straightforward way; triggered by boot topology / hotplug.
### Step 8.3: Failure mode severity
**Record:**
- `wrmsrq(0, …)` → likely #GP / kernel oops on invalid MSR write
- `pci_write_config_dword(pdev, 0, …)` → write to PCI config offset 0
(vendor/device ID) — hardware corruption risk
**Severity: HIGH** (potential oops / invalid hardware access), though
trigger is relatively rare.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** Prevents invalid MSR/PCI writes on a path made explicitly
reachable by `58cbb1c2aadf` already in this tree
- **Risk:** Very low — early-return mirrors existing `assign_hw_event`
logic
- **Ratio:** Strong benefit, minimal risk
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real bug: hardware access at address 0 when discovery unit missing
- Prerequisite `58cbb1c2aadf` already in 6.18.44 and documents NULL as
expected
- Small, single-file, obviously correct fix
- Reviewed by Intel engineer; signed off by perf maintainer
- Completes incomplete fix from patch 2/3 of same series
- Invalid MSR/PCI writes can cause kernel oops
**AGAINST backport:**
- Commit says “theoretically” — no direct user crash report for this
specific patch
- Affects niche multi-die + offline-die boot scenarios
- Perf subsystem, not core kernel path
**Unresolved:** Lore thread content; upstream commit SHA for this
specific patch (not in local tree).
### Step 9.2: Stable rules checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — mirrors existing guard;
reviewed by subsystem engineer |
| 2. Fixes real bug affecting users? | **PASS** — invalid hardware
access on documented code path |
| 3. Important issue? | **PASS** — potential kernel oops / invalid PCI
config write (HIGH) |
| 4. Small and contained? | **PASS** — one file, ~25 lines |
| 5. No new features/APIs? | **PASS** — defensive guards only |
| 6. Can apply to local tree? | **PASS** — prerequisite in tree; clean
apply expected |
### Step 9.3: Exception categories
**Record:** None (not device ID, quirk, DT, build, or docs). Standard
bug fix.
### Step 9.4: Decision rationale
This tree (6.18.44) already contains `58cbb1c2aadf`, which intentionally
allows `intel_uncore_find_discovery_unit()` to return NULL for offline-
die enumeration gaps. Without this follow-up,
`init_box`/`enable_box`/`disable_box` still perform `wrmsrq(0, …)` and
`pci_write_config_dword(pdev, 0, …)`. The fix is the natural completion
of an already-backported series, minimal, and prevents a plausible
kernel oops on multi-die Intel systems.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body from user-provided commit
message
- **[Phase 2]** Diff analysis: 6 functions guarded in
`uncore_discovery.c`
- **[Phase 3]** `git describe HEAD` → v6.18.44 / 6.18.44
- **[Phase 3]** `git blame -L 478,580` → `b1d9ea2e1ca4`, `58cbb1c2aadf`
on lookup path
- **[Phase 3]** `git show 58cbb1c2aadf` → prerequisite in tree;
documents expected NULL
- **[Phase 3]** `git show f34feda8e0c95` → offline-die skip in tree;
Steve Wahl report
- **[Phase 3]** `git log --grep="Guard against invalid box control"` →
no match (commit not in tree)
- **[Phase 4]** `b4 dig -c HEAD` → commit not in tree; cannot dig
- **[Phase 4]** WebFetch lore/patch.msgid.link → blocked by Anubis
- **[Phase 5]** Read `uncore.h:538–543`, `uncore.c:820–836,1158,1602` →
call paths verified
- **[Phase 5]** Read `uncore_discovery.c:229–234,478–589` → buggy code
and missing guards verified
- **[Phase 5]** Read `uncore_discovery.h:36` →
`UNCORE_DISCOVERY_PCI_BOX_CTRL(0)` = 0
- **[Phase 5]** Read `asm/msr.h:197–200` → `wrmsrq` → `native_write_msr`
- **[Phase 6]** Buggy unguarded code confirmed present in 6.18.44
checkout
- **[Phase 6]** `58cbb1c2aadf` and `f34feda8e0c95` confirmed in tree via
`git log`
- **[UNVERIFIED]** Lore thread review comments and explicit stable
nominations
**YES**The background search for this commit in the local tree finished
with no matches — `git log --grep="Guard against invalid box control"`
and `--grep="invalid box control"` both came up empty. So the guard
patch isn’t in **6.18.44** yet, while its prerequisite `58cbb1c2aadf`
(“Fix discovery unit lookup for multi-die systems”) is already there.
That lines up with the earlier analysis: the tree has the per-die lookup
change that can return NULL/0, but not the follow-up that stops
`wrmsrq(0, …)` and `pci_write_config_dword(pdev, 0, …)` in the
init/enable/disable paths. Backport recommendation remains **YES**.
arch/x86/events/intel/uncore_discovery.c | 33 +++++++++++++++++-------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/arch/x86/events/intel/uncore_discovery.c b/arch/x86/events/intel/uncore_discovery.c
index 7dd3910d8de3a..8595e14199ed4 100644
--- a/arch/x86/events/intel/uncore_discovery.c
+++ b/arch/x86/events/intel/uncore_discovery.c
@@ -489,17 +489,28 @@ static u64 intel_generic_uncore_box_ctl(struct intel_uncore_box *box)
void intel_generic_uncore_msr_init_box(struct intel_uncore_box *box)
{
- wrmsrq(intel_generic_uncore_box_ctl(box), GENERIC_PMON_BOX_CTL_INT);
+ u64 box_ctl = intel_generic_uncore_box_ctl(box);
+
+ if (!box_ctl)
+ return;
+
+ wrmsrq(box_ctl, GENERIC_PMON_BOX_CTL_INT);
}
void intel_generic_uncore_msr_disable_box(struct intel_uncore_box *box)
{
- wrmsrq(intel_generic_uncore_box_ctl(box), GENERIC_PMON_BOX_CTL_FRZ);
+ u64 box_ctl = intel_generic_uncore_box_ctl(box);
+
+ if (box_ctl)
+ wrmsrq(box_ctl, GENERIC_PMON_BOX_CTL_FRZ);
}
void intel_generic_uncore_msr_enable_box(struct intel_uncore_box *box)
{
- wrmsrq(intel_generic_uncore_box_ctl(box), 0);
+ u64 box_ctl = intel_generic_uncore_box_ctl(box);
+
+ if (box_ctl)
+ wrmsrq(box_ctl, 0);
}
static void intel_generic_uncore_msr_enable_event(struct intel_uncore_box *box,
@@ -548,6 +559,7 @@ bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
if (box->pci_dev) {
box_ctl = UNCORE_DISCOVERY_PCI_BOX_CTRL(box_ctl);
+
hwc->config_base = box_ctl + uncore_pci_event_ctl(box, hwc->idx);
hwc->event_base = box_ctl + uncore_pci_perf_ctr(box, hwc->idx);
return true;
@@ -566,27 +578,30 @@ static inline int intel_pci_uncore_box_ctl(struct intel_uncore_box *box)
void intel_generic_uncore_pci_init_box(struct intel_uncore_box *box)
{
- struct pci_dev *pdev = box->pci_dev;
int box_ctl = intel_pci_uncore_box_ctl(box);
+ if (!box_ctl)
+ return;
+
__set_bit(UNCORE_BOX_FLAG_CTL_OFFS8, &box->flags);
- pci_write_config_dword(pdev, box_ctl, GENERIC_PMON_BOX_CTL_INT);
+ pci_write_config_dword(box->pci_dev, box_ctl, GENERIC_PMON_BOX_CTL_INT);
}
void intel_generic_uncore_pci_disable_box(struct intel_uncore_box *box)
{
- struct pci_dev *pdev = box->pci_dev;
int box_ctl = intel_pci_uncore_box_ctl(box);
- pci_write_config_dword(pdev, box_ctl, GENERIC_PMON_BOX_CTL_FRZ);
+ if (box_ctl)
+ pci_write_config_dword(box->pci_dev, box_ctl,
+ GENERIC_PMON_BOX_CTL_FRZ);
}
void intel_generic_uncore_pci_enable_box(struct intel_uncore_box *box)
{
- struct pci_dev *pdev = box->pci_dev;
int box_ctl = intel_pci_uncore_box_ctl(box);
- pci_write_config_dword(pdev, box_ctl, 0);
+ if (box_ctl)
+ pci_write_config_dword(box->pci_dev, box_ctl, 0);
}
static void intel_generic_uncore_pci_enable_event(struct intel_uncore_box *box,
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] perf: Fix addr_filter_ranges lifetime
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:20 ` [PATCH AUTOSEL 6.18] perf/x86/intel/uncore: Guard against invalid box control address Sasha Levin
@ 2026-08-31 13:24 ` Sasha Levin
2026-08-31 15:04 ` sashiko-bot
1 sibling, 1 reply; 4+ messages in thread
From: Sasha Levin @ 2026-08-31 13:24 UTC (permalink / raw)
To: patches, stable
Cc: Peter Zijlstra, Lee Jia Jie, Sasha Levin, mingo, acme, namhyung,
linux-perf-users, linux-kernel
From: Peter Zijlstra <peterz@infradead.org>
[ Upstream commit e62d4192e593630f355094adc467058a05bdc935 ]
Lee Jia Jie reported that since event::addr_filter_ranges is used
under RCU, it should be RCU freed.
Reported-by: Lee Jia Jie <jiajie.lee@starlabs.sg>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit Message Forensics
### Step 1.1: Parse Subject Line
**Record:** `[perf]` `[Fix]` — correct the lifetime of
`event::addr_filter_ranges` so it is freed only after RCU readers are
done.
### Step 1.2: Parse All Commit Message Tags
**Record:**
- **Reported-by:** Lee Jia Jie \<jiajie.lee@starlabs.sg\> — single
reporter; indicates a real review/testing finding
- **Signed-off-by:** Peter Zijlstra (Intel) \<peterz@infradead.org\> —
perf subsystem maintainer
- No Fixes:, Link:, Tested-by:, Reviewed-by:, Acked-by:, or Cc: stable
tags (absence of Cc: stable is expected per review pipeline)
### Step 1.3: Analyze Commit Body
**Record:**
- **Bug:** `event::addr_filter_ranges` is accessed under RCU but was
freed synchronously in `__free_event()` before the RCU grace period
ended.
- **Symptom:** Use-after-free when RCU readers still access the array
(crash, KASAN report, or memory corruption).
- **Root cause:** `kfree(event->addr_filter_ranges)` ran in
`__free_event()` while `call_rcu(&event->rcu_head, free_event_rcu)`
deferred only the `perf_event` struct itself — not the separately
allocated array.
- **Version info:** None in the commit message.
### Step 1.4: Detect Hidden Bug Fixes
**Record:** Not disguised — this is an explicit lifetime/UAF fix. The
one-line move of `kfree()` from synchronous teardown to the RCU callback
is a classic deferred-free pattern.
---
## Phase 2: Diff Analysis
### Step 2.1: Inventory the Changes
**Record:**
- **File:** `kernel/events/core.c` (+1 / −2 lines)
- **Functions modified:** `free_event_rcu()`, `__free_event()`
- **Scope:** Single-file, surgical fix (2-line net change)
### Step 2.2: Code Flow Change
**Record:**
- **Hunk 1 (`free_event_rcu`):** Before → frees only `perf_event` struct
(after filter cleanup). After → also
`kfree(event->addr_filter_ranges)` here, after RCU grace period.
- **Hunk 2 (`__free_event`):** Before →
`kfree(event->addr_filter_ranges)` synchronously, then `call_rcu()`.
After → array is not freed here; only the event struct is deferred via
`call_rcu()`.
### Step 2.3: Bug Mechanism
**Record:** **Memory safety / use-after-free.** Category (d).
`addr_filter_ranges` is a separately `kcalloc()`'d array accessed from
RCU-protected iterators while the parent `perf_event` may still be
visible to RCU readers until `free_event_rcu()` runs.
### Step 2.4: Fix Quality
**Record:** Obviously correct — mirrors how the `perf_event` struct
itself is already RCU-freed. Minimal change. `kfree(NULL)` is safe for
events without address filters. No meaningful regression risk.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame Changed Lines
**Record:** `kfree(event->addr_filter_ranges)` in `__free_event()` was
placed there by **c70ca298036c5** ("perf/core: Simplify the
perf_event_alloc() error path", Nov 2024). The same premature-free
pattern existed in `_free_event()` since **c60f83b813e5b** (Feb 2019)
when `addr_filter_ranges` was introduced.
### Step 3.2: Follow Fixes: Tag
**Record:** No Fixes: tag present — N/A.
### Step 3.3: File History for Related Changes
**Record:** Related commits in this tree:
- **c60f83b813e5b** (2019) — introduced `addr_filter_ranges`
- **c70ca298036c5** (2024) — refactored into `__free_event()`, kept
premature `kfree`
- **0fe8813baf4b2** (Jan 2025) — restored RCU read-lock around
`perf_iterate_ctx()` in `perf_event_exec()` (Cc: stable)
- **e62d4192e5936** (Jun 2026) — this fix; on `master`, **not** in
current HEAD
Standalone fix, not part of a series.
### Step 3.4: Author's Other Commits
**Record:** Peter Zijlstra is the perf core maintainer. He authored
c70ca298 (which organized the buggy path) and e62d4192 (this fix).
Multiple recent perf UAF/lifetime fixes exist on this stable branch
(e.g. c27dea9f50ed5 perf_mmap UAF, c8b7e113f7b61 perf/aux page UAF).
### Step 3.5: Prerequisites
**Record:** No dependencies. `git apply --check` on e62d4192 against
current tree succeeds cleanly. Self-contained.
---
## Phase 4: Mailing List and External Research
### Step 4.1: Original Patch Discussion
**Record:** `b4 dig -c e62d4192e5936` →
https://patch.msgid.link/178186383722.1650852.13407085310329360626.tip-
bot2@tip-bot2 (tip-bot commit notification). `b4 dig -a` returned no
additional revisions (single-shot fix). Lore fetch blocked by bot
protection — could not read thread content.
### Step 4.2: Reviewers
**Record:** `b4 dig -w` returned only the tip-bot link; no expanded
recipient list available.
### Step 4.3: Bug Report
**Record:** Reported-by Lee Jia Jie only; no syzbot, no Link: to
external tracker. Reporter is also credited on c8b7e113f7b61 (another
perf UAF fix in this tree), suggesting active perf security review.
### Step 4.4: Related Patches/Series
**Record:** Standalone; no series.
### Step 4.5: Stable Mailing List
**Record:** Lore stable search blocked. UNVERIFIED whether stable
maintainers already discussed this specific fix.
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `free_event_rcu()`, `__free_event()`, `_free_event()`,
`perf_iterate_ctx()`, `__perf_addr_filters_adjust()`,
`perf_event_addr_filters_exec()`, `perf_addr_filters_adjust()`,
`perf_event_exec()`.
### Step 5.2: Trace Callers
**Record:** RCU readers accessing `addr_filter_ranges`:
- `perf_addr_filters_adjust()` → `rcu_read_lock()` →
`perf_iterate_ctx()` → `__perf_addr_filters_adjust()` — triggered from
`perf_event_mmap()` on every executable `mmap()`
- `perf_event_exec()` → `scoped_guard(rcu)` → `perf_iterate_ctx()` →
`perf_event_addr_filters_exec()` — triggered on every `execve()`
Teardown path: `perf_release` / `perf_event_exit_task` → `_free_event()`
→ `__free_event()` → `kfree(addr_filter_ranges)` [buggy] →
`call_rcu(free_event_rcu)`.
### Step 5.3: Key Callees
**Record:** `kcalloc()` allocates the array (line 13103);
`list_for_each_entry_rcu()` in `perf_iterate_ctx()` (line 8604);
`list_del_rcu(&event->event_entry)` in `list_del_event()` (line 2136)
removes the event from the RCU list but does not wait for grace period
before the array is freed.
### Step 5.4: Call Chain / Reachability
**Record:** Reachable from normal process activity (`mmap` of executable
mappings, `execve`) concurrent with `perf_event` close/exit. Affects
processes using perf events with address filters on PMUs that expose
`nr_addr_filters` (Intel PT at `arch/x86/events/intel/pt.c`, CoreSight
ETM at `drivers/hwtracing/coresight/coresight-etm-perf.c`).
### Step 5.5: Similar Patterns
**Record:** Same file has multiple recent RCU/lifetime fixes (perf_mmap
UAF, aux page UAF). The fix pattern (move free into RCU callback)
matches `free_event_rcu()`'s existing role for the event struct.
---
## Phase 6: Cross-Referencing Against Local Tree
### Step 6.1: Does Buggy Code Exist?
**Record:** **YES.** Tree is **linux-6.18.y** at
`v6.18.44-1-g2736c32da98b9` (Makefile: 6.18.44). Buggy
`kfree(event->addr_filter_ranges)` is at line 5610 in `__free_event()`.
`free_event_rcu()` at lines 5157–5165 does not yet free the array. Fix
commit e62d4192e5936 is **not** an ancestor of HEAD.
### Step 6.2: Backport Complications
**Record:** `git apply --check` passes cleanly. Line numbers differ
slightly from the patch context but structure matches. Expected: clean
apply.
### Step 6.3: Related Fixes Already Present?
**Record:** No equivalent fix found. The premature `kfree` is still
present.
---
## Phase 7: Subsystem and Maintainer Context
### Step 7.1: Subsystem Criticality
**Record:** **perf core** (`kernel/events/core.c`) — **CORE/IMPORTANT**.
Not universal like the scheduler, but widely used for profiling/tracing;
bugs are memory-safety issues in kernel code reachable from syscalls.
### Step 7.2: Subsystem Activity
**Record:** Highly active — 106 commits to `kernel/events/core.c` since
c70ca298; multiple UAF fixes landed on this stable branch in 2025–2026.
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** Users of perf events with address filters — Intel Processor
Trace and Arm CoreSight ETM tracing with file-based or kernel address
filters. Config-dependent on `CONFIG_PERF_EVENTS` and PMU drivers with
`nr_addr_filters > 0`.
### Step 8.2: Trigger Conditions
**Record:** Concurrent perf event teardown (`close(2)` on perf fd, task
exit) with `mmap()` of executable mappings or `execve()` in the same
process context while address-filter events exist. Timing-dependent but
realistic. Unprivileged users can trigger via normal perf usage.
### Step 8.3: Failure Mode Severity
**Record:** **Use-after-free** on kernel heap → kernel oops, KASAN
splat, or exploitable memory corruption. **Severity: HIGH** (potential
security impact via UAF).
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH — prevents UAF in perf core on realistic concurrent
paths
- **Risk:** VERY LOW — 2-line move, no API/behavior change, maintainer-
authored
- **Ratio:** Strongly favors backport
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Compile
**FOR backport:**
- Real UAF: `addr_filter_ranges` freed before RCU grace period while RCU
iterators access it
- RCU access paths verified in `perf_addr_filters_adjust()` and
`perf_event_exec()`
- Small, surgical, maintainer fix; applies cleanly to 6.18.y
- Bug present since 2019; still unfixed in this tree
- Reported by active perf security reviewer
- Same class of fix as other accepted stable perf UAF fixes on this
branch
**AGAINST backport:**
- Niche hardware (PT/CoreSight address filters) — not every user
- No syzbot reproducer or crash log in commit message
- Lore discussion content unverified
**UNRESOLVED:**
- Full mailing-list review thread content (lore blocked)
- Whether Lee Jia Jie's report included a concrete reproducer/crash log
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — standard RCU deferred-free;
maintainer fix; no logic ambiguity
2. Fixes a real bug? **PASS** — UAF verified by code path analysis
3. Important issue? **PASS** — UAF / potential crash or security issue
(HIGH)
4. Small and contained? **PASS** — 3 lines, one file
5. No new features or APIs? **PASS** — lifetime fix only
6. Can apply to local tree? **PASS** — `git apply --check` succeeds;
buggy code confirmed present
### Step 9.3: Exception Categories
**Record:** None (not device ID, quirk, DT, build, or docs). Qualifies
on straight bug-fix criteria.
### Step 9.4: Problem Summary for Stable Users
When a perf event with address filters is torn down, `__free_event()`
immediately frees `addr_filter_ranges` but defers freeing the
`perf_event` struct via RCU. Meanwhile, `mmap()` and `execve()` paths
iterate events under `rcu_read_lock()` and read/write
`event->addr_filter_ranges[]`. A concurrent close/exit can free the
array while an RCU reader still uses it — a classic use-after-free.
The fix moves `kfree(event->addr_filter_ranges)` into
`free_event_rcu()`, ensuring the array outlives all RCU readers,
consistent with how the event struct itself is freed.
---
## Verification
- [Phase 1] Parsed subject, tags, body from `git show e62d4192e5936`
- [Phase 2] Diff: +1 line in `free_event_rcu`, −1 line in
`__free_event`; net 3 lines changed
- [Phase 3] `git describe HEAD`: v6.18.44 on linux-6.18.y
- [Phase 3] `git blame -L 5608,5612`: kfree placed by c70ca298036c5
- [Phase 3] `git log -S 'kfree(event->addr_filter_ranges)'`:
c60f83b813e5b, c70ca298036c5
- [Phase 3] `git merge-base --is-ancestor e62d4192e5936 HEAD`: fix NOT
in tree
- [Phase 3] `git merge-base --is-ancestor c70ca298036c5 HEAD`: bug-
introducing refactor IS in tree
- [Phase 4] `b4 dig -c e62d4192e5936`: tip-bot lore link found
- [Phase 4] `b4 dig -a`, `b4 dig -w`: no extra revisions; minimal
recipient info
- [Phase 4] Lore fetch: BLOCKED by bot protection — thread content
UNVERIFIED
- [Phase 5] `grep addr_filter_ranges kernel/events/core.c`: RCU access
at lines 8690–8691, 9566, 11514–11520
- [Phase 5] `perf_iterate_ctx` uses `list_for_each_entry_rcu` at line
8604
- [Phase 5] `perf_addr_filters_adjust` uses `rcu_read_lock` at line 9594
- [Phase 5] `perf_event_exec` uses `scoped_guard(rcu)` at line 8716
- [Phase 5] PMUs with address filters: `arch/x86/events/intel/pt.c`,
`drivers/hwtracing/coresight/coresight-etm-perf.c`
- [Phase 6] Buggy `kfree` at line 5610 confirmed in working tree
- [Phase 6] `git apply --check` of e62d4192: PASSES cleanly
- [Phase 6] `free_event_rcu` at lines 5157–5165 lacks
`kfree(addr_filter_ranges)` — confirms fix needed
- [Phase 8] Failure mode: UAF, severity HIGH
**YES****Backport recommendation: YES** for linux-6.18.y (v6.18.44).
This is a small perf-core UAF fix: `event->addr_filter_ranges` was freed
in `__free_event()` before the RCU grace period ended, while `mmap()`
and `execve()` paths still access it under RCU via `perf_iterate_ctx()`.
The fix moves `kfree()` into `free_event_rcu()`, matching how the event
struct itself is freed.
The buggy code is present in your checkout; commit `e62d4192e5936` is on
`master` but not in HEAD. The patch applies cleanly with `git apply
--check`.
kernel/events/core.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f3bd7c97c3aab..99810cfecfd8c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5161,6 +5161,7 @@ static void free_event_rcu(struct rcu_head *head)
if (event->ns)
put_pid_ns(event->ns);
perf_event_free_filter(event);
+ kfree(event->addr_filter_ranges);
kmem_cache_free(perf_event_cache, event);
}
@@ -5607,8 +5608,6 @@ static void __free_event(struct perf_event *event)
if (event->attach_state & PERF_ATTACH_CALLCHAIN)
put_callchain_buffers();
- kfree(event->addr_filter_ranges);
-
if (event->attach_state & PERF_ATTACH_EXCLUSIVE)
exclusive_event_destroy(event);
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH AUTOSEL 6.18] perf/x86/intel/uncore: Guard against invalid box control address
2026-08-31 13:20 ` [PATCH AUTOSEL 6.18] perf/x86/intel/uncore: Guard against invalid box control address Sasha Levin
@ 2026-08-31 13:51 ` sashiko-bot
0 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-08-31 13:51 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-perf-users
> From: Zide Chen <zide.chen@intel.com>
>
> [ Upstream commit 3c19ea24f02658c4b8ad364458fae4d77fdb3fae ]
>
> Theoretically, intel_uncore_find_discovery_unit() could return NULL,
> e.g., when a CPU die is offline during uncore enumeration and its PMU
> units are not added to the discovery RB-tree.
>
> Guard against a NULL return value and the resulting invalid box control
> address (0) before accessing hardware.
>
> Signed-off-by: Zide Chen <zide.chen@intel.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
> Link: https://patch.msgid.link/20260602144908.263680-3-zide.chen@intel.com
> Signed-off-by: Sasha Levin <sashal@kernel.org>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831133314.4125787-18-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH AUTOSEL 6.18-6.12] perf: Fix addr_filter_ranges lifetime
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-6.12] perf: Fix addr_filter_ranges lifetime Sasha Levin
@ 2026-08-31 15:04 ` sashiko-bot
0 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-08-31 15:04 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-perf-users
> From: Peter Zijlstra <peterz@infradead.org>
>
> [ Upstream commit e62d4192e593630f355094adc467058a05bdc935 ]
>
> Lee Jia Jie reported that since event::addr_filter_ranges is used
> under RCU, it should be RCU freed.
>
> Reported-by: Lee Jia Jie <jiajie.lee@starlabs.sg>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831133314.4125787-227-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-31 15:04 UTC | newest]
Thread overview: 4+ 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:20 ` [PATCH AUTOSEL 6.18] perf/x86/intel/uncore: Guard against invalid box control address Sasha Levin
2026-08-31 13:51 ` sashiko-bot
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-6.12] perf: Fix addr_filter_ranges lifetime Sasha Levin
2026-08-31 15:04 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox