DF-5355 / verdict.json
{ "finding_id": "DF-5355", "status": "reproduced", "verdict": "REPRODUCED at the verbatim-rig level (3/3 deterministic), upgrading the seeded hand-model verification. The production pccard_function_init (pccard.c:407-503) and the production resource_list family (subr_bus.c:2594-2670) were machine-extracted BYTE-IDENTICAL from the guests /usr/src (sha256 gates 5b610669.../949f75de...; PCCARD_BYTE_IDENTICAL=yes, SUBR_BUS_BYTE_IDENTICAL=yes) and driven through the real entry pccard_attach_card() with a crafted two-CFTABLE_ENTRY CIS: cfe#0 (anywhere range granted at rid 0 -> rle->res set, then fixed 0x3F8 refused by the bridge window) takes the not_this_one path whose purge is #if 0d (pccard.c:499-501), leaving rid-0 busy; cfe#1s fixed 0x200 grant then re-enters resource_list_add for rid 0 and the verbatim panic fires: RIG KERNEL PANIC: resource_list_add: resource entry is busy (subr_bus.c:2631), exit 42. In kernel context: deterministic panic at card insertion/boot. card.error stays 0 (the CIS parses cleanly), so the attach gate at pccard.c:205-212 does not help; every ingredient (entry count, per-entry ranges, sizes) is card-controlled. Kernel entry itself is hardware-gated (no PCMCIA bridge in QEMU, env.txt) -- DF-1040/1041/2319 precedent.", "reproduced": true, "impact": "panic", "confidence": "certain", "exploit_chain": "evil PC Card CIS -> insertion -> pccard_attach_card -> pccard_function_init: cfe#0 partially allocates (first range granted + recorded busy, second range refused) -> not_this_one without unwind (#if 0 purge) -> cfe#1 grants its range -> resource_list_add(rl, SYS_RES_IOPORT, rid=0) finds the busy entry -> panic(resource entry is busy) at subr_bus.c:2631. Deterministic insertion/boot DoS; no privilege boundary crossed. Non-panicking variants (all entries failing mid-way) hold the granted bridge windows until removal.", "evidence": "run.log (decisive baseline: Allocation failed for cfe 0 then RIG KERNEL PANIC: resource_list_add: resource entry is busy, exit 42); fixed_run.log (fix A/B: exit 0, cfe#1 window granted, devadded fires, zero leak); busypanic_pair.log (side-by-side); matrix.log (f5355 flips exactly busypanic; controls green); extract2_manifest.txt (byte-identity); build.log; DF-2318 pack run.log/run.2.log/run.3.log (3/3 determinism); postboot_run.log in DF-2318 pack (combined-fix booted kernel)", "kernel_refs": [ "sys/bus/pccard/pccard.c:425", "sys/bus/pccard/pccard.c:429", "sys/bus/pccard/pccard.c:439", "sys/bus/pccard/pccard.c:443", "sys/bus/pccard/pccard.c:449", "sys/bus/pccard/pccard.c:464", "sys/bus/pccard/pccard.c:483", "sys/bus/pccard/pccard.c:496", "sys/bus/pccard/pccard.c:499", "sys/kern/subr_bus.c:2614", "sys/kern/subr_bus.c:2619", "sys/kern/subr_bus.c:2630", "sys/kern/subr_bus.c:2631", "sys/bus/pccard/pccard_cis.c:1023" ], "poc_changes": "Replaced the seeded hand-written model (preserved in seed_model/) with the verbatim rig: production pccard.c + subr_bus.c + pccard_cis.c code machine-extracted byte-identical and executed through pccard_attach_card. The seeded CIS encoding (little-endian fields, length+1 semantics) carried over unchanged and worked first try in the rig. The SEEDED fix.diff was buggy: its unwind called resource_list_delete without clearing rle->res and itself panicked (resource_list_delete: resource has not been released, first matrix run); corrected fix adds trle->res = NULL (mirroring pccard_function_free at pccard.c:534) and now validates clean.", "attempts": 9, "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": 12, "guest_dirty": 0, "build_cmd": "sh build.sh (= sh extract2.sh extracted /usr/src/sys && cc -O2 -g -Wall -I extracted -o rig2 rig2_main.c)", "run_cmd": "./rig2 busypanic (baseline success = RIG KERNEL PANIC: resource entry is busy + exit 42; fixed build = exit 0)", "code_hash": "6746055beafbffae93e5758ec0373a40694ee704e9b4ebcd1915ea7e4d82b658", "notes": "No PCMCIA hardware in QEMU (env.txt); rig proves the exact shipped codes behavior, combined-fix kernel build/boot proves compile+boot. Same defect shape exists in the mem branch (pccard.c:452-474) and irq branch (rid fixed 0, :479-492) -- the fix unwinds all of them since it walks the whole rl.", "recommended_fix": "Unwind partial allocations at not_this_one: for each busy rl entry, bus_release_resource + rle->res = NULL + resource_list_delete (restart scan after each mutation), removing both the busy-panic and the per-failed-entry window hold.", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "VALIDATED. (1) Single-fix rig A/B (matrix.log, fixed_run.log): busypanic exits 0, cfe#1 allocates 0x200 cleanly, function attaches (devadded pnpinfo printed), io-windows-held=1, zero leak; all six other scenarios unchanged incl. negative controls. The originally-seeded fix.diff FAILED validation (resource_list_delete panic for uncleared res) and was corrected with trle->res = NULL before it passed. (2) Combined three-fix kernel: -Werror nativekernel rc=0, installkernel rc=0, booted kernel #1; rig re-extracted from the RUNNING kernels patched source and re-driven: busypanic clean (postboot_run.log). In-kernel behavioral test impossible (no PCMCIA bridge).", "fix_evidence": "fix.diff; fixed_run.log; busypanic_pair.log; matrix.log; postboot_extract_manifest.txt + postboot_run.log + kernel_apply.log + kernel_build.tail.log (in DF-2318 pack)" } |