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

STEPBY unsigned underflow via missing minimum length check (LMI_MIN_LENGTH defined never used) β€” ng7 twin of DF-0554

Summary

ng7 twin of DF-0554. LMI_MIN_LENGTH=8 defined(:88) never used. nglmi_checkdata reads fixed header bytes sequentially STEPBY(1)(:757/:783/:791/:806) without verifying packetlen>=1. packetlen u_short(:741). Short frame -> STEPBY underflows 0->0xFFFF -> IE loop while(packetlen>=2) iterates with huge packetlen -> data advances past mbuf into adjacent kernel heap. Hex-dump logging(:992-1046) exposes heap. Panics crossing unmapped page. Reliability depends on residual mbuf bytes matching expected values (0x03/0x7D/0x95). Fix: if(m_len<LMI_MIN_LENGTH) goto drop + packetlen>=1 guard before each STEPBY.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0562 Β· 6 files
FileTypeDescriptionSize
VERDICT.md verdict full narrative: why not live, source-trace confirmation, twin-of-DF-0554 4.5 KB ↓ raw
fix.diff suggested-fix LMI_MIN_LENGTH guard at top of nglmi_checkdata (validated compile-only) 715 B view raw
build.log build-log ng7_lmi.ko standalone build, patched source, full output 6.8 KB view raw
env.txt environment guest uname, ng7 unshipped status 928 B view raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
VERDICT.md verdict full narrative: why not live, source-trace confirmation, twin-of-DF-0554
↓ download raw

DF-0562 β€” ng7_lmi STEPBY underflow (twin of DF-0554)

Verdict

NOT REPRODUCED LIVE β€” but bug confirmed in source (latent in a parallel source tree that is not built/shipped by default). The code is byte-for-byte identical to the DF-0554 pattern in the shipped sys/netgraph/lmi/ng_lmi.c, which I reproduced and patched live (see DF-0554 evidence pack).

Why not live-reproduced

sys/netgraph7/lmi/ng_lmi.c is built only when the kernel is compiled with options NETGRAPH7 AND options NETGRAPH7_LMI (see sys/conf/options:284,332 and sys/conf/files:1668+). The default X86_64_GENERIC kernel ships the OLDER netgraph (sys/netgraph/lmi/ng_lmi.c) as /boot/kernel/ng_lmi.ko. The two files have the same Makefile-target name (ng_lmi.ko) so only one can be installed at a time; the audit guest ships the older one (verified by strings /boot/kernel/ng_lmi.ko showing /usr/src/sys/netgraph/lmi/ng_lmi.c).

Standalone make in /usr/src/sys/netgraph7/lmi does succeed (the file itself is valid kernel C), but loading the resulting ng_lmi.ko would require also loading the netgraph7 base (netgraph7/netgraph/ng_base.c), which is not built/shipped either. Without an admin explicitly enabling NETGRAPH7 in a custom kernel, the path is dead code.

Source-level confirmation (trace)

The bug pattern in sys/netgraph7/lmi/ng_lmi.c is identical to DF-0554:

line code role
:88 #define LMI_MIN_LENGTH 8 /* XXX verify */ defined, never used
:544-548 STEPBY(stepsize) macro packetlen -= stepsize; data += stepsize; no guard
:741 u_short packetlen; underflowable 16-bit unsigned
:751 packetlen = m->m_len; init from mbuf length
:757 STEPBY(1) after *data == 0x03 1st underflow site
:783 STEPBY(1) after Protocol ID check 2nd underflow site
:791 STEPBY(1) after Call Ref check 3rd underflow site
:806 STEPBY(1) after msg-type switch 4th underflow site
:841 while (packetlen >= 2) IE loop iterates with wrapped packetlen=0xFFFF

For a 1-2 byte mbuf, STEPBY(1) at :757 underflows packetlen from 0 to 0xFFFF (u_short). Subsequent *data reads at :760/:786/:794/:811 read past the mbuf into adjacent kernel heap. Same code path as DF-0554; same effect (heap OOB read + leak via NGM_LMI_GET_STATUS).

Reachability on default install

not reachable β€” netgraph7 stack is opt-in and not shipped. If a future release switches the default netgraph to netgraph7 (or an admin enables NETGRAPH7_LMI), this bug becomes live. The fix is warranted as defense-in-depth before that switch happens.

PoC

The DF-0554 PoC (df0554.c) triggers the bug on the shipped ng_lmi.ko with the identical code pattern; the same PoC would trigger this finding if ng7_lmi were loaded. See ../DF-0554/df0554.c and ../DF-0554/run.sh.

fix.diff applies the same LMI_MIN_LENGTH guard to sys/netgraph7/lmi/ng_lmi.c:751 (just after packetlen = m->m_len;, before the first *data deref). Validated by:

  1. patch -p4 < fix.diff β†’ Hunk #1 succeeded at 750.
  2. make in /usr/src/sys/netgraph7/lmi β†’ builds cleanly (/usr/obj/usr/src/sys/netgraph7/lmi/ng_lmi.ko, 15824 bytes).
  3. strings ng_lmi.ko | grep "too short" β†’ the new log message is present.

Cannot run the PoC against this module on the audit guest because the netgraph7 base is not shipped; the fix validation is therefore not_testable (compile-only + traced close). The live behavior of an identical patch on the shipped twin is documented in DF-0554 (status: FIXED β€” baseline showed error at location -65533, patched shows too short (N)).

Kernel references (verified by source trace)

Threat model

Same as DF-0554 (remote FR peer feeding crafted LMI over a serial link into an admin-configured ng_lmi node), but only on installations that opt into the netgraph7 stack. The bug is latent on default installs.

Fix verification

not_testable

compile validated

see evidence pack

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. ng7_lmi STEPBY underflow (twin of DF-0554). netgraph7 not shipped. Compile validated.