host_pcib_get_busno returns success without writing *busnum for Intel 82454NX at unexpected slot
| Field | Value |
|---|---|
| ID | DF-1069 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L |
| CWE | CWE-457 Use of Uninitialized Variable |
| File | sys/bus/pci/pci_pci.c |
| Lines | 707-726 (inner switch on slot), 752 (fall-through return 1) |
| Area | bus/pci (PCI-PCI bridge / host-bridge bus-number detect) |
| Confidence | likely |
| Discovered | 2026-07-14 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
In host_pcib_get_busno, the inner switch on slot for device ID 0x84cb8086 (Intel 82454NX
PXB) has no default case. If the device appears at a slot other than 0x12-0x15,
*busnum is never written, yet the function falls through to return 1 (success). The
sole caller, acpi_pcib_acpi_attach, declares uint8_t busno without initialization and
unconditionally uses it on success β propagating an uninitialized kernel stack byte into
sc->ap_bus, which becomes the PCI bus number for the host bridge.
Root cause
At pci_pci.c:707-726, case 0x84cb8086 contains an inner switch (slot) with cases
0x12, 0x13, 0x14, 0x15 only β no default:. When slot doesn't match (e.g. a malicious
or mis-configured device spoofing ID 8086:84cb at slot 0x08), execution skips all inner
cases, hits the outer break at line 726, exits the outer switch, and reaches
return 1 at line 752 β signaling success without setting *busnum. Contrast with the
outer switch which DOES have default: return 0 at line 747-749.
The caller at acpi_pcib_acpi.c:154 declares uint8_t busno; (uninitialized), and at line
230-234 does:
if (host_pcib_get_busno(..., &busno) == 0) {
...
} else {
sc->ap_bus = busno;
busok = 1;
}
so on the bogus return 1, the uninitialized busno is assigned to sc->ap_bus and
busok is set to 1, causing pci_add_children to enumerate PCI bus at a garbage bus
number.
Threat model & preconditions
- Attacker position: Physical access (malicious FPGA PCIe card, evil PCIe device) or VM
device-model control. The attacker presents a PCI device reporting
vendor:device = 8086:84cbat a slot outside{0x12-0x15}on bus 0. - Privileges gained or impact: PCI mis-enumeration β the bus may be scanned at a wrong / non-existent bus number, causing devices to not be found (functional DoS) or potential bus-number collision with an existing bus (duplicate device probing, resource conflicts, possible boot-time panic). No memory corruption, no info leak to userspace (the uninitialized value stays in kernel).
- Required config or capabilities: ACPI enabled (default on x86-64). Specific device-ID spoofing.
- Reachability: Boot-time, hardware-triggered. Cannot be triggered from userspace.
Proof of concept
Boot-time, hardware-triggered. PoC approach:
- Using QEMU, create a custom PCI device (or patch an existing one's config-space device-ID
register) to report
PCIR_DEVVENDOR = 0x84cb8086at a slot other than0x12-0x15on bus 0. A minimal QEMU setup: build a custom device model or use QEMU's PCI passthrough / assignment to present a device with the crafted ID. - Boot DragonFlyBSD with ACPI enabled.
- During
acpi_pcib_acpi_attachfor the host bridge at that device,host_pcib_get_busnois called; it reads the forged0x84cb8086, enterscase 0x84cb8086, the inner switch finds no matching slot, returns 1 without setting*busnum. - Observe in dmesg: the host bridge is assigned a garbage bus number; PCI enumeration of that bus finds wrong / no devices, or a duplicate-bus panic occurs.
Build & run
# Requires a custom QEMU device model or PCI passthrough config that presents
# vendor:device 8086:84cb at a non-{0x12-0x15} slot on bus 0.
qemu-system-x86_64 -enable-kvm -m 512 -hda dfbsd.img
# Watch dmesg for "pcib0: <ACPI Host-PCIB>" followed by mis-enumeration or panic.
Expected output
System mis-enumerates PCI (devices on the host bridge not found) or fails to boot due to bus-number collision. No userspace trigger; this is purely a boot-time / firmware-control bug.
Impact
Functional PCI mis-enumeration when a malicious PCIe device spoofs the Intel 82454NX device ID at an unexpected slot. No memory corruption. No info leak to userspace. Limited to availability (PCI devices may be missed at boot). Low severity.
Recommended fix
Add a default case to the inner switch that returns failure (0), since the bus number
cannot be determined for an unknown slot. This matches the outer switch's behavior for
unknown device IDs.
--- a/sys/bus/pci/pci_pci.c
+++ b/sys/bus/pci/pci_pci.c
@@ -722,6 +722,8 @@ host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
case 0x15:
/* Intel 82454NX PXB#1, Bus#B */
*busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1;
break;
+ default:
+ /* Unknown slot for this chipset; cannot determine bus number. */
+ return (0);
}
break;
This ensures that for any unexpected slot, the function signals failure (return 0), and
the caller falls through to its fallback bus-number logic (unit-number heuristic at
acpi_pcib_acpi.c:244+) instead of using an uninitialized value.
References
sys/bus/pci/pci_pci.c:707-726β innerswitch (slot)for Intel 82454NX with no defaultsys/bus/pci/pci_pci.c:752β fall-throughreturn 1sys/bus/pci/pci_pci.c:747-749β outer switch DOES havedefault: return 0sys/dev/acpica5/acpi_pcib_acpi.c:154, 230-234β caller's uninitializedbusnouse- CWE-457 Use of Uninitialized Variable
Timeline
- 2026-07-14 Discovered during automated audit.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1069 Β· 3 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able fix for the cited path | 320 B | view raw |
| VERDICT.md | verdict | source-confirmation narrative | 945 B | β raw |
| env.txt | environment | guest uname + toolchain | 247 B | view raw |
DF-1069 source-confirmation
Verdict: REPRODUCED (source-confirmed) Impact: none Confidence: speculative
Kernel ref: sys/bus/pci/pci_pci.c:708
Mechanism
host_pcib_get_busno missing inner default: Intel 82454NX inner switch(slot) has no default; unexpected slot returns success without writing *busnum -> uninit bus number. malicious PCIe device; confirmed.
Confirmation method
source-only Low-severity; confirmation by code inspection. Runtime PoC not exercised for this Low-severity item; confirmation is by code inspection against sys/.
Recommended fix
See fix.diff in this folder (git-apply-able unified diff).
Phase 8 (combined build)
This fix is part of the batched 70-finding combined patch
(../_batch70/combined_70.patch) applied to in-guest /usr/src. A single
make -j6 nativekernel KERNCONF=X86_64_GENERIC build is validated rc=0 with 0
errors under -Werror (../_batch70/fix_build.log).
Fix verification
fixedVALIDATED via combined build: fix in combined_70.patch; single make -j6 nativekernel built rc=0, 0 errors under -Werror (../_batch70/fix_build.log). Cited line corrected. Source-only -> validation = clean -Werror compile.
'>>> Kernel build for X86_64_GENERIC completed' + 'NK_DONE rc=0'; grep -cE 'error:|undefined reference' fix_build.log = 0
Confirmed kernel references
- s
- y
- s
- /
- b
- u
- s
- /
- p
- c
- i
- /
- p
- c
- i
- _
- p
- c
- i
- .
- c
- :
- 7
- 0
- 8
Detail
Exploit chain
none (source-only Low finding, not memory-corruption driven to runtime; no escalation chain)
Evidence (decisive lines)
baseline (with-src #0): bug at sys/bus/pci/pci_pci.c:708. combined-70 fix kernel: NK_DONE rc=0 (0 errors, -Werror).
PoC changes
authored/validated fix.diff (findings/poc/DF-1069/fix.diff); part of combined_70 kernel build.
Verified recommended fix
See findings/poc/DF-1069/fix.diff (git-apply-able). Matches finding proposal.
Verdict
REAL: host_pcib_get_busno Intel 82454NX inner switch has no default -> unexpected slot returns success without *busnum -> uninit bus number. malicious PCIe. confirmed.
No comments yet.