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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2312 Β· 6 files
FileTypeDescriptionSize
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

fixed
↓ fix.diffper-fix-DF-2312

Confirmed 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.