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

amdsmb_bread uses unbounded hardware byte-count for register indexing and out-param

Summary

amdsmb_bread reads block byte-count directly from controller SMB_BCNT register into len with no validation. Non-compliant/malicious SMBus slave can return up to 255 causing loop to issue bus_read_1() at offsets SMB_DATA+i (0x04..0x102) far beyond 32-entry data register file (0x04..0x23). *count=len reports hardware length back to caller breaking contract. Buf write guarded by i<*count so buf not overwritten OOB but *count reports unbounded len so caller trusting *count reads uninitialized buffer. /dev/smbN 0600 root:wheel. Impact: out-of-range I/O register reads + inconsistent out-param. [VERIFIED pass2: reproduced - BCNT 255 slave fetches 221 registers past the 32-entry file via EC protocol offset wrap and reports count 255 against a 32-byte buffer; double HW-gated AMD-8111 plus malicious slave root-only; 32-clamp fix-validated]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2330 Β· 10 files
FileTypeDescriptionSize
amdsmb_rig.c β€” 7.2 KB view raw
build.log β€” 207 B view raw
build.sh β€” 91 B view raw
env.txt β€” 412 B view raw
fix.diff β€” 349 B view raw
run.log β€” 2.0 KB view raw
run.sh β€” 112 B view raw
run_fixed.log β€” 1.6 KB view raw
verdict.json β€” 1.9 KB view raw
fix.diff β€” 349 B view raw

Fix verification

not_testable
↓ fix.diffper-fix-DF-2330

Confirmed kernel references

Detail

Evidence (decisive lines)

run.log (attack: PROOF + CONTRACT BREAK lines; edge bcnt=33; control), run_fixed.log (count_out=32, OOB=1 legitimate BCNT fetch), fix.diff

PoC changes

first model returned 224 (rig had overwritten the BCNT register in its own data fill); fixed the model to serve distinct values beyond the file

Verified recommended fix

clamp the hardware byte count to the 32-entry data register file in amdsmb_bread

Verdict

amdsmb_bread (amdsmb.c:517-547) verbatim rig with an emulated AMD-8111 SMBus controller: a non-compliant slave reporting BCNT=255 makes the loop fetch logical SMB registers 0x04..0xff via the EC protocol - 221 fetches beyond the 32-entry data register file (SMB_DATA..0x23), sweeping protocol registers after the u_char offset wraps - and sets *count=255 against a 32-byte caller buffer (contract break: caller reads 223 uninitialized bytes). With the 32 clamp the attack run is indistinguishable from the compliant control (count_out=32, only the legitimate BCNT fetch touches >0x23). Hardware-gated twice over: AMD-8111 SMBus2 controller plus a malicious slave, via root-only /dev/smbN.