I2CRDWR: no upper-bound validation on nmsgs allows massive kernel allocations (DoS)
Summary
I2CRDWR handler performs no validation on d->nmsgs (uint32_t fully user-controlled). Values up to UINT32_MAX cause kmalloc of up to ~64GB (16*nmsgs for msgs array) and ~32GB (8*nmsgs for usrbufs) with M_WAITOK. These allocations can exhaust kernel memory or hang calling thread indefinitely as allocator waits for memory that will never become available. No integer overflow on LP64 (16*UINT32_MAX < 2^36) but allocation itself unbounded. [VERIFIED pass2: reproduced - nmsgs 262144 performs unvalidated 4MiB plus 2MiB kmallocs, nmsgs 0x8000000 one-syscall panic malloc limit exceeded; nmsgs cap fix-validated EINVAL]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2312 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| poc2312.c | β | 3.0 KB | view raw | |
| run.log | β | 998 B | view raw | |
| panic.txt | β | 186 B | view raw | |
| fix.diff | β | 690 B | view raw | |
| verdict.json | β | 1.8 KB | view raw | |
| README.md | β | 819 B | β raw |
DF-2312 β I2CRDWR: unbounded nmsgs drives unbounded M_WAITOK allocations
What (sys/bus/iicbus/iic.c:350-352)
d->nmsgs is a fully user-controlled u32 used directly as the multiplier of kmalloc(16nmsgs) and kmalloc(8nmsgs), both M_WAITOK, with no upper bound.
Reproduce / Result (run.log + panic.txt)
- Phase A (nmsgs=262144): the kernel really performs the 4 MiB + 2 MiB allocations in one ioctl (temp +2 MiB retained per call via the DF-2309 usrbufs interaction proves the sizes).
- Phase B (nmsgs=134217728): kmalloc(2 GiB) ->
panic: temp: malloc limit exceeded, backtrace malloc <- _kmalloc <- iicioctl. One unvalidated u32 = one-syscall privileged kernel panic.
Fix
fix.diff rejects nmsgs == 0 || nmsgs > 4096 with EINVAL. Validated: both phases return EINVAL, no allocation, no panic.
Fix verification
fixedConfirmed kernel references
Detail
Evidence (decisive lines)
run.log + panic.txt: phase A allocation accounting; phase B panic: temp: malloc limit exceeded with iicioctl in the backtrace
PoC changes
Self-contained iic ABI header (no /usr/include/bus/iicbus on the guest).
Verified recommended fix
Reject nmsgs == 0 || nmsgs > 4096 with EINVAL before the allocations (fix.diff).
Verdict
REPRODUCED in both flavors on the production iic.ko rig: (A) nmsgs=262144 makes the kernel really perform the unvalidated kmalloc(4 MiB) + kmalloc(2 MiB) pair in one ioctl (vmstat temp +2 MiB retained usrbufs per call via the DF-2309 interaction; the msgs copyin then EFAULTs); (B) nmsgs=134217728 drives kmalloc(2147483648) (2 GiB) straight into panic: temp: malloc limit exceeded, backtrace malloc <- _kmalloc <- iicioctl <- dev_dioctl. A single unvalidated u32 multiplied into M_WAITOK sizes is a one-syscall privileged kernel panic; moderate values silently allocate without bound.
No comments yet.