DragonFlyBSD Kernel Audit
DF-1123 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/netif/iwn/if_iwn.c b/sys/dev/netif/iwn/if_iwn.c
--- a/sys/dev/netif/iwn/if_iwn.c
+++ b/sys/dev/netif/iwn/if_iwn.c
@@ -3081,6 +3081,27 @@
 		len = le16toh(stat->len);
 	}
 
+	/*
+	 * Upper-bound the firmware-reported frame length against the RX
+	 * cluster.  `head` sits inside data->m's IWN_RBUF_SIZE (4096) DMA
+	 * buffer, and the FCS read below dereferences (head + len).  Without
+	 * this check a buggy or hostile firmware/PHY reporting len up to 65535
+	 * read ~60KB past the 4KB cluster (OOB heap read) and fabricated an
+	 * mbuf claiming that oversized body for ieee80211_input.
+	 */
+	if (len > IWN_RBUF_SIZE ||
+	    (vm_offset_t)(head + len + sizeof(uint32_t)) >
+	    (vm_offset_t)mtod(data->m, caddr_t) + IWN_RBUF_SIZE) {
+		DPRINTF(sc, IWN_DEBUG_RECV, "%s: frame too long: %d\n",
+		    __func__, len);
+#if defined(__DragonFly__)
+		++ic->ic_ierrors;
+#else
+		counter_u64_add(ic->ic_ierrors, 1);
+#endif
+		return;
+	}
+
 	flags = le32toh(*(uint32_t *)(head + len));
 
 	/* Discard frames with a bad FCS early. */