DF-3824 / verdict.json
{ "finding_id": "DF-3824", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "ASR_init_message()s SGL loop is bounded by compile-time SG_SIZE=58 (asr.c:1812) which fills bytes [48,512) of asr_action()s 512-byte stack buffer exactly; the mandatory sense element written unconditionally after the loop (asr.c:1844-1845) then lands at bytes [512,520) - an 8-byte kernel stack OOB write (flags dword + low-32-bit physical address) whenever a single XPT_SCSI_IO spans >=58 physically-discontiguous runs (~>=232KiB). Normal disk I/O is capped by MAXPHYS=128KiB (~33 runs) and cannot trigger it; CAM pass-through (root-only /dev/passN) with a large scattered buffer can. The adapter-derived ha_SgSize (asr.c:2459-2465) is computed and never used, so the posted SGL also ignores the adapters inbound frame size. Arithmetic verified on the guest by compiling and running sg_layout_proof.c (struct replicas; output: sense element at [512,520), overflow 8 bytes). The kernel write itself is unexercisable: guest has no asr HBA (no /dev/asr0, zero vendor-0x1044 PCI devices) so asr_action never runs.", "exploit_chain": "root on host with asr card: camcontrol pass-through with dxfer_len >= ~256KiB over fragmented buffer -> 58+ physical runs -> sense SGL element overwrites 8 bytes past struct Message on asr_actions stack (adjacent locals/saved state, compiler-dependent) -> corruption/panic; exploitability beyond DoS depends on stack layout.", "evidence": "run.log (sg_layout_proof output on guest: offsets 48/8/512, sense at [512,520)); build.log; VERDICT.md (full derivation); fix.diff (reserve one SGL slot for the sense element)", "kernel_refs": [ "sys/dev/raid/asr/asr.c:1812", "sys/dev/raid/asr/asr.c:1844", "sys/dev/raid/asr/asr.c:2680", "sys/dev/raid/asr/asr.c:2459", "sys/dev/raid/asr/asr.c:258", "sys/cpu/x86_64/include/param.h:122" ], "poc_changes": "Layout prover written fresh from the i2omsg.h/i2odpt.h struct definitions; no seed PoC existed.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 X86_64_GENERIC x86_64", "runtime_sec": 60, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o sg_layout_proof sg_layout_proof.c", "run_cmd": "./sg_layout_proof", "code_hash": "33e62c9581bad0a0b10766bf58ad37fb36437aa3b8842318eb0e7d1fdda48bc9", "notes": "ccb scatter/gather hunt item (c). Severity Low: needs root + rare hardware; the OOB itself is certain. ha_SgSize dead-store confirms the bound was meant to be dynamic.", "recommended_fix": "Bound the SGL loop by SG_SIZE-1 (reserve the last slot for the sense element) and honor sc->ha_SgSize (asr.c:1812).", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Baseline overflow cannot be triggered without an asr controller; the layout proof validates the geometry only. fix.diff reserves the sense slot so the maximum write is [48,512) in-bounds.", "fix_evidence": "fix.diff" } |