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

Firmware completion tokens consumed unvalidated: psrb_pool[SMID] OOB read (ARC1884) and wild vir2phy SRB dereference (types A-D)

Summary

arcmsr_drain_donequeue() for TYPE E does srb = acb->psrb_pool[flag_srb] with flag_srb = the 16-bit cmdSMID DMA-written by firmware, with no bounds check against the 384-entry array: an SMID in 384..65535 reads up to ~512KB past psrb_pool into adjacent kernel heap, and the value is immediately dereferenced (srb->acb). For types A-D the raw device token is turned into a pointer via vir2phy_offset arithmetic and dereferenced before any pool-range validation - a device value anywhere in 32-bit physical space yields a wild kernel pointer. Same threat model as DF-1184 (buggy/hostile firmware or device DMA): transient fault -> panic; deliberate attacker -> forged SRB -> arcmsr_srb_complete on attacker-chosen pointers (bus_dmamap_unload/xpt_done on forged pointers). Upstream FreeBSD main still has the same unguarded index (verified). VERIFIED: harness on the guest - SMID=0xffff reads 521216 bytes past the array; the (A-D) variant resolves a device value ~1GB away from the pool. Fix validated on rebuilt kernel.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3709 Β· 9 files
FileTypeDescriptionSize
harness.c trigger-source models psrb_pool[384] indexing with firmware u16 SMID + (A-D) vir2phy address derivation 5.0 KB view raw
build.sh build cc -O2 -Wall -o harness harness.c 65 B view raw
run.sh run executes harness 89 B view raw
build.log log untrimmed guest build output 66 B view raw
run.log log decisive run 859 B view raw
run.2.log log repeat run 859 B view raw
fix.diff fix SMID >= ARCMSR_MAX_FREESRB_NUM guards in drain_donequeue + polling_hbe 1012 B view raw
fix_build.log log patched-source kernel build log (arcmsr.c compiled -Werror clean, in-kernel + KLD) 870 B view raw
env.txt env guest uname/compiler/no-HW evidence 643 B view raw

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

fix.diff (two SMID guards) applied to guest /usr/src copy; arcmsr.c recompiled clean with -Werror in-kernel and KLD builds (fix_build.log). On-hardware behavioral validation impossible in this guest.

fix_build.log arcmsr compile lines with -Werror and 0 arcmsr-related errors; guards visible at arcmsr.c:820-826 and 3596-3601 in guest tree before restore
↓ fix.diffper-fix-DF-3709

Confirmed kernel references

Detail

Exploit chain

firmware/DMA-controlled SMID or address -> OOB read of kernel heap / wild SRB pointer -> srb->acb/srb_state deref (panic) or, with DMA control, forged SRB -> arcmsr_srb_complete -> bus_dmamap_unload/xpt_done on forged pointers; not exercisable without Areca hardware

Evidence (decisive lines)

run.log: 'SMID=0xffff -> index distance past array end: 65152 entries (521216 bytes)'; '(A-D variant) raw device value 0xedcba988 -> distance from pool base: +0x41fea980 bytes (pool is only ~209KB)'; '[+] DF-3709 CONFIRMED'; VERDICT.md cites all sites

PoC changes

authored from scratch (no seed)

Verified recommended fix

reject flag_srb/cmdSMID >= ARCMSR_MAX_FREESRB_NUM in arcmsr_drain_donequeue() and arcmsr_polling_hbe_srbdone(); harden A-D by range-checking the physical token against [srb_phyaddr, srb_phyaddr + ARCMSR_SRBS_POOL_SIZE)

Verdict

Firmware completion tokens are consumed unvalidated: for ARC1884 (TYPE E) arcmsr_drain_donequeue() (arcmsr.c:821) and arcmsr_polling_hbe_srbdone() (arcmsr.c:3582) index acb->psrb_pool[] (384 entries) with the firmware DMA-written 16-bit cmdSMID (arcmsr.c:2120-2122) with no bounds check -> OOB kernel read up to 65152 entries (~512KB) past the array, value immediately dereferenced as srb->acb (arcmsr.c:829); for TYPE A-D (arcmsr.c:818/826) the raw device value is turned into a pointer via vir2phy_offset arithmetic and dereferenced before any pool-range validation. Guest has no Areca HBA (0 PCI devices vendor 0x17D3), so reproduction is a harness modeling the exact arithmetic: SMID 0xffff reads 65152 entries past psrb_pool and feeds a wild pointer; the A-D variant resolves a device value ~1GB away from the 209KB pool. Threat model identical to DF-1184: buggy/hostile firmware or device DMA; realistic impact kernel panic, with forged-SRB completion (xpt_done on attacker-chosen pccb) available to a DMA-level attacker.