DF-4390 / verdict.json
{ "finding_id": "DF-4390", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Statically confirmed NULL-dereference in mfi_tbolt_send_frame(): for MFI_CMD_PD_SCSI_IO frames whose CDB[0] is READ_10(0x28)/WRITE_10(0x2A) the function prints DJA NA XXX SYSPDIO (mfi_tbolt.c:1166-1167), leaves req_desc == NULL (init at 1140), and dereferences req_desc->words when posting (1181-1182) - guaranteed kernel panic on every Thunderbolt controller. Three live triggers: (1) every read/write bio to a system PD (mfi_build_syspdio, mfi.c:1992-2001, builds exactly this frame; TBOLT cards are all SKINNY so mfi_syspdprobe attaches JBOD devices, mfi_pci.c:119-149 + mfi.c:1205-1206), (2) crash dumps to a system PD (mfi_dump_syspd_blocks, mfi.c:2453-2461), (3) a single MFIIO_PASSTHRU ioctl with cmd=0x02 and mbox[4]=0x28 (aliases pass.cdb[0]; user frame copied verbatim at mfi.c:2838; /dev/mfi0 is root:operator 0640). Runtime reproduction was impossible on this audit guest: DragonFly 6.5-DEVELOPMENT X86_64_GENERIC has mfi compiled in but the QEMU guest has zero vendor-0x1000 PCI devices, so no /dev/mfi0 exists and mfi_tbolt_send_frame() never executes; QEMUs megasas model (1078/Gen2) cannot emulate the Thunderbolt 2108/2208 path. The trigger compiled and ran on the guest, exiting ENOENT as the hardware-absent proof (run.log, env.txt). Impact field reflects runtime observation only; on real hardware the impact is a reliable local kernel panic (DoS), including automatic boot-time panics on JBOD configurations. Not an exploitation primitive beyond DoS: the only NULL-sourced value is written to the card doorbell, no attacker-controlled index or write.", "exploit_chain": "", "evidence": "VERDICT.md (full line-by-line trace); df4390_trigger.c (trigger, with kernel-ABI mirror structs); run.log + env.txt (guest: mfi in-kernel, no LSI PCI device, ENOENT); fix.diff (git-apply verified on a scratch clone)", "kernel_refs": [ "sys/dev/raid/mfi/mfi_tbolt.c:1140", "sys/dev/raid/mfi/mfi_tbolt.c:1156-1168", "sys/dev/raid/mfi/mfi_tbolt.c:1181-1182", "sys/dev/raid/mfi/mfi.c:1992-2001", "sys/dev/raid/mfi/mfi.c:2453-2461", "sys/dev/raid/mfi/mfi.c:2838" ], "poc_changes": "Seed sketch (none existed - finding is new in pass 2): authored trigger from scratch with layout-accurate packed structs mirroring mfireg.h/mfi_ioctl.h (mfi_dcmd_frame=56B, mfi_ioc_passthru=68B, mbox[4] aliases pass.cdb[0] at frame offset 32); verified it compiles clean with the guest cc and runs.", "attempts": 1, "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": 42, "guest_dirty": 0, "build_cmd": "cc -O -Wall -o /tmp/df4390 /tmp/df4390_trigger.c", "run_cmd": "/tmp/df4390 /dev/mfi0", "code_hash": "4d673e61400512eb7d0ac213fed9e5023fe94711f9db24ea001ef5ed77cbd5a9", "notes": "Hardware-dependent path: requires LSI Thunderbolt (2108/2208) HBA for runtime exercise; QEMU cannot provide one. Static proof is end-to-end and certain. Fix validation impossible for the same reason (fix_status=not_testable); fix.diff verified git-apply clean against the tree and routes the 0x28/0x2A case through mfi_tbolt_build_mpt_cmd() like all other PD passthru, which also makes system-PD I/O and PD crash dumps functional.", "recommended_fix": "Always build the MPT descriptor for MFI_CMD_PD_SCSI_IO (drop the cdb[0]!=0x28/0x2A exclusion in mfi_tbolt_send_frame) so req_desc can never be NULL at the doorbell write.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored and git-apply-verified against sys/dev/raid/mfi/mfi_tbolt.c, but baseline and patched kernels cannot be exercised on this guest (no TBOLT HBA), so behavioral fix validation was not possible.", "fix_evidence": "fix.diff in this pack; scratch-clone git-apply check passed; rationale in VERDICT.md" } |