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

UAC2.0 Mixer Unit verifier reads d1->bNrChannels one byte past the validated length

Summary

In uaudio20_mixer_verify_desc UAC2 MIXER case reads d1->bNrChannels (first byte of mixer_unit_1 at offset 5+bNrInPins) after only checking bLength>=5+bNrInPins. When crafted device sets bLength exactly equal to 5+bNrInPins (descriptor contains header+source IDs but no mixer_unit_1) read of d1->bNrChannels lands at offset bLength one byte out of bounds. Bogus value makes final bLength<len check fail descriptor rejected but transient 1-byte OOB read already occurred. Impact: single-byte OOB read during verification panic at page boundary no data exfiltrated. [VERIFIED pass2: reproduced - bNrChannels read one byte past the declared mixer body, guard-page SIGSEGV in crash scenario, OOB byte flows into computed len in canary scenario; reject fix-validated]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2334 Β· 10 files
FileTypeDescriptionSize
build.log β€” 240 B view raw
build.sh β€” 91 B view raw
env.txt β€” 412 B view raw
fix.diff β€” 287 B view raw
run.log β€” 305 B view raw
run.sh β€” 113 B view raw
run_fixed.log β€” 809 B view raw
uaudio_rig.c β€” 5.1 KB view raw
verdict.json β€” 2.0 KB view raw
fix.diff β€” 287 B view raw

Fix verification

not_testable
↓ fix.diffper-fix-DF-2334

Confirmed kernel references

Detail

Evidence (decisive lines)

run.log (guard: SIGSEGV si_addr=0x800474000; canary: OOB byte consumed into len; control ACCEPTED), run_fixed.log (guard rejected cleanly, no SIGSEGV), fix.diff

PoC changes

initial caller len of 1 rejected the descriptor before the OOB; production caller passes 0 for degenerate clusters (ichs*ochs <= 7) so the rig uses len=0 for the attack shapes

Verified recommended fix

check bLength covers one more byte before reading d1->bNrChannels

Verdict

uaudio20_mixer_verify_desc (uaudio.c:3935-4086) verbatim rig: a UAC2 mixer descriptor with bLength == 5 + bNrInPins and a zero-length caller len passes both existing checks, and the read of d1->bNrChannels (uaudio.c:3988) lands one byte past the declared body - SIGSEGV at the guard page (si_addr == page boundary) in the crash scenario, and in the canary scenario the out-of-body byte (0x5A) demonstrably flows into the computed len (DPRINTF: len=8 of 104 bytes). With the added body check the guard scenario is rejected without any fault and the well-formed control is still accepted. Physical evil-USB exposure; descriptor is rejected after the read, so impact stays at the transient 1-byte OOB read (page-boundary panic possible in unlucky layouts).