From nobody Fri Apr 25 05:38:42 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ZkM8L4zwGz5vGY1; Fri, 25 Apr 2025 05:38:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZkM8L3hrRz4MvB; Fri, 25 Apr 2025 05:38:42 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1745559522; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tZf5XCocUZLACXGNOxSkMacAc2OPmIRpI37iQlzlSog=; b=pj1M6hBh0hkrU6rPHpdRw7fg2wUJ+e7s18qGxHjGdtrRZ1PlNcVwStMzh3VrxHuqNDR1rJ vzJuvcK9lj/Bb3TDAB0Ag1Q3lrKECgKYhjMIU19V8XsDH6onxxb+c3RCV5I2t69vRLYUI2 rpWz/LubcuP0/5qOBrjR14kU3egR9qD7+tMn47psLBuUV0L5Z2Xu81I/V3OpNTUfi8D3d6 xLQtctDoMzFlfJKdrmWDPWFqJT2MC3DLXLiwqduZj2oBAPb0Ff2q97BzFPWWV7KB9OYKAm nIT/9glNEJdn/g5F7A2/gQFKiGk3r0p3JhO9sXm+oin7m3slRY2YP0ZS0uDU6Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1745559522; a=rsa-sha256; cv=none; b=Wc3cH40/Cf3D4pd56r+4de9AlFR6ips9Dw4s7dXznZjFJodhtQDwqaKEzRBE/TWOQUehRU 7D/IFpJn4ohMzlBT68P1PCHFBOu7Or6pIURubMjc6jR2b5EiiwMtFn+nZWWzeC0Xk+7vQo cWxK+CbayQI3waMN+MDdlfOOZVG5CVB1ZZqdKbewsh5tQEvCO7kWxBSj0GnOD+NGMABFuv 5xUR8fw/qMMDqZ2d/k/XK7PPMUVdkyfmePr+YbOPr6LVez3dOKaWfjoJUrrVX1yifPwkVf IUEGfGrCC7zsWfU6g91ytWT11VpQYIIIYBdtT3OozH6qha2snPDCjBKfdDWxeA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1745559522; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tZf5XCocUZLACXGNOxSkMacAc2OPmIRpI37iQlzlSog=; b=B3c+utYVc4aExO9W6jIaD2Gy5cmiL5KtfzahlUOKbhrVWKSsbNQlN+c1sum06l74ZW61UL ZqIn4Uc4AWVii2fhvGHNLuwCp6Rws6g1Nxy/tbkIFiW4FLxb0h9QTvb0T7KcER4Kk8xYbf 2Vo62l6KiDC6ENfP1WDufU9qxLfiNEfJxKerLDSrie54ci09Ve+UO31E53juF9ePXBG9nb UcSdKrH4RptKGZHzhzp4UYZ15KvbsDaP1uLoSu2+Hc46Df6Ii8OYmNNRimNCRyovCZzkFY Whh/xxgo3SgoI9cJQ3xm6y2lljdKzKOdegibKgXqst4jr5pQnjBVqQL0isEJPQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ZkM8L2nRtz6KV; Fri, 25 Apr 2025 05:38:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 53P5cgXL060802; Fri, 25 Apr 2025 05:38:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53P5cgkc060799; Fri, 25 Apr 2025 05:38:42 GMT (envelope-from git) Date: Fri, 25 Apr 2025 05:38:42 GMT Message-Id: <202504250538.53P5cgkc060799@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Adrian Chadd Subject: git: 267e8f64e4d3 - main - net80211: validate control frame TA/RA before further processing List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: adrian X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 267e8f64e4d366ce6901cea5e360af528acb0887 Auto-Submitted: auto-generated The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=267e8f64e4d366ce6901cea5e360af528acb0887 commit 267e8f64e4d366ce6901cea5e360af528acb0887 Author: Adrian Chadd AuthorDate: 2025-03-30 00:03:17 +0000 Commit: Adrian Chadd CommitDate: 2025-04-25 05:35:49 +0000 net80211: validate control frame TA/RA before further processing An earlier commit relaxed the TA/RA rules around control frames to fix other issues, however it now results in control frames not specifically from a known node / to us to be handled in the control path. Specifically, rtwn(4) RTL8812/RTL8821 NICs are currently passing BARs from the AP TA to any destination to us; which is tripping up BAW tracking and causing traffic hangs. So do the check before vap->iv_recv_ctl() is called in each input path. Note that mesh doesn't seem to pass the control frames up; however I haven't tested/validated mesh in a long while and I know it's currently broken. Differential Revision: https://reviews.freebsd.org/D49575 --- sys/net80211/ieee80211.c | 54 +++++++++++++++++++++++++++++++++++++++++ sys/net80211/ieee80211_adhoc.c | 3 ++- sys/net80211/ieee80211_hostap.c | 3 ++- sys/net80211/ieee80211_sta.c | 4 ++- sys/net80211/ieee80211_var.h | 3 +++ 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 9d036f298ed3..dbc7023c7fee 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -2732,3 +2732,57 @@ ieee80211_is_key_unicast(const struct ieee80211vap *vap, */ return (!ieee80211_is_key_global(vap, key)); } + +/** + * Determine whether the given control frame is from a known node + * and destined to us. + * + * In some instances a control frame won't have a TA (eg ACKs), so + * we should only verify the RA for those. + * + * @param ni ieee80211_node representing the sender, or BSS node + * @param m0 mbuf representing the 802.11 frame. + * @returns false if the frame is not a CTL frame (with a warning logged); + * true if the frame is from a known sender / valid recipient, + * false otherwise. + */ +bool +ieee80211_is_ctl_frame_for_vap(struct ieee80211_node *ni, const struct mbuf *m0) +{ + const struct ieee80211vap *vap = ni->ni_vap; + const struct ieee80211_frame *wh; + uint8_t subtype; + + wh = mtod(m0, const struct ieee80211_frame *); + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + + /* Verify it's a ctl frame. */ + KASSERT(IEEE80211_IS_CTL(wh), ("%s: not a CTL frame (fc[0]=0x%04x)", + __func__, wh->i_fc[0])); + if (!IEEE80211_IS_CTL(wh)) { + if_printf(vap->iv_ifp, + "%s: not a control frame (fc[0]=0x%04x)\n", + __func__, wh->i_fc[0]); + return (false); + } + + /* Verify the TA if present. */ + switch (subtype) { + case IEEE80211_FC0_SUBTYPE_CTS: + case IEEE80211_FC0_SUBTYPE_ACK: + /* No TA. */ + break; + default: + /* + * Verify TA matches ni->ni_macaddr; for unknown + * sources it will be the BSS node and ni->ni_macaddr + * will the BSS MAC. + */ + if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) + return (false); + break; + } + + /* Verify the RA */ + return (IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr)); +} diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index 77e5a2d99904..210c9fc75bd9 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -661,7 +661,8 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, case IEEE80211_FC0_TYPE_CTL: vap->iv_stats.is_rx_ctl++; IEEE80211_NODE_STAT(ni, rx_ctrl); - vap->iv_recv_ctl(ni, m, subtype); + if (ieee80211_is_ctl_frame_for_vap(ni, m)) + vap->iv_recv_ctl(ni, m, subtype); goto out; default: diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index c9e2c4896f15..1573d83f4cb4 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -889,7 +889,8 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, case IEEE80211_FC0_TYPE_CTL: vap->iv_stats.is_rx_ctl++; IEEE80211_NODE_STAT(ni, rx_ctrl); - vap->iv_recv_ctl(ni, m, subtype); + if (ieee80211_is_ctl_frame_for_vap(ni, m)) + vap->iv_recv_ctl(ni, m, subtype); goto out; default: IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 48d56d0ad217..887eb81dd3c4 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -972,7 +972,8 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, case IEEE80211_FC0_TYPE_CTL: vap->iv_stats.is_rx_ctl++; IEEE80211_NODE_STAT(ni, rx_ctrl); - vap->iv_recv_ctl(ni, m, subtype); + if (ieee80211_is_ctl_frame_for_vap(ni, m)) + vap->iv_recv_ctl(ni, m, subtype); goto out; default: @@ -2054,6 +2055,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, static void sta_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype) { + switch (subtype) { case IEEE80211_FC0_SUBTYPE_BAR: ieee80211_recv_bar(ni, m); diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index e011d2dd32ed..91beaec6f997 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -845,6 +845,9 @@ bool ieee80211_is_key_global(const struct ieee80211vap *vap, bool ieee80211_is_key_unicast(const struct ieee80211vap *vap, const struct ieee80211_key *key); +bool ieee80211_is_ctl_frame_for_vap(struct ieee80211_node *, + const struct mbuf *); + void ieee80211_radiotap_attach(struct ieee80211com *, struct ieee80211_radiotap_header *th, int tlen, uint32_t tx_radiotap,