DF-5454 / verdict.json
{ "finding_id": "DF-5454", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "The legacy host-PCI config bridges in sys/bus/pci/x86_64/pci_bus.c:61-75 forward caller-supplied (reg,bytes) with no validation into the PCIe MMIO backend pciereg_cfgread/cfgwrite (pci_cfgreg.c:315-365), which checks only reg>4095 and never reg+bytes<=4096 nor alignment (the port-I/O backend pci_cfgenable at pci_cfgreg.c:187-193 checks both). A 2-byte access at reg=0xfff on (bus=pcie_maxbus,slot=31,func=7) reads/writes 1-3 bytes past the 256MB pmap_mapdev_uncacheable MMCFG kernel_map allocation. Proven live on the QEMU guest with a KLD that makes the same legal pcie_cfgregopen() call ACPI MCFG handling makes at boot (acpi.c:1669; the i440FX guest boots with the MMIO backend dormant): control read at reg=0xffc/4 succeeds, read at reg=0xfff/2 panics instantly (Fatal trap 12, supervisor read, fault VA exactly pcie_base+0x10000000, stopped at the inlined volatile uint16_t load in pci_docfgregread+0xb4). Root-gated: the only attacker-regulated path, /dev/pci PCIOCREAD/PCIOCWRITE, validates width/alignment but no upper bound on pi_reg, yet /dev/pci open requires SYSCAP_RESTRICTEDROOT (pci_user.c:82). Impact ceiling for the (already-privileged) trigger: reliable kernel panic plus a 1-3 byte OOB write into the kernel_map neighbor of the MMCFG window. No unprivileged chain exists. fix.diff (carry width/alignment/end-bound into the MMIO backend) validated end-to-end: patched kernel rejects all OOB accesses (0xffffffff / silent no-op), control read unaffected, guest stays up.", "exploit_chain": "", "evidence": "panic.txt (Fatal trap 12, fault VA 0xfffff80128660000 == pcie_base+256MB, stopped at pci_docfgregread+0xb4 movzwl); run.log (baseline: control read 0xffc/4 ok then step2 panic); run_patched.log (same PoC on fix.diff kernel: step2 returns 0xffffffff rejected, KLDLOAD_RC=0, guest up); df5454.c (PoC source); fix.diff (validated fix); env.txt (guest 6.5-DEVELOPMENT X86_64_GENERIC, i440FX, no MCFG line in dmesg)", "kernel_refs": [ "sys/bus/pci/x86_64/pci_bus.c:61-66", "sys/bus/pci/x86_64/pci_bus.c:70-75", "sys/bus/pci/x86_64/pci_cfgreg.c:315-340", "sys/bus/pci/x86_64/pci_cfgreg.c:342-365", "sys/bus/pci/x86_64/pci_cfgreg.c:278-279", "sys/bus/pci/x86_64/pci_cfgreg.c:187-193", "sys/bus/pci/pci_user.c:602-673", "sys/bus/pci/pci_user.c:75-91", "sys/dev/acpica/acpi.c:1669", "sys/platform/pc64/x86_64/pmap.c:6174-6217" ], "poc_changes": "authored fresh (no seed pack existed): KLD performs the legal pcie_cfgregopen() call ACPI MCFG makes at boot to activate the dormant CFGMECH_PCIE backend on the i440FX guest, then issues control (0xffc/4) and OOB (0xfff/2, 0xfff/2 write, 0xffd/4) config accesses via the exported pci_cfgregread/write", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 26, "guest_dirty": 0, "build_cmd": "cd /root/df5454 && make SYSDIR=/usr/src/sys (see build.sh)", "run_cmd": "kldload /root/df5454/df5454.ko (see run.sh)", "code_hash": "83a4c8a5b4679b552b097a9b9cdfbf4d8096167eeaa38e928c198bc2ef01cee8", "notes": "Finding filed against pci_bus.c (the pass-through bridges, this files audit); sink+fix in sibling pci_cfgreg.c which pass 1 marked clean. Root-gated (SYSCAP_RESTRICTEDROOT on /dev/pci open; KLD trigger needs root too), CFGMECH_PCIE precondition (MCFG hardware). Fix cycle: first buildkernel attempt failed (no built world in with-src snapshot -> buildworld before buildkernel); used make nativekernel instead (BUILD_RC=0, INSTALL_RC=0), rebooted into kernel #1 Oct 5 18:56. Guest reset to with-src afterwards. No unprivileged uid=0 chain: trigger requires root; impact = privileged DoS/panic + 1-3 byte OOB write into adjacent kernel_map mapping.", "recommended_fix": "In pciereg_cfgread/pciereg_cfgwrite (pci_cfgreg.c) require bytes in {1,2,4}, reg aligned to bytes, and reg+bytes <= PCIE_REGMAX+1 \u2014 same policy the mech-1 backend pci_cfgenable already enforces.", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff applied to guest /usr/src (patch -p1, hunks at 320/348), kernel rebuilt with make nativekernel KERNCONF=X86_64_GENERIC and installed (BUILD_RC=0, INSTALL_RC=0), rebooted, exact same PoC re-run: control read unaffected, all OOB accesses rejected (0xffffffff / no-op), KLDLOAD_RC=0, no panic, guest stayed up. Baseline (unpatched) panicked at the same step. Bad behavior gone.", "fix_evidence": "fix.diff; fix_build.log (BUILD_RC=0 / INSTALL_RC=0, kernel #1: Mon Oct 5 18:56:47 2026); run_patched.log (rejected OOB accesses, guest alive); panic.txt + run.log (baseline panic)" } |