--- a/sys/net/netmap/netmap_generic.c +++ b/sys/net/netmap/netmap_generic.c @@ -690,10 +690,17 @@ generic_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) // XXX should we invert the order ? /* Skip past packets that userspace has released */ j = kring->nr_hwcur; k = ring->cur; - if (resvd > 0) { - if (resvd + ring->avail >= lim + 1) { - D("XXX invalid reserve/avail %d %d", resvd, ring->avail); - ring->reserved = resvd = 0; // XXX panic... - } + /* + * DF-3428: ring->reserved/avail are user-writable u_int32; the old + * `resvd + ring->avail >= lim + 1` test wraps (e.g. 0xFFFFFFFF + 1) + * and lets resvd through, driving k out of [0, lim] at the + * subtraction below so the release loop never terminates + * (unkillable thread holding the kring lock). reserved can never + * legitimately exceed the slot count: reject it outright. + */ + if (resvd > lim) { + D("XXX invalid reserve %d (lim %d)", resvd, lim); + ring->reserved = resvd = 0; + } + if (resvd > 0) { k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; }