# 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`.

## Recommended fix (validated compile-only)

`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)

- `sys/netgraph7/lmi/ng_lmi.c:88`  — `LMI_MIN_LENGTH` defined, never used.
- `sys/netgraph7/lmi/ng_lmi.c:544` — `STEPBY` macro, no underflow guard.
- `sys/netgraph7/lmi/ng_lmi.c:741` — `packetlen` declared `u_short`.
- `sys/netgraph7/lmi/ng_lmi.c:751` — `packetlen = m->m_len;`.
- `sys/netgraph7/lmi/ng_lmi.c:757,783,791,806` — four `STEPBY(1)` sites.
- `sys/netgraph7/lmi/ng_lmi.c:841` — IE loop `while (packetlen >= 2)`.
- `sys/conf/options:284` — `NETGRAPH7` opt-in.
- `sys/conf/files:1668+` — netgraph7 sources only built under NETGRAPH7_*.

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