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

Unbounded queue-number index into sense_buffers[] heap OOB read / kernel heap info leak

Summary

adv_done indexes adv->sense_buffers[q_no-1] using queue number read directly from firmware LRAM via adv_copy_lram_doneq with no validation q_no in [1 max_openings]. sense_buffers allocated for exactly max_openings entries. q_no of 0 (underflows to 0xFFFFFFFF since u_int) or q_no > max_openings (firmware queue space extends ADV_MAX_QNO=0xF8=248 while max_openings may be 16) causes OOB heap read structure-copied into CCB auto-sense buffer returned to userland via CAM_AUTOSNS_VALID. Impact: kernel heap memory disclosure up to few KB per request when q_no > max_openings or immediate panic when q_no==0. Requires control of AdvanSys HBA LRAM. [VERIFIED pass2: reproduced - q_no 25 struct-copies sense_buffers 24 OOB into autosense, q_no 0 wraps to 128GB span index; zeros in-capture so no contentful leak captured; bound fix authored]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2412 Β· 11 files
FileTypeDescriptionSize
README.md β€” 345 B ↓ raw
VERDICT.md β€” 1.4 KB ↓ raw
build.sh β€” 93 B view raw
dfadv24.c β€” 46.2 KB view raw
env.txt β€” 254 B view raw
fix.diff β€” 517 B view raw
manifest.json β€” 734 B view raw
primeadv.sh β€” 663 B view raw
run.log β€” 1.0 KB view raw
run.sh β€” 147 B view raw
verdict.json β€” 2.0 KB view raw

DF-2412 -- evidence pack

Verdict: reproduced (reproduced=1, impact=none, confidence=likely)

Build: see build.sh (df43xx_rig.ko extension) Run: sh primeadv.sh; sysctl kern.df43xx.go=12; sysctl kern.df43xx.go=13

See VERDICT.md for the full narrative, run.log/panic.txt for the decisive output, fix.diff for the post-verification fix.

VERDICT.md
↓ download raw

DF-2412 VERDICT

Status: reproduced Impact: none Confidence: likely

Firmware-controlled q_no indexes adv->sense_buffers[q_no-1] with no bound: production adv_intr completed a CHECK_COND entry naming q_no=25 over a 16-entry array, copying the struct at sense_buffers+768 (OOB by construction) into ccb->csio.sense_data with CAM_AUTOSNS_VALID set (kernel heap disclosure window into pass(4)-readable sense data); the q_no=0 variant reads at sense_buffers + 0x1FFFFFFE0 (u_int wrap), also survived and copied 32 zero bytes from that distant KVA. Captured contents were zeros on this heap state both times, so no secret bytes were disclosed in the capture, but the OOB read is mechanically proven (index 24 of a 16-element array; AUTOSNS=1).

Kernel references

Guest

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

Notes

requires control of the AdvanSys HBA LRAM (hostile/compromised card or VM passthrough), hence Low

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
↓ fix.diffper-fix-DF-2412

Confirmed kernel references

Detail

Exploit chain

HBA LRAM/firmware controls q_no -> sense_buffers[q_no-1] struct-copied into user-visible sense data: kernel heap read window up to a 128GB span at 32-byte granularity

Evidence (decisive lines)

run.log (AUTOSNS=1 dumps for q_no=25 and q_no=0)

PoC changes

df43xx rig (DF-4349 harness) extended with a status-parameterized done-queue entry and the two q_no scenarios; production adv_intr dispatched over fabricated post-attach state

Verified recommended fix

validate q_no in adv_done/adv_run_doneq: if (q_no == 0 || q_no > adv->max_openings) drop the completion

Verdict

Firmware-controlled q_no indexes adv->sense_buffers[q_no-1] with no bound: production adv_intr completed a CHECK_COND entry naming q_no=25 over a 16-entry array, copying the struct at sense_buffers+768 (OOB by construction) into ccb->csio.sense_data with CAM_AUTOSNS_VALID set (kernel heap disclosure window into pass(4)-readable sense data); the q_no=0 variant reads at sense_buffers + 0x1FFFFFFE0 (u_int wrap), also survived and copied 32 zero bytes from that distant KVA. Captured contents were zeros on this heap state both times, so no secret bytes were disclosed in the capture, but the OOB read is mechanically proven (index 24 of a 16-element array; AUTOSNS=1).