# DF-0528 — VERDICT

## Verdict: SOURCE-CONFIRMED, NOT REACHABLE AT RUNTIME (blocked by DF-0529)

## The bug (confirmed in source)

`ng_fec_rmnode()` (`sys/netgraph/fec/ng_fec.c:1213`) tears down the bundle by
looping over member ports and calling `ng_fec_delport()` **by interface name**,
which re-resolves the interface via `ifunit()`:

```c
// :1224-1229
while (!TAILQ_EMPTY(&b->ng_fec_ports)) {
    p = TAILQ_FIRST(&b->ng_fec_ports);
    ksprintf(ifname, "%s", p->fec_if->if_xname);   // UAF if iface already freed
    ng_fec_delport(priv, ifname);
}
```

`ng_fec_delport()` (`:417`) does:

```c
// :433-439
bifp = ifunit(iface);
if (bifp == NULL) {
    kprintf("... doesn't seem to exist\n");
    return (ENOENT);          // returns WITHOUT removing the port from the TAILQ
}
```

If a member interface has already been destroyed (e.g. the admin destroyed a
`tap` member, or the underlying NIC was detached), `ifunit()` returns NULL and
`delport` returns `ENOENT` **without unlinking the port**.  The `while` loop in
`rmnode` therefore never makes progress → **infinite loop** (kernel hang /
soft-lockup).  Additionally `p->fec_if->if_xname` is a **use-after-free** once
the member `ifnet` has been freed.  This is the same defect as the netgraph7
twin DF-0502.

## Why it cannot be triggered at runtime on this guest

`ng_fec_rmnode()` runs when an ng_fec node is shut down — which requires a
node to have been created first.  But `ng_fec_constructor()` panics on every
node creation (DF-0529), so no node is ever available to shut down.  Verified
empirically; the node is uncreatable even after DF-0529's documented fix.

## Impact ceiling (latent)

Kernel hang / infinite loop in `ng_fec_rmnode` (local DoS), plus a
use-after-free read on `p->fec_if->if_xname`.  The UAF is a read (string
format), not a controllable write.

## Exploit chain

`none` — infinite-loop DoS + UAF read; not a write-capable primitive.

## Fix validation

`fix.diff` replaces the `delport`-by-name loop with a direct unlink+free
(avoiding the `ifunit()` re-resolution entirely):

```c
while (!TAILQ_EMPTY(&b->ng_fec_ports)) {
    p = TAILQ_FIRST(&b->ng_fec_ports);
    TAILQ_REMOVE(&b->ng_fec_ports, p, fec_list);
    kfree(p, M_NETGRAPH);
}
b->fec_ifcnt = 0;
```

Compiles cleanly (RC=0).  `fix_status = not_testable` — the DF-0529 constructor
panic prevents creating a node to shut down; compile-validated only, traced to
close the cited path.

## PoC changes

Wrote `trigger.sh` (create node, add tap, destroy tap, shutdown node — needs a
DF-0529-fixed kernel), `build.sh`/`run.sh`, `fix.diff`.  No upstream PoC.
