β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-3873

mfi ioctl handlers dereference user ioctl buffers without copyin/copyout -> trap_fatal panic on unmapped args (and kernel writes through raw user pointers)

Summary

DragonFly passes the user ioctl pointer to d_ioctl handlers; mfi_ioctl/mfi_user_command dereference it directly across MFIIO_STATS, MFIIO_QUERY_DISK, MFI_CMD (reads adapter_no and bcopy's the frame), MFI_SET_AEN, and MFIIO_PASSTHRU (reads AND writes through ioc). An unmapped user address makes the kernel fault on a user VA with pcb_on_fault==NULL: 'Fatal user address access from kernel mode' -> panic. The PASSTHRU bcopy write direction additionally writes kernel data to an arbitrary (attacker-chosen, mapped) user address without copyout. The Linux shim cases copyin properly, showing the intended pattern. Single-syscall local kernel panic. Copyin/copyout-each-struct fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3873 Β· 8 files
FileTypeDescriptionSize
README.md β€” 1.4 KB ↓ raw
VERDICT.md β€” 1.1 KB ↓ raw
build.sh β€” 106 B view raw
env.txt β€” 283 B view raw
fix.diff β€” 1019 B view raw
mfi_ioctl_nullderef.c β€” 4.2 KB view raw
run.log β€” 264 B view raw
run.sh β€” 102 B view raw

DF-3873 β€” mfi ioctl handlers dereference user ioctl buffers without copyin -> panic on unmapped args

DragonFly passes the user ioctl data pointer to d_ioctl handlers; drivers must copyin. mfi_ioctl / mfi_user_command dereference it directly:

  • mfi.c:2909-2916 (MFIIO_STATS): ms->ms_item, bcopy to &ms->ms_qstat
  • mfi.c:2928-2943 (MFIIO_QUERY_DISK): reads qd->array_id, writes qd fields
  • mfi.c:2950-2973 (MFI_CMD): ioc->mfi_adapter_no, bcopy(ioc->mfi_frame.raw, ...) and every later ioc->mfi_sgl[...] / ioc->mfi_sense_* access
  • mfi.c:3126-3128 (MFI_SET_AEN): aen->aen_seq_num
  • mfi.c:2818-2867 (MFIIO_PASSTHRU via mfi_user_command): ioc->buf_size, copyin(ioc->buf,...), bcopy(&ioc->ioc_frame,...), bcopy(dcmd,&ioc->ioc_frame,...) β€” the last one also writes through the raw user pointer.

An unmapped user address makes the kernel fault on a user VA with pcb_onfault == NULL: DragonFly trap.c:905-925 prints "Fatal user address access from kernel mode" and calls trap_fatal() -> panic. One ioctl with a garbage arg pointer from any user holding /dev/mfi0 open (operator group). The Linux shim cases (MFI_LINUX_CMD_2 / MFI_LINUX_SET_AEN_2) copyin properly, showing the intended pattern.

Build/run

cc -O2 -o mfi_ioctl_nullderef mfi_ioctl_nullderef.c   # trigger 3 = this finding
./mfi_ioctl_nullderef

Guest has no MegaRAID -> hardware-gated (run.log).

VERDICT.md
↓ download raw

DF-3873 VERDICT β€” inconclusive (hardware-gated), source-certain

  • Verified the direct user-pointer dereferences at the cited lines and the DragonFly fault policy: sys/platform/pc64/x86_64/trap.c:905-925 β€” a kernel-mode fault on a user-range address with no pcb_onfault (i.e. outside copyin/copyout) is fatal ("Fatal user address access from kernel mode").
  • No SMAP on the standard guest/snapshot is irrelevant: the panic comes from the unmapped VA, not from protection.
  • Trigger: ioctl(fd, MFI_CMD, (void*)0x515100001000UL) etc. β€” single syscall.
  • Guest: device absent (run.log); code-level certainty high.
  • fix.diff (illustrative for MFI_CMD; same pattern for the other cases): copyin the packet first, then operate on the kernel copy.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

copyin/copyout the ioctl structs instead of direct dereference

fix.diff
↓ fix.diffper-fix-DF-3873

Confirmed kernel references

Detail

Evidence (decisive lines)

DF-3873/run.log (build OK, device absent) + VERDICT.md line-by-line trace

PoC changes

written fresh; shared trigger binary covers DF-3871 (T1), DF-3872 (T2), DF-3873 (T3)

Verified recommended fix

mfi_ioctl_nullderef.c

Verdict

mfi_ioctl/mfi_user_command dereference the raw user ioctl pointer without copyin (MFIIO_STATS :2909, MFIIO_QUERY_DISK :2928, MFI_CMD :2950-2973 incl. bcopy of mfi_frame.raw, MFI_SET_AEN :3126, MFIIO_PASSTHRU :2818-2867 incl. a bcopy WRITE through the user pointer). An unmapped arg faults in kernel mode with pcb_onfault==NULL: trap.c:905-925 'Fatal user address access from kernel mode' -> trap_fatal -> panic, one syscall, operator-group. Guest has no MegaRAID: hardware-gated, source-certain.