DF-3382 / fix.diff
--- 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. |