git: 81a67bfebc60 - main - rsu: add a runtime TX buffer bound check for a kernel buffer overflow

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 20 Aug 2026 14:30:38 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=81a67bfebc60055bbf19ce6e39537fb5f53eeee5

commit 81a67bfebc60055bbf19ce6e39537fb5f53eeee5
Author:     Andrew Griffiths <andrew@calif.io>
AuthorDate: 2026-08-20 14:30:03 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-08-20 14:30:03 +0000

    rsu: add a runtime TX buffer bound check for a kernel buffer overflow
    
    The rsu driver currently relies on a `KASSERT` to prove that the mbuf payload
    plus TX descriptor fits in the per-transfer USB TX buffer. On production
    kernels without `INVARIANTS`, an oversized raw 802.11 frame can reach
    `m_copydata()` and overwrite past that buffer, causing local kernel memory
    corruption.
    
    This suggested patch replaces the assertion-only guard with a runtime size
    check before the copy. Oversized frames return `EMSGSIZE`, leaving the existing
    caller cleanup paths responsible for freeing `m0`, `ni`, and the unused
    transfer buffer.
    
    Reachable via root / bpf access
    
    Reviewed by:    bz, adrian
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D58898
---
 sys/dev/usb/wlan/if_rsu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c
index 2f934737f699..68271f365dd5 100644
--- a/sys/dev/usb/wlan/if_rsu.c
+++ b/sys/dev/usb/wlan/if_rsu.c
@@ -2917,6 +2917,9 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
 	 */
 	txd->txdw3 |= htole32(SM(R92S_TXDW3_SEQ, prio));
 
+	if (m0->m_pkthdr.len > RSU_TXBUFSZ - sizeof(*txd))
+		return (EMSGSIZE);
+
 	if (ieee80211_radiotap_active_vap(vap)) {
 		struct rsu_tx_radiotap_header *tap = &sc->sc_txtap;
 
@@ -2925,7 +2928,6 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
 	}
 
 	xferlen = sizeof(*txd) + m0->m_pkthdr.len;
-	KASSERT(xferlen <= RSU_TXBUFSZ, ("%s: invalid length", __func__));
 	m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&txd[1]);
 
 	data->buflen = xferlen;