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)
PoC verification
Evidence pack
findings/poc/DF-2334 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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_testableConfirmed 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).
No comments yet.