# DF-4939 VERDICT — REPRODUCED (kernel heap leak, unbounded, privileged trigger)

## What was claimed

`sys/dev/netif/ic/if_ic.c` `icioctl()` SIOCSIFFLAGS: the down branch
(if_ic.c:179-187) never frees `sc->ic_obuf` / `sc->ic_ifbuf`, and the up
branch (if_ic.c:193-197) unconditionally re-kmallocs both, overwriting the
pointers. Every down→up cycle leaks `2 × (if_mtu + ICHDRLEN)` bytes of
M_DEVBUF. Unbounded: a privileged loop (`while :; do ifconfig ic0 down;
ifconfig ic0 up; done`) exhausts the kernel heap.

## How it was reproduced (guest, 2026-09-25)

Guest: DragonFly dfbsd 6.5-DEVELOPMENT #0 Thu Jul 2 06:02:54 UTC 2026,
X86_64_GENERIC, clean-source snapshot; `sys/dev/netif/ic/if_ic.c` sha256
3ff9e187... (identical to host audit tree).

No I2C controller exists in QEMU, so the ic driver (child of iicbus) cannot
attach on stock hardware. A test-harness KLD (`lpbbfake.c` in this pack)
registers a driver named "lpbb" on the ISA bus — the exact bus name iicbb
attaches to (iicbb.c:444 DRIVER_MODULE(iicbb, lpbb, ...)) — and implements
the `iicbb_if` bit-bang methods against virtual lines (SDA reads 0 = ACK,
SCL reads 1). This yields `lpbb0 → iicbb0 → iicbus0 → ic0` with no
hardware. All subsequent exercise of the bug is via stock `ifconfig(8)`
only; the harness never touches if_ic internals.

Observed (full transcript in run.log):

    kldload lpbbfake.ko, iicbb, iicbus, if_ic   -> ic0 attached
    ifconfig ic0 10.99.99.1 10.99.99.2 netmask 255.255.255.252 up
    vmstat -m : devbuf   219   214K   (baseline)
    200 x (ifconfig ic0 down && ifconfig ic0 up)
    vmstat -m : devbuf   619   814K   (+400 allocs, +600 KB)

+400 allocations = exactly 2 per cycle (ic_obuf + ic_ifbuf), +600 KB ≈
200 × 2 × 1504 B. run.2.log: a further 100 cycles → 819 allocs / 1.09M
(+200, +300 KB): linear, unbounded, deterministic (not a race — 300/300
cycles leaked).

## Impact

Kernel memory exhaustion DoS (VM pressure, allocation failures system-wide)
driven by an otherwise-inert config loop. Trigger is privileged
(SIOCSIFFLAGS is gated by caps_priv_check SYSCAP_RESTRICTEDROOT,
sys/net/if.c:2135) and requires an if_ic instance (I2C-attached system,
or the same virtual-bridge technique if an attacker can load modules).
With if_mtu at the generic max 65535 (if.c:2272), the leak rate is
~128 KB/cycle. Severity Low (privileged trigger, leak class).

Non-overlap: DF-2000 (SIOCSIFMTU free-vs-use UAF race) and DF-2001
(NULL deref pre-alloc) both concern the same buffers but different defects;
this finding is the steady-state lifecycle leak, no race involved.

## Fix validation

fix.diff (authored after reproduction): up-branch allocates only when the
respective pointer is NULL (buffers retained across down are reused).
Applied to the guest's /usr/src copy, `if_ic.ko` rebuilt (build.log.fix),
installed to /boot/kernel, guest rebooted, identical 200-cycle workload:

    vmstat -m : devbuf   219   214K   (before)
    vmstat -m : devbuf   219   214K   (after 200 cycles)  <- byte-flat

Bad behavior GONE. Guest then reset to clean-source snapshot.

## Kernel references

- sys/dev/netif/ic/if_ic.c:179-187 (down: no free, no NULL)
- sys/dev/netif/ic/if_ic.c:193-197 (up: unconditional re-kmalloc)
- sys/net/if.c:2134-2175 (generic SIOCSIFFLAGS wrapper, privilege + flag pre-set)
- sys/kern/kern_slaballoc.c (M_DEVBUF zone stats backing vmstat -m)

## Observations, limitations

- The one-off shutdown hang noted during teardown (vm.sh down after heavy
  cycling, console log overwritten by the next boot) was NOT characterized
  and is NOT counted as part of this finding.
- Leak is M_DEVBUF-typed; `vmstat -m` InUse count/KB used as the observable.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
