DF-3631 / verdict.json
{ "finding_id": "DF-3631", "status": "inconclusive", "reproduced": 0, "poc_path": "findings/poc/DF-3631", "artifact_dir": "findings/poc/DF-3631", "build_cmd": "cc -O2 -Wall -o tlv_underflow tlv_underflow.c", "run_cmd": "./tlv_underflow A; ./tlv_underflow B", "code_hash": "02d55afb43914525eed1cad9ce396e95d80805eec954c42eb9935c3d787acbd0", "build_log": "build.log", "run_log": "run.log", "impact": "none", "confidence": "certain", "verdict": "iwm_read_firmware()s TLV walk subtracts roundup2(tlv_len,4) from size_t len after only checking len >= tlv_len (if_iwm.c:630-638): a final TLV with unaligned length ending at the image end underflows len to ~SIZE_MAX and the parser keeps reading TLV headers past the firmware image; a file shorter than the 88-byte header underflows len immediately (:620) and the magic check dereferences 4 bytes with no size check (:607). Reproduced at logic level ON THE GUEST with a verbatim userland port of the exact loop: case A (SEC_RT len=5 at image end) prints len=0xfffffffffffffffd then SIGSEGV on the guard page, case B (40-byte file) SIGSEGVs (run.log); the fix arithmetic (len < roundup2(tlv_len,4) + header-size guard) returns clean errors, exit 0 (run_fixed.log). Kernel path itself not exercisable: no iwm PCI device on the guest to bind the driver and load a firmware file (env.txt).", "exploit_chain": "crafted firmware file -> firmware_get() at attach -> TLV walk underflow -> OOB TLV parse -> (e.g.) IWM_UCODE_TLV_SEC_RT with garbage header stored as fw section pointing outside the image -> iwm_pcie_load_section() memcpy+DMA of out-of-image memory (if_iwm.c:2427) -> kernel heap disclosure to device / crash. Precondition: root-installed or supply-chain firmware file.", "evidence": "run.log (both cases SIGSEGV exit 139, len wrap visible: 0xfffffffffffffffd); run_fixed.log (both cases clean, exit 0); tlv_underflow.c / tlv_underflow_fixed.c (verbatim port + fixed variant); build.log; env.txt; VERDICT.md", "kernel_refs": [ "sys/dev/netif/iwm/if_iwm.c:607", "sys/dev/netif/iwm/if_iwm.c:620", "sys/dev/netif/iwm/if_iwm.c:630", "sys/dev/netif/iwm/if_iwm.c:637", "sys/dev/netif/iwm/if_iwm.c:638", "sys/dev/netif/iwm/if_iwm.c:2427" ], "poc_changes": "PoC authored from scratch in verify phase (no seed): verbatim port of the :619-638 loop with structs/constants from if_iwmreg.h; guard-page placement to turn the OOB walk into a deterministic fault", "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": 120, "guest_dirty": 0, "notes": "iwm module loads on guest (kldload if_iwm) but attaches to no device: pciconf shows no Intel Wireless NIC, no wlan interface appears. Verification is source-level (plus the DF-3631 logic-level harness).", "recommended_fix": "fix.diff (header-size guard + padded-length check) applies cleanly to sys/dev/netif/iwm/if_iwm.c", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "fix.diff (header-size guard + padded-length check) applies cleanly to sys/dev/netif/iwm/if_iwm.c; validated at ported-logic level on the guest: baseline harness crashes (run.log), fixed arithmetic exits 0 (run_fixed.log). In-kernel build validation impossible - no iwm device on guest.", "fix_evidence": "run.log vs run_fixed.log + fix.diff (patch --dry-run clean against sys/dev/netif/iwm/if_iwm.c)" } |