DF-3583 / verdict.json
{ "finding_id": "DF-3583", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Kernel stack OOB read confirmed at source level and proven arithmetically on the guest with the real kernel headers: isp_intr()s RQSTYPE_RIO1 handler (sys/dev/disk/isp/isp.c:5093) loops `i < rio->req_header.rqs_seqno` over isp_rio1_t.req_handles[15] (ispmbox.h:866-871) where rqs_seqno is a full card-written 8-bit byte; seqno > 15 reads up to 960 bytes past the 64-byte stack buffer qe[]. The extracted-logic PoC faults at the first i == 16 iteration (run.log). Values are only used as completion-handle lookup keys (isp_fastpost_complete validates via ISP_VALID_INI_HANDLE), so impact is chance spurious command completion/stack-value disclosure into lookup keys \u2014 not a direct user-visible leak. Reachable only on Ultra3 SCSI cards (RIO 32-bit enabled by default, isp.c:1360-1361) with faulty/malicious firmware; guest has no QLogic HBA so the in-kernel path was not exercised. Modern FreeBSD removed RIO1 handling entirely.", "exploit_chain": "", "evidence": "run.log \u2014 sizeof(isp_rio1_t) = 64 (header 4 + req_handles[15]) and FAULT (SIGSEGV/SEGV) ... (loop reached i == 16, array holds 15); trigger_df3583.c; VERDICT.md; fix.diff (clamp to NELEM(req_handles))", "kernel_refs": [ "sys/dev/disk/isp/isp.c:5087-5098", "sys/dev/disk/isp/isp.c:1360-1361", "sys/dev/disk/isp/ispmbox.h:316-321", "sys/dev/disk/isp/ispmbox.h:866-871" ], "poc_changes": "No seed (pass-2 new finding). Trigger written from scratch against the verbatim kernel headers; qe[64] placed flush against a PROT_NONE page so the first out-of-array read (i == 16) faults deterministically.", "attempts": 2, "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": 90, "guest_dirty": 0, "build_cmd": "cc -Wall -I. -o trigger_df3583 trigger_df3583.c (headers copied from /usr/src/sys/dev/disk/isp)", "run_cmd": "./trigger_df3583", "code_hash": "1b9635747c5eba439d1ea7646e213452d136ea018b7622424453ee1cfaad1b24", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff clamps the loop with NELEM(rio->req_handles); NELEM is already used in this file (isp.c:7163). Baseline not reproducible without hardware, so no patched-kernel A/B was possible; the clamp is a pure bounds correction.", "fix_evidence": "fix.diff (git-apply-able against sys/dev/disk/isp/isp.c hunk at line 5093)", "notes": "Robustness-against-faulty-hardware class (card is the trust boundary); same family as pass-1 DF-1125 (hw-driven length trusted) but distinct site and read-only impact.", "recommended_fix": "Clamp the RIO1 fast-post loop to NELEM(rio->req_handles) entries." } |