⬢ DragonFlyBSD Kernel Audit
DF-3428 / fix.diff
← back to finding ↓ download raw
--- 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;
 	}