⬢ DragonFlyBSD Kernel Audit
DF-3382 / fix.diff
← back to finding ↓ download raw
--- a/sys/net/bpf.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/net/bpf.c	2026-09-11 22:19:03.889823392 +0000
@@ -792,7 +792,12 @@
 	 * Set buffer length.
 	 */
 	case BIOCSBLEN:
-		if (d->bd_bif != NULL) {
+		/*
+		 * Also reject once buffers exist: bpf_setif() only
+		 * (re)allocates when bd_sbuf == NULL, so resizing here
+		 * after a detach would leave stale undersized buffers.
+		 */
+		if (d->bd_bif != NULL || d->bd_sbuf != NULL) {
 			error = EINVAL;
 		} else {
 			u_int size = *(u_int *)ap->a_data;
@@ -1126,6 +1131,16 @@
 		 * just flush the buffer.
 		 */
 		if (d->bd_sbuf == NULL) {
+			/*
+			 * The store buffer must at least hold the bpf
+			 * header + link header of this interface,
+			 * otherwise catchpacket() underflows
+			 * bh_caplen = totlen - hdrlen.
+			 */
+			if (d->bd_bufsize < bp->bif_hdrlen) {
+				ifnet_unlock();
+				return (EINVAL);
+			}
 			error = bpf_allocbufs(d);
 			if (error != 0) {
 				ifnet_unlock();
@@ -1418,11 +1433,24 @@
 	totlen = hdrlen + min(snaplen, pktlen);
 	if (totlen > d->bd_bufsize)
 		totlen = d->bd_bufsize;
+	if (totlen < hdrlen) {
+		/*
+		 * Buffer smaller than the bpf+link header: drop rather
+		 * than underflowing bh_caplen into a huge copy length.
+		 */
+		++d->bd_dcount;
+		return;
+	}
 
 	/*
 	 * Round up the end of the previous packet to the next longword.
 	 */
 	curlen = BPF_WORDALIGN(d->bd_slen);
+	if (d->bd_sbuf == NULL) {
+		/* Lost store buffer (read/flush race): drop. */
+		++d->bd_dcount;
+		return;
+	}
 	if (curlen + totlen > d->bd_bufsize) {
 		/*
 		 * This packet will overflow the storage buffer.