Unvalidated descriptor-field reads in the UVC entity/CS parsers: OOB reads up to 253 bytes past malformed descriptors
Summary
Four device-field reads before/without bLength validation: XU bControlSize at 22+bNrInPins (unbounded, up to 253B past a 24B descriptor and past the cdesc when last), IT offset-14 pre-read, VC bIfaceList[0] 1-byte over, COLORFORMAT offset-3. All values traced to rejection compares/bounded indexes - no disclosure path today (hardening; the XU traversal is one refactor from one). Guards compiled in the DF-5306 fix-validation build.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5307 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.3 KB | β raw | |
| VERDICT.md | β | 2.1 KB | β raw | |
| fix.diff | β | 2.9 KB | view raw | |
| manifest.json | β | 852 B | view raw | |
| verdict.json | β | 2.2 KB | view raw |
DF-5307 β unvalidated descriptor-field reads in uvc_drv_parse_standard_ctrl()/uvc_drv_parse_data(): OOB reads up to 253 bytes past malformed descriptors
Where (all in sys/bus/u4b/uvc/uvc_drv.c)
- Extension Unit (largest) β
uvc_drv.c:2332-2334:c src_ids_num = xu_desc->bLength >= 22 ? xu_desc->bNrInPins : 0; ctrls_mask_size = xu_desc->bLength >= 24 ? *(&xu_desc->bControlSize + src_ids_num) : 0;bNrInPins(offset 21, up to 255) is not bounded by bLength; thebControlSizebyte is read at offset22 + bNrInPins, i.e. up to offset 277 of a descriptor whosebLengthmay be as small as 24 β up to 253 bytes past the descriptor end, past the end of thekmalloc()ed cdesc buffer when the XU descriptor is last. The value read is used for validation only (bLength < ctrls_mask_size + src_ids_num + 24β EINVAL), so no disclosure β but the kernel reads heap memory it must not read (and the traversal*(&field + n)is exactly the anti-pattern). - Input Terminal β
uvc_drv.c:2209:bControlSizeis read from offset 14 (memcpy(&ctrls_mask_size, it_desc + 14, 1)) before thebLength < 15 + ctrls_mask_sizecheck at 2212; a camera-terminal descriptor withbLength8..14 gives a 1..7-byte over-read. - VC header β
uvc_drv.c:2109-2124: withbLength == 12andvsnum == 1,bIfaceList[0]is read at offset 12 β one byte past the descriptor. (Same site as the DF-5306 acceptance bug; fixed together.) - VS_COLORFORMAT β
uvc_drv.c:1843-1845:cld->bColorPrisis read at offset 3 with nobLength >= 4check.
All four are read-only primitives with values consumed internally (no path to userspace found), hence Low. Same class as DF-2350/DF-5305 but distinct sites; the XU over-read is by far the largest reach.
Fix
fix.diff (shared with DF-5305/DF-5306, applies with git apply -p0):
guards each read with the appropriate bLength check and clamps
src_ids_num to bLength - 23. The VC-header guard was compiled and
exercised during the DF-5306 fix validation; the other guards are
compiled but not separately triggered (Low severity β not QEMU-verified
in this run; status untested).
Files
fix.diff covers all four sites
DF-5307 VERDICT
Status: untested (Low severity, read-only primitives β Phase V not mandated), confidence: certain in the code defect, speculative in any impact beyond the OOB read itself.
Analysis
Four sites in the descriptor parsers read device-supplied fields without first proving the descriptor is long enough to contain them (see README.md for exact path:line and mechanics):
- XU
bControlSizeat22 + bNrInPinswithbNrInPinsunbounded bybLengthβ up to 253 bytes past the descriptor (uvc_drv.c:2332-2334); - IT
bControlSizeat offset 14 before validation (uvc_drv.c:2209); - VC header
bIfaceList[0]at offset 12 whenbLength == 12(uvc_drv.c:2109-2124); - VS_COLORFORMAT
bColorPrisat offset 3 (uvc_drv.c:1843-1845).
Each over-read stays inside the cdesc allocation unless the descriptor
sits at the end of the blob, in which case it is a kernel heap OOB
read. I traced every consumer of the four values: they feed either a
comparison that rejects the descriptor (XU, IT, VC) or a colorspace
table index bounded by nitems() (COLORFORMAT) β no value reaches
userspace, so this is hardening/defense-in-depth (CWE-125 read) with
no demonstrated disclosure. The XU traversal is additionally fragile:
any future code change that uses ctrls_mask_size from the over-read
before validation would turn it into a heap-info leak.
Why untested
The QEMU harness built for DF-5305/DF-5306 exercises the parse paths but was not extended to trigger these specific malformed shapes; Low severity places them below the Phase V mandate. The fix.diff guards were compiled during the DF-5306 fix validation (the VC-header guard is on the exercised path); the XU/IT/COLORFORMAT guards are compile-checked only.
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_testablefix.diff guards present for all four sites; the VC-header guard was compiled and exercised via the DF-5306 fix-validation run; XU/IT/COLORFORMAT guards compile-checked only, not behaviorally verified.
fix.diff; DF-5306/fix.log (exercises the shared VC-header guard path)
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (full path:line analysis of all four sites and value consumers), fix.diff (guards for every site)
PoC changes
no PoC built for this finding (Low; see verdict)
Verified recommended fix
Validate bLength before each field read and clamp XU bNrInPins to bLength-23 (included in fix.diff, shared with DF-5305/DF-5306).
Verdict
Static-analysis finding, certain at the code level: four descriptor-field reads happen before (or without) bLength validation, the largest being the Extension Unit bControlSize read at offset 22+bNrInPins with bNrInPins unbounded (up to 253 bytes past a 24-byte descriptor, and past the cdesc allocation when the descriptor is last). All four values were traced to rejection comparisons or a bounded table index - no userspace disclosure path exists today, so impact is a kernel OOB read / hardening defect (Low). Not QEMU-verified: Low severity falls below the Phase V mandate; the fix.diff guards for the shared VC-header site were compiled and exercised during the DF-5306 fix validation, the rest are compile-checked.
No comments yet.