[PATCH AUTOSEL 6.18-5.10] PCI: altera: Protect root bus removal with rescan lock

From: Sasha Levin

Date: Mon Aug 31 2026 - 10:21:28 EST


From: Hans Zhang <18255117159@xxxxxxx>

[ Upstream commit a8759c8ac48c0419f5899e95a6ffc611b07c965b ]

Hold the pci_rescan_remove_lock lock while stopping and removing a root bus
to avoid racing with concurrent rescan or hotplug operations triggered via
sysfs. Such races may lead to use-after-free issues or system crashes.

Signed-off-by: Hans Zhang <18255117159@xxxxxxx>
Signed-off-by: Manivannan Sadhasivam <mani@xxxxxxxxxx>
[bhelgaas: commit log]
Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
Link: https://patch.msgid.link/20260521161822.132996-4-18255117159@xxxxxxx
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---

LLM Generated explanations, may be completely bogus:

# Stable Backport Analysis: PCI: altera: Protect root bus removal with
rescan lock

**Local tree:** `v6.18.44-1-g2736c32da98b9` (kernel 6.18.44)
**Fix commit on mainline:** `a8759c8ac48c0` — **not present in this
tree**
**Buggy code:** present since `ec15c4d0d5d2e` (2019, "PCI: altera: Allow
building as module")

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: Subject line
**Record:** `[PCI: altera]` `[Protect]` — Protect root bus removal with
rescan lock during driver teardown.

### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Hans Zhang `<18255117159@xxxxxxx>` (author)
- **Signed-off-by:** Manivannan Sadhasivam `<mani@xxxxxxxxxx>` (PCI
maintainer reviewer)
- **Signed-off-by:** Bjorn Helgaas `<bhelgaas@xxxxxxxxxx>` (PCI
maintainer, committer)
- **Link:**
`https://patch.msgid.link/20260521161822.132996-4-18255117159@xxxxxxx`
- No Fixes:, Reported-by:, Tested-by:, Cc: stable@xxxxxxxxxxxxxxx
- Notable: maintainer sign-offs from PCI subsystem; no syzbot or user
crash report

### Step 1.3: Body analysis
**Record:**
- **Bug:** `altera_pcie_remove()` calls `pci_stop_root_bus()` /
`pci_remove_root_bus()` without holding `pci_rescan_remove_lock`.
- **Symptom:** Race with concurrent sysfs-triggered PCI rescan or
hotplug → use-after-free or system crash.
- **Root cause:** Root bus teardown and sysfs rescan/remove paths can
run concurrently on the same bus topology.
- **Version info:** None explicit; bug dates to 2019 module-support
commit in this tree.

### Step 1.4: Hidden bug fix?
**Record:** No — this is an explicit synchronization bug fix, not
disguised cleanup.

---

## PHASE 2: DIFF ANALYSIS

### Step 2.1: Inventory
**Record:**
- **File:** `drivers/pci/controller/pcie-altera.c` (+2 lines)
- **Function:** `altera_pcie_remove()`
- **Scope:** Single-file, surgical fix (2 insertions)

### Step 2.2: Code flow change
**Record:**
- **Before:** `pci_stop_root_bus()` → `pci_remove_root_bus()` →
`altera_pcie_irq_teardown()` with no lock.
- **After:** Same sequence wrapped in `pci_lock_rescan_remove()` /
`pci_unlock_rescan_remove()`.
- **Path affected:** Platform driver `.remove` callback (module unload /
device unbind).

### Step 2.3: Bug mechanism
**Record:** **Category: synchronization / race condition.**
- Sysfs rescan (`rescan_store`, `dev_rescan_store` in `pci-sysfs.c`)
holds `pci_rescan_remove_lock`.
- `altera_pcie_remove()` did not, so teardown and rescan could
interleave on the same bus.
- `pci_stop_and_remove_bus_device()` uses
`lockdep_assert_held(&pci_rescan_remove_lock)` — the PCI core expects
this lock for bus mutation; root-bus removal should follow the same
rule.

### Step 2.4: Fix quality
**Record:**
- **Quality:** High — matches `pci-aardvark.c`, `pci-mvebu.c`, `pci-
host-common.c`, `pci-hyperv.c`, `pcie-mediatek-gen3.c`.
- **Regression risk:** Very low — standard mutex, no API change, IRQ
teardown stays outside the lock (same as other drivers).
- **Red flags:** None.

---

## PHASE 3: GIT HISTORY INVESTIGATION

### Step 3.1: Blame
**Record:**
- Buggy `pci_stop_root_bus`/`pci_remove_root_bus` calls introduced in
`ec15c4d0d5d2e` (Ley Foon Tan, 2019-04-24).
- Function signature updated in `3a610560aa4fc` (2023) — void remove
callback; lock omission unchanged.

### Step 3.2: Fixes: tag
**Record:** N/A — no Fixes: tag.

### Step 3.3: Related file history
**Record:**
- Part of 9-patch series `[PATCH 0/9] PCI: controller: Add missing
rescan lock around root bus removal` (Hans Zhang, May 2026).
- Cover letter: **"Each patch is independent."**
- Merged to mainline as `a8759c8ac48c0` via `7c97ee7c4951a` (Merge
branch 'pci/controller/rescan_lock').
- Related precedent: `1d59d474e1cb7` "PCI: Hold rescan lock while adding
devices during host probe" — **present in this tree**; documents a
real NULL-deref crash from missing rescan lock.

### Step 3.4: Author context
**Record:** Hans Zhang — active PCI contributor (cadence, dwc capability
search, etc.). Patch reviewed/signed by PCI maintainers.

### Step 3.5: Dependencies
**Record:** None.
- `pci_lock_rescan_remove()` exists since `9d16947b75831` (2014) — **in
this tree**.
- `<linux/pci.h>` already included in `pcie-altera.c`.
- Standalone; applies cleanly to current `pcie-altera.c`.

---

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

### Step 4.1: Original discussion
**Record:**
- `b4 dig -c` failed (commit not in HEAD).
- Local mbox/cover: `20260522_18255117159_pci_controller_add_missing_res
can_lock_around_root_bus_removal.{cover,mbx}`.
- Cover letter explains race with sysfs rescan/hotplug → UAF/crash.
- Triggered by sashiko-bot review of a related cadence patch asking
whether root bus teardown needs the lock.
- Lore fetch blocked (Anubis bot protection) — discussion content taken
from local mbox.

### Step 4.2: Reviewers
**Record:** Signed-off-by Manivannan Sadhasivam and Bjorn Helgaas.
Series sent to linux-pci.

### Step 4.3: Bug report
**Record:** No syzbot, bugzilla, or user crash report for Altera
specifically. Cover letter and `1d59d474e1cb7` provide class-of-bug
evidence in PCI core.

### Step 4.4: Series context
**Record:** Patch 3/9; independent per cover letter. Other drivers in
series (cadence, dwc, brcmstb, etc.) have the same bug pattern.

### Step 4.5: Stable list
**Record:** Not searched (lore blocked). No stable nomination found in
local mbox.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1: Key functions
**Record:** `altera_pcie_remove()` only.

### Step 5.2: Callers
**Record:** Called from platform driver framework on:
- `rmmod` (driver is tristate module since 2019)
- platform device unbind
- Module unload is an explicit design goal for post-boot FPGA
programming.

### Step 5.3: Callees
**Record:** `pci_lock_rescan_remove()`, `pci_stop_root_bus()`,
`pci_remove_root_bus()`, `pci_unlock_rescan_remove()`,
`altera_pcie_irq_teardown()`.

### Step 5.4: Reachability
**Record:**
- Unprivileged users can trigger sysfs PCI rescan
(`/sys/bus/pci/rescan`, per-device `rescan`).
- Root can unload the module (`rmmod`).
- Concurrent rescan + unload is the race window — realistic on FPGA
systems that reload bitstreams.
- **Userspace-reachable rescan path:** yes (with appropriate
privileges).

### Step 5.5: Similar patterns
**Record:** Same missing-lock pattern in cadence, dwc, brcmstb, iproc,
mediatek, rockchip, plda, vmd (series). Already-fixed examples:
aardvark, mvebu, host-common, hyperv, mediatek-gen3.

---

## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE

### Step 6.1: Buggy code present?
**Record:** **Yes.** Current HEAD at lines 1078–1079:

```1073:1081:drivers/pci/controller/pcie-altera.c
static void altera_pcie_remove(struct platform_device *pdev)
{
struct altera_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *bridge =
pci_host_bridge_from_priv(pcie);

pci_stop_root_bus(bridge->bus);
pci_remove_root_bus(bridge->bus);
altera_pcie_irq_teardown(pcie);
}
```

No `pci_lock_rescan_remove()`. Bug present since v4.19-era module
support.

### Step 6.2: Backport complications
**Record:** **Clean apply** — 2-line addition, no conflicts expected.
`git show a8759c8ac48c0` matches current file context.

### Step 6.3: Related fixes already present?
**Record:** `1d59d474e1cb7` (probe-side rescan lock) is in tree. Altera-
specific remove-path fix (`a8759c8ac48c0`) is **not** in tree.

---

## PHASE 7: SUBSYSTEM CONTEXT

### Step 7.1: Subsystem criticality
**Record:** **PERIPHERAL** — `CONFIG_PCIE_ALTERA` host controller for
Altera/Intel FPGA (ARM, ARM64, NIOS2). Not universal, but crash/UAF
severity is high when triggered.

### Step 7.2: Activity
**Record:** Moderately active — recent probe leak fix (`09c43b7b7d29c`),
Agilex support, IRQ domain updates.

---

## PHASE 8: IMPACT AND RISK

### Step 8.1: Who is affected
**Record:** Users with `CONFIG_PCIE_ALTERA` on Altera/Intel FPGA PCIe
platforms who unload/reload the driver while PCI sysfs rescan or hotplug
runs.

### Step 8.2: Trigger conditions
**Record:**
- Concurrent `altera_pcie_remove()` and sysfs `rescan` or `remove` on
the same bus.
- More likely than average because the driver is a module for post-boot
FPGA loading.
- Requires root for module unload; rescan also typically root.
- **Likelihood:** uncommon but realistic on target hardware.

### Step 8.3: Failure mode severity
**Record:** **HIGH** — UAF and kernel crash (per commit message and PCI
subsystem precedent in `1d59d474e1cb7`).

### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** Prevents crash/UAF on supported FPGA platforms during
driver teardown.
- **Risk:** Very low — 2 lines, established pattern, no behavior change
beyond serialization.
- **Ratio:** Favorable for backport.

---

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: Evidence summary

**FOR:**
- Real synchronization bug with documented PCI class-of-crash precedent
- UAF/crash failure mode
- Minimal, obviously correct fix matching multiple peer drivers
- Bug present in this tree since 2019
- No dependencies; clean apply
- Maintainer-reviewed (Helgaas, Sadhasivam)
- Driver explicitly supports module unload scenarios

**AGAINST:**
- No Altera-specific crash report or syzbot hit
- Niche driver (`CONFIG_PCIE_ALTERA`)
- Race needs concurrent unload + rescan

**UNRESOLVED:**
- Lore thread not readable (bot protection); relied on local mbox
- No independent runtime test evidence for Altera specifically

### Step 9.2: Stable rules checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — matches established PCI
pattern; maintainer-reviewed |
| 2. Fixes real bug affecting users? | **PASS** — race on module unload
vs sysfs rescan |
| 3. Important issue? | **PASS** — UAF/crash (HIGH severity) |
| 4. Small and contained? | **PASS** — 2 lines, one function |
| 5. No new features/APIs? | **PASS** — synchronization only |
| 6. Can apply to local tree? | **PASS** — clean apply, APIs present |

### Step 9.3: Exception categories
**Record:** None (not device ID, quirk, DT, build, or docs). Standard
race-condition fix.

### Step 9.4: Decision rationale
This is a missing-lock race in root bus teardown — the same class of bug
that caused a documented crash in `1d59d474e1cb7`, already in 6.18.y.
The Altera driver has lacked this protection since module support was
added in 2019. The fix is trivial, follows peer drivers, and prevents
UAF/crash on FPGA platforms where module reload is an intended use case.
Niche scope is offset by high severity and very low backport risk.

---

## Verification

- **[Phase 1]** `git show a8759c8ac48c0`: parsed subject, tags, body
- **[Phase 1]** Local mbox/cover: series context, bot review,
independent patches
- **[Phase 2]** Diff: +2 lines in `altera_pcie_remove()`
- **[Phase 2]** `drivers/pci/remove.c:143`:
`lockdep_assert_held(&pci_rescan_remove_lock)` on bus removal helpers
- **[Phase 2]** `drivers/pci/pci-sysfs.c:470,504,539`: sysfs rescan
holds same lock
- **[Phase 3]** `git blame -L 1073,1081`: bug from `ec15c4d0d5d2e`
(2019)
- **[Phase 3]** `git show 9d16947b75831`: lock API since 2014
- **[Phase 3]** `git show 1d59d474e1cb7`: related crash from missing
lock; in tree
- **[Phase 3]** `git log master --grep="Protect root bus removal"`: fix
`a8759c8ac48c0` on mainline
- **[Phase 3]** `git merge-base --is-ancestor a8759c8ac48c0 HEAD`: fix
NOT in HEAD
- **[Phase 4]** `b4 dig`: failed; used local mbox instead
- **[Phase 4]** WebFetch lore: blocked by Anubis
- **[Phase 5]** `grep pci_lock_rescan_remove drivers/pci/controller/`:
peer drivers use same pattern
- **[Phase 5]** `Kconfig`: `PCIE_ALTERA` tristate, ARM/ARM64/NIOS2
- **[Phase 6]** `git describe HEAD`: v6.18.44
- **[Phase 6]** Read `pcie-altera.c:1073-1081`: buggy code confirmed in
HEAD
- **[Phase 6]** `git show master:.../pcie-altera.c`: fix confirmed on
mainline
- **[Phase 8]** `ec15c4d0d5d2e` commit message: module support for post-
boot FPGA load

**YES**The background checks finished and match what we already
concluded:

- **Altera history:** `pcie-altera.c` has never used
`pci_lock_rescan_remove()`; the missing lock goes back to the 2019
module-support commit. The lock API itself has been in the tree since
2014.
- **Mainline status:** The fix landed on `master` via merge
`7c97ee7c4951a` (`PCI: altera: Protect root bus removal with rescan
lock`, `a8759c8ac48c0`). It is **not** in your current `v6.18.44`
checkout.

**Verdict remains YES** for backporting to this 6.18.y tree — small,
obviously correct race fix with crash/UAF potential, and it should apply
cleanly.

drivers/pci/controller/pcie-altera.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
index 76f3823d96139..8ef56e2fabcfb 100644
--- a/drivers/pci/controller/pcie-altera.c
+++ b/drivers/pci/controller/pcie-altera.c
@@ -1075,8 +1075,10 @@ static void altera_pcie_remove(struct platform_device *pdev)
struct altera_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);

+ pci_lock_rescan_remove();
pci_stop_root_bus(bridge->bus);
pci_remove_root_bus(bridge->bus);
+ pci_unlock_rescan_remove();
altera_pcie_irq_teardown(pcie);
}

--
2.53.0