⬢ DragonFlyBSD Kernel Audit
DF-4390 / verdict.json
← back to finding ↓ download raw
{
  "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"
}