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

Missing minimum-length check + u_short packetlen underflow in LMI packet parser kernel heap OOB read

Summary

LMI_MIN_LENGTH=8 defined(:88) but never used. Neither nglmi_rcvdata nor nglmi_checkdata enforces minimum packet length. Loop variable packetlen is u_short while STEPBY macro(:544-548) does unchecked packetlen-=step. 0-4 byte mbuf surviving byte-by-byte header checks causes packetlen wrap from 0 to 65535 then IE-parsing loop while(packetlen>=2) walks data far past mbuf storage into adjacent kernel heap. m_pullup check :576 dead (m_len<packetlen identically false). STEPBY(1) at :757/:783/:791/:806 consume bytes past valid. Per-iteration reads data[0]/data[1] become silent OOB reads ~85 iterations past MHLEN~172. No info leak logs bounded m_len no controlled write. [VERIFIED pass2: reproduced - 4-byte Annex-D frame checkdata errors at location -65528 proving 8 bytes walked past after packetlen wrapped 0 to 65535; LMI_MIN_LENGTH guard proposed]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2603 Β· 3 files
FileTypeDescriptionSize
harness.c β€” 4.7 KB view raw
build.sh β€” 89 B view raw
run.log β€” 973 B view raw

Fix verification

not_testable
↓ fix.diffper-fix-DF-2603

Confirmed kernel references

Detail

Evidence (decisive lines)

lmi run + dmesg: error at location -65528 for the 4-byte frame vs location 8 for the 8-byte control

PoC changes

real ng_lmi.c checkdata + crafted cluster with controlled residue

Verified recommended fix

enforce LMI_MIN_LENGTH (m_len >= 8) at the top of nglmi_checkdata/nglmi_rcvdata

Verdict

LMI_MIN_LENGTH=8 (ng_lmi.c:88) is never enforced and STEPBY() decrements u_short packetlen unchecked. Real ng_lmi.c (compiled into the harness, linkage-only edits): a 4-byte Annex-D frame [03 09 00 7D] drove nglmi_checkdata into nglmi: unexpected SEQ ... error at location -65528 -- the parsers OWN error dump shows the data pointer 8 bytes past the packet after packetlen wrapped 0->65535 and the IE loop consumed residue beyond m_len (the 0x95 locking shift + IE stream read from stale cluster bytes). Control 8-byte frame errored at location 8 (in-bounds). Bytes feed parser decisions only (no return path), matching the findings no-leak/no-write assessment; a sufficiently long garbage walk could still fault into unmapped memory (DoS ceiling).