⬢ DragonFlyBSD Kernel Audit
DF-2287 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2287",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "REPRODUCED on the BUSAUDIT kernel with the targsim rig: 2000 deterministically-failing CTIOs (XPT_CONT_TARGET_IO with dxfer_len 1 MiB > MAXPHYS; cam_periph_mapmem rejects at cam_periph.c:702-707, targstart :674-684 parks each descr on abort_queue) followed by 2000 reads drained all descriptors with exact user_ccb pointer matches, while M_TARG grew monotonically across four independent measurement points: 1.95K/156K -> 3.91K/313K -> 5.86K/469K -> 7.81K/625K (vmstat -m TARG) = exactly ~80 bytes (sizeof targ_cmd_descr) leaked per drained descriptor, permanently. targread abort_queue drain (scsi_target.c:921-937) TAILQ_REMOVEs each descr and hands back the pointer without kfree; no other free path can reach a drained descriptor (targfreeccb is only called for user_ccb_queue entries; targdtor :545-547 only drains what is still queued). RESTRICTEDROOT gated; unbounded kernel-memory exhaustion.",
  "exploit_chain": "",
  "evidence": "run.log: 2000/2000 pointer-matched drains; vmstat TARG 1.95K/156K -> 3.91K/313K -> 5.86K/469K -> 7.81K/625K across runs; ~80 B/descr",
  "kernel_refs": [
    "sys/bus/cam/scsi/scsi_target.c:921",
    "sys/bus/cam/scsi/scsi_target.c:924",
    "sys/bus/cam/scsi/scsi_target.c:931",
    "sys/bus/cam/scsi/scsi_target.c:937",
    "sys/bus/cam/scsi/scsi_target.c:674",
    "sys/bus/cam/scsi/scsi_target.c:681",
    "sys/bus/cam/scsi/scsi_target.c:545",
    "sys/bus/cam/scsi/scsi_target.c:1041",
    "sys/bus/cam/cam_periph.c:702"
  ],
  "poc_changes": "Authored from scratch; vmstat -m human-suffix parsing (1.95K/156K) had to be added (plain sscanf read 1 and 156); printf type fixes.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Wed Oct 21 11:04:42 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/BUSAUDIT x86_64 (stock GENERIC + device targ; INVARIANTS)",
  "runtime_sec": 120,
  "guest_dirty": 0,
  "build_cmd": "cc -O -Wall -o poc2287 poc2287.c",
  "run_cmd": "kldload ./targsim.ko; ./poc2287",
  "code_hash": "2528147dad6a8e29d1eae4c93e2ba690e705e2a3d7435b146b27f556091d3d0e",
  "notes": "",
  "recommended_fix": "kfree(user_descr, M_TARG) after the successful uiomove in the drain loop (fix.diff).",
  "fix_status": "fixed",
  "fix_validation": "fix kernel: same 2000-cycle PoC -> M_TARG count delta 1 (vmstat TARG 0/0 after): zero leaked descriptors; A/B: +1950 -> 0"
}