⬢ DragonFlyBSD Kernel Audit
DF-5361 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5361",
  "status": "reproduced",
  "verdict": "REPRODUCED at the verbatim-rig level on the DragonFly guest; kernel entry hardware-gated (no PCMCIA bridge). The verbatim CISTPL_END MFC reset (pccard_cis.c:635-649) kfrees the pccard_function structs (:641) and reinits pf_head (:644) but never drains pf->cfe_head, orphaning every pccard_config_entry the CFTABLE handler kmallocd and STAILQ_INSERT_TAILd (:908-917). The rigs instrumented ledger on the verbatim parser: a terminating CONFIG+CFTABLE+CFTABLE+MFC+END card returns normally with alloc cfe=2, kfree cfe=0, LIVE cfe=2 (2 x 160 B = 320 B leaked per insertion), exactly upgrading the seeded models numbers to the production code. The benign scenario proves the real-world case: a fully VALID two-function MFC card leaks its pre-MFC cfe on every insertion (pccard.c:195 attach path; pccard_detach_card :317-324 can only free what is still linked). Combined with the DF-5362 chain cycle the leakloop scenario shows unbounded growth (+1 cfe per 22 bus reads; 4545 LIVE cfes at read-budget 100k, 9090 at 200k -- exactly linear, and the kernel has no budget). Fix validated: single-fix rig A/B (LIVE cfe=0; benign keeps exactly its two functions entries) and the combined-five-fix kernel built -Werror, booted, and the rig re-driven from the running kernels patched source: alloc cfe=2 kfree cfe=2 LIVE cfe=0.",
  "reproduced": true,
  "impact": "leak",
  "confidence": "certain",
  "exploit_chain": "evil (or even valid MFC) card -> pccard_attach_card -> pccard_read_cis -> CISTPL_CONFIG allocs pf, CISTPL_CFTABLE_ENTRY allocs cfes onto pf->cfe_head, CISTPL_LONGLINK_MFC sets gotmfc=1, CISTPL_END reset kfrees the pf structs but not their cfe chains -> permanent kmalloc(M_DEVBUF) leak, N x 160 B per insertion; repeat per insert/eject, or loop with DF-5362 for unbounded heap exhaustion",
  "evidence": "run.log (mfcleak: alloc cfe=2 pf=1 | kfree cfe=0 pf=1 | LIVE cfe=2; benign valid card LIVE cfe=3 with 1 orphaned); fixed_run.log (f5361: LIVE cfe=0, benign LIVE cfe=2); matrix.log (only f5361 flips); postboot_run.log (alloc cfe=2 ... kfree cfe=2 ... LIVE cfe=0)",
  "kernel_refs": [
    "sys/bus/pccard/pccard_cis.c:635",
    "sys/bus/pccard/pccard_cis.c:638",
    "sys/bus/pccard/pccard_cis.c:641",
    "sys/bus/pccard/pccard_cis.c:644",
    "sys/bus/pccard/pccard_cis.c:908",
    "sys/bus/pccard/pccard_cis.c:909",
    "sys/bus/pccard/pccard_cis.c:916",
    "sys/bus/pccard/pccard.c:195",
    "sys/bus/pccard/pccard.c:317"
  ],
  "poc_changes": "Upgraded the seeded hand-written model (poc_pccard_cis2.c, kept for history) to the machine-extracted verbatim rig; the ledger reproduces the seeded models numbers on the production code (allocs=2 frees=0) and adds the benign-card real-world case.",
  "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",
  "runtime_sec": 1100,
  "guest_dirty": 0,
  "build_cmd": "sh extract.sh . && cc -O2 -Wall -o rig rig_main.c",
  "run_cmd": "./rig mfcleak && ./rig benign   (A/B: sh run_matrix.sh)",
  "code_hash": "908c166959ac485b7dadf00c66e9ec963ba421de027b157ddc056f2ed3837319",
  "notes": "Verbatim-rig standard (orchestrator-approved method for this hardware-gated parser; DF-1040/1041 precedent): the compiled parser text is the guests own /usr/src production code, sha256-gated at extraction (extract_manifest.txt). Kernel entry unreachable on this guest: no PCMCIA bridge, no /dev/pccard*, no pccardc (env.txt) -- impact statements are the in-kernel consequences of the demonstrated production-code behavior. Deterministic across two independent boots (identical matrix). Guest left up and clean on the with-src snapshot; pristine pccard_cis.c sha256 acdd2484... re-verified after reset. Incidental: poweroff of the freshly-installed test kernel #1 required a QEMU kill on both takes (no panic trace in the serial console; stock kernel shuts down cleanly) -- VM artifact, not a parser finding.",
  "recommended_fix": "Drain pf->cfe_head (STAILQ_REMOVE_HEAD + kfree) before kfree(pf) in the MFC reset, mirroring pccard_detach_card pccard.c:317-324.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "VALIDATED. (1) Single-fix rig A/B: drain-before-kfree in the reset -> mfcleak LIVE cfe=0 (kfree cfe=2), benign card keeps exactly its two live functions entries; identical to the pccard.c:317-324 teardown semantics. (2) Combined five-fix kernel build+boot+running-source re-run: LIVE cfe=0 on every scenario.",
  "fix_evidence": "fix.diff; fixed_run.log; matrix.log (single-fix A/B); kernel_apply.log + kernel_build.tail.log + env.txt + postboot_extract_manifest.txt + postboot_run.log (combined-fix kernel build/boot/running-source rerun)"
}