From nobody Tue Mar 15 18:16:16 2022 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 AADE61A24D71; Tue, 15 Mar 2022 18:16:16 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4KJ1nD2vnkz58br; Tue, 15 Mar 2022 18:16:16 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647368176; 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=q8Z6LdM6+qcsJscuiZ/QNjo1JhnGVkwb0D6z2h2wZTw=; b=naEw33nZIILLkiEtOu9Q65wb5M8jcvNVeNzZf2Sf1vJWobcAXUrdgLUTwyclR60VEBoSD4 qGlw3Rf89xIrGdjZ8ol4CL7fr/kXY7XHnYZxtvgH4Ct66HIFWYmrNiC481M0R6AmGODnXc nANohaS2tUt5B5K+kyM/Hslrq0IX3tT81IyMjNzIoRbi0j041oWwWEO47SlelgIqSBQxqE Rn/ibSmslQuyO5wOykk7WPdbuMuc5Y84dp+db0g0l1XtG/E/iYOfEhr3zhke4yQOBZPGVm MI7VwdWJHPtfj1L5KTSLNU5zLjmO7KWT4Tlvg7L8qCIC/+6k8Rfl0LYeXGfaBg== 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 288E7266C4; Tue, 15 Mar 2022 18:16:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 22FIGG7l075645; Tue, 15 Mar 2022 18:16:16 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 22FIGGnb075644; Tue, 15 Mar 2022 18:16:16 GMT (envelope-from git) Date: Tue, 15 Mar 2022 18:16:16 GMT Message-Id: <202203151816.22FIGGnb075644@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: 060c556da720 - releng/12.3 - net80211: reject mixed plaintext/encrypted fragments 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: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/releng/12.3 X-Git-Reftype: branch X-Git-Commit: 060c556da720145912ac79f67e91ef656f74a78b Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647368176; 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=q8Z6LdM6+qcsJscuiZ/QNjo1JhnGVkwb0D6z2h2wZTw=; b=cO7h5L7SZzmZihq1oGaD+agHlH/7ta5NWuDJCxDYUmDobnMc+4dy//dXiylxQvx1mjw6lg CIc3mujub29IpJs4tjJR/+iW6v4pIxMr9vaLURp+Mk3Tg1qdTiUJNboamv8Lwm6qAGuaen Wm8zirCGSvcDpSwEOwFVXmmyWfrmkJuJIciLGl8tsAMZfjJSSCo4G46xUeiRJJmZFNdH/0 0vM32IQ5xQoRN2R8tjgFm0AU6pQUagHzctkvAxTXC1q9z1N3r/wurCEb2sE+EFdo1o+UgT YZLUZvrDWXoimesnRZvzOEKX0afT8JO4reYO/neBC/9Ula8UaxFJKX6ItuzBUQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1647368176; a=rsa-sha256; cv=none; b=iFPkUxtVRLjAA+zx3Z6vXJqiw8eKZthwOYqOOVgvfGr7J1pJGpMi/NqMYzh0+F0CjTRdje 3agbvOcoNCr8tni/abh4b2761q5VZow9Ba5uNpwmzd2dQBH8GyGPwL6Fhnkaxl4Yk8W3XO wHBDUwwwBDDPGiXZgzfn/HlAT/aQgk3mKsJvT4/8dzm6+PKfAs6HrTZ+6CEYTF0RLPJwTT nCRBkiKYBwMDmB80Q61ojZQEkKyaKb2NQsviBlR45/zJ3I2WArY2ggyCOuzV1+/w14lJB7 KnbMiK32boMU8Jw8gOinXqrE/yCs+wHdiaZSqTDK+zzb8u7Yck6h8uqcqmnIyw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch releng/12.3 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=060c556da720145912ac79f67e91ef656f74a78b commit 060c556da720145912ac79f67e91ef656f74a78b Author: Mathy Vanhoef AuthorDate: 2021-06-06 22:10:41 +0000 Commit: Mark Johnston CommitDate: 2022-03-15 18:16:01 +0000 net80211: reject mixed plaintext/encrypted fragments ieee80211_defrag() accepts fragmented 802.11 frames in a protected Wi-Fi network even when some of the fragments are not encrypted. Track whether the fragments are encrypted or not and only accept successive ones if they match the state of the first fragment. This relates to section 6.3 in the 2021 Usenix "FragAttacks" (Fragment and Forge: Breaking Wi-Fi Through Frame Aggregation and Fragmentation) paper. Submitted by: Mathy Vanhoef (Mathy.Vanhoef kuleuven.be) Security: CVE-2020-26147 PR: 256118 (cherry picked from commit 11572d7d7fb9802ceb46ea9dc6cbe3bb95373e55) (cherry picked from commit e13d483c5677d12b52f1c81537d54faa85ed43b9) (cherry picked from commit 00cd5a2f614ae2cf1daa30cde7f91de9cdde2393) Approved by: so Security: FreeBSD-SA-22:02.wifi --- sys/net80211/ieee80211_adhoc.c | 2 +- sys/net80211/ieee80211_hostap.c | 2 +- sys/net80211/ieee80211_input.c | 21 ++++++++++++++++++--- sys/net80211/ieee80211_input.h | 2 +- sys/net80211/ieee80211_mesh.c | 2 +- sys/net80211/ieee80211_sta.c | 2 +- sys/net80211/ieee80211_wds.c | 2 +- 7 files changed, 24 insertions(+), 9 deletions(-) diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index c97b99425caa..e2164bbb46a1 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -531,7 +531,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, * Next up, any fragmentation. */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - m = ieee80211_defrag(ni, m, hdrspace); + m = ieee80211_defrag(ni, m, hdrspace, has_decrypted); if (m == NULL) { /* Fragment dropped or frame not complete yet */ goto out; diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index 8c132332f86b..8183d3e9b25a 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -719,7 +719,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, * Next up, any fragmentation. */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - m = ieee80211_defrag(ni, m, hdrspace); + m = ieee80211_defrag(ni, m, hdrspace, has_decrypted); if (m == NULL) { /* Fragment dropped or frame not complete yet */ goto out; diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 979e9aef9d12..5b2d2c15cc12 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -170,7 +170,8 @@ ieee80211_input_mimo_all(struct ieee80211com *ic, struct mbuf *m) * XXX should handle 3 concurrent reassemblies per-spec. */ struct mbuf * -ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace) +ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace, + int has_decrypted) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); @@ -189,6 +190,11 @@ ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace) if (!more_frag && fragno == 0 && ni->ni_rxfrag[0] == NULL) return m; + /* Temporarily set flag to remember if fragment was encrypted. */ + /* XXX use a non-packet altering storage for this in the future. */ + if (has_decrypted) + wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; + /* * Remove frag to insure it doesn't get reaped by timer. */ @@ -219,10 +225,14 @@ ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace) lwh = mtod(mfrag, struct ieee80211_frame *); last_rxseq = le16toh(*(uint16_t *)lwh->i_seq); - /* NB: check seq # and frag together */ + /* + * NB: check seq # and frag together. Also check that both + * fragments are plaintext or that both are encrypted. + */ if (rxseq == last_rxseq+1 && IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) && - IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) { + IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2) && + !((wh->i_fc[1] ^ lwh->i_fc[1]) & IEEE80211_FC1_PROTECTED)) { /* XXX clear MORE_FRAG bit? */ /* track last seqnum and fragno */ *(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq; @@ -253,6 +263,11 @@ ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace) ni->ni_rxfrag[0] = mfrag; mfrag = NULL; } + /* Remember to clear protected flag that was temporarily set. */ + if (mfrag != NULL) { + wh = mtod(mfrag, struct ieee80211_frame *); + wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; + } return mfrag; } diff --git a/sys/net80211/ieee80211_input.h b/sys/net80211/ieee80211_input.h index 5959319c76d7..ae2b4644cc9e 100644 --- a/sys/net80211/ieee80211_input.h +++ b/sys/net80211/ieee80211_input.h @@ -309,7 +309,7 @@ fail: void ieee80211_deliver_data(struct ieee80211vap *, struct ieee80211_node *, struct mbuf *); struct mbuf *ieee80211_defrag(struct ieee80211_node *, - struct mbuf *, int); + struct mbuf *, int, int); struct mbuf *ieee80211_realign(struct ieee80211vap *, struct mbuf *, size_t); struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int, uint8_t); diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 217ce51ee1a2..3c8e371d7c5c 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1637,7 +1637,7 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m, */ hdrspace = ieee80211_hdrspace(ic, wh); if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - m = ieee80211_defrag(ni, m, hdrspace); + m = ieee80211_defrag(ni, m, hdrspace, 0); if (m == NULL) { /* Fragment dropped or frame not complete yet */ goto out; diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 56372543a200..42a377f12857 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -795,7 +795,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, * Next up, any fragmentation. */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - m = ieee80211_defrag(ni, m, hdrspace); + m = ieee80211_defrag(ni, m, hdrspace, has_decrypted); if (m == NULL) { /* Fragment dropped or frame not complete yet */ goto out; diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c index 74cc764b856e..dc0d9f8e1afd 100644 --- a/sys/net80211/ieee80211_wds.c +++ b/sys/net80211/ieee80211_wds.c @@ -592,7 +592,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, * Next up, any fragmentation. */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - m = ieee80211_defrag(ni, m, hdrspace); + m = ieee80211_defrag(ni, m, hdrspace, has_decrypted); if (m == NULL) { /* Fragment dropped or frame not complete yet */ goto out;