DF-2287 / verdict.json
{ "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" } |