⬢ DragonFlyBSD Kernel Audit
DF-4964 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4964",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "sili_pci_attach() maps BAR(2) and sili_port_alloc() carves per-port subregions at 8192*port with no validation against the mapped window size (bus_space_subregion is unchecked pointer arithmetic), so a SiI 3124/3132 decoding an undersized BAR(2) drives OOB MMIO reads/writes past the pmap-mapped window. Reproduced on the guest by driving the kernels own sili_port_alloc(sc,3) against a 4KB window: canary mode proved silent OOB writes at +0x7014/+0x7000 (values 0xfff/0x1 read back), panic mode produced Fatal trap 12 at sili_port_alloc+0x360 (movl $0xfff,0x1014(%rdx), fault VA exactly fake_bar+0x7014) and killed the guest. Crafted-hardware precondition, so uid0 escalation is not realistic (offsets device-constrained, values fixed constants, targets device-adjacent KVA); impact ceiling is boot/kldload panic or silent corruption of adjacent mappings. fix.diff (bounds-check rman_get_size(sc_pregs) in sili_port_alloc) validated on a rebuilt kernel: both modes return EINVAL with canaries untouched and no panic.",
  "exploit_chain": "crafted/malfunctioning SiI3124/3132 (or emulated) PCIe device decodes BAR(2) < nports*8KB -> sili_pci_attach maps it -> sili_port_alloc subregions port at 8192*port unvalidated -> first sili_pwrite(INT_DISABLE) at +0x1014 past port base writes outside the mapped window -> adjacent KVA mapped: silent corruption (canary-proven); adjacent KVA unmapped: Fatal trap 12 kernel panic at attach/kldload (guest dies, db> prompt).",
  "evidence": "panic.txt (Fatal trap 12, fault VA 0xfffff80118c67014 = fake_bar+0x7014, Stopped at sili_port_alloc+0x360: movl $0xfff,0x1014(%rdx)); run.log (canary mode: canary@+0x7014 after=00000fff, canary@+0x7000 after=00000001 -> OOB writes proven, guest alive); run.2.log (patched kernel: port regs window too small for port 3, rc=22, canaries deadbeef/cafebabe untouched, panic-mode target never touched, guest up); fix.diff (rman_get_size bounds check in sili_port_alloc); VERDICT.md for the full narrative",
  "kernel_refs": [
    "sys/dev/disk/sili/sili_attach.c:170",
    "sys/dev/disk/sili/sili_attach.c:253",
    "sys/dev/disk/sili/sili_attach.c:267",
    "sys/dev/disk/sili/sili.c:156",
    "sys/dev/disk/sili/sili.c:173",
    "sys/dev/disk/sili/sili.c:185",
    "sys/cpu/x86_64/include/bus_dma.h:78"
  ],
  "poc_changes": "Rewrote the seeded concept into a dual-mode kld module: canary mode (real 64KB pmap_mapdev backing + fake 4KB BAR resource; canary readback proves the silent OOB write on any KVA layout) and panic mode (fake BAR parked in a kmem_alloc/kmem_freed, pmap_extract-verified unmapped hole -> deterministic Fatal trap 12). Fixed module build against the guest tree (generated bus_if/device_if/pci_if/opt_cam/pcidevs headers, no MODULE_DEPEND since sili lacks MODULE_VERSION), fake struct resource for the patched check, real DMA tags + leaked softc for the port-thread path, and worked around DFly pmap_extracts no-frame return for cleared PTEs.",
  "attempts": 4,
  "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 (baseline); fix validation on #1: Fri Sep 25 12:08:33 UTC 2026",
  "runtime_sec": 3600,
  "guest_dirty": 0,
  "build_cmd": "make -C /root/df4964 (kld module against /usr/src; sili compiled into X86_64_GENERIC); fix: patch -p1 < fix.diff && make -j6 quickkernel KERNCONF=X86_64_GENERIC && make installkernel",
  "run_cmd": "kldload /root/df4964/df4964.ko            (canary mode); kenv df4964.panic=1; kldload /root/df4964/df4964.ko   (panic mode)",
  "code_hash": "dfcb214e110f85d68194a8d4880b97b4311cb90ab47e62f9f5bc28dcc97ee784",
  "notes": "Guest reset to clean-source snapshot after the run. Incidental observation for future audit: sys/platform/pc64/x86_64/pmap.c:1739 pmap_extract() tests *pt (PT pointer) instead of *ptep for PG_V, so a cleared kernel PTE with a present PT yields a bogus physical address of va&PAGE_MASK for callers.",
  "recommended_fix": "In sili_port_alloc(), reject ports whose subregion exceeds the mapped port-register window: if (sc->sc_pregs == NULL || rman_get_size(sc->sc_pregs) < SILI_PORT_REGION(port) + SILI_PORT_SIZE) return (EINVAL); (see fix.diff)",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Baseline unpatched kernel: canary mode clobbered both canaries with the drivers register constants and panic mode took Fatal trap 12 at sili_port_alloc+0x360 killing the guest. Patched kernel (quickkernel rebuilt with fix.diff, #1 Sep 25 12:08 build): both modes print pci0: port regs window too small for port 3, sili_port_alloc returns EINVAL(22) before any MMIO, canaries read deadbeef/cafebabe untouched, and the previously-fatal unmapped-hole target is never accessed - guest stays up.",
  "fix_evidence": "run.2.log (patched canary + patched panic-mode runs with uptime shown); fix_build.log (kernel build/install completion); panic.txt (baseline panic); run.log (baseline canary corruption)"
}