From nobody Tue Mar 15 18:14:03 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 034221A22DAF; Tue, 15 Mar 2022 18:14:03 +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 4KJ1kg5X33z572W; Tue, 15 Mar 2022 18:14:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647368043; 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=6u7+vM1txO5RhdsWf5h5Z8x8Gnyl75KzcxzjCMXvu44=; b=w+pDGnQbi4qr/ae9fQUtVJz8vCZ6tqX8hUYOBDih6CBAKjqeyG9Vy16JpaS/7K8cm1h55X la9agYcu0lJCnWF/KaPMPnAJ1zcfIcB0sxAT1G1zma8L4Ix9iOUpdp0vfltt7pvFyn0s73 q6rzMZXpbJwxXJ8KoVdklnplf9PCevtJYxNEIxMdk6PWx17QUaD/8R361FA4t1B57eRfsn Zn7qBj7buJo9gZ0Jt7sPkD1kUG3wSLrRhFB8Jj5t9KQsCM4V6Almsh1yj1P8PbsAo9yMva eTXiEaXzUUhWidh1DgFjFWQ6I3FoOZHcePWUkNhXa1HI4A2GXD5aBG/+jKgmGg== 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 9AB4626C01; Tue, 15 Mar 2022 18:14:03 +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 22FIE3QK074903; Tue, 15 Mar 2022 18:14:03 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 22FIE3qh074902; Tue, 15 Mar 2022 18:14:03 GMT (envelope-from git) Date: Tue, 15 Mar 2022 18:14:03 GMT Message-Id: <202203151814.22FIE3qh074902@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: cf15ab553dd0 - releng/13.0 - 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/13.0 X-Git-Reftype: branch X-Git-Commit: cf15ab553dd0dabd8718995aedbe90e3ff0bc7e1 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647368043; 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=6u7+vM1txO5RhdsWf5h5Z8x8Gnyl75KzcxzjCMXvu44=; b=c2qbcJ4v2Fe5u6eS9cOfA4LjrOX5E5ndu+QVREMpT0qrXQllzFWk0zU59EWf+PwYD5ixxw r7OLKfeyAO0tMkGyAgYlRi7gtrxK0lgcE/BMU10dFumRdblc6kOSSGSRVC2jXrIzaBLbKo CsPjbY4VVGj1l0Z9LiJjWaBKT31hsT7OxzaPvAH6DIb785GoUwcgvHYpcKg/L0Dgg6uYKG RKyiW2avdl5r6dRb5i/k2nuhMDHEbfaIaJB3u1qiMjhxdkcwePiN3RScWndounTtmG0Yyb 1qn61pUe6Sq8cWI/F7AfeIUU+0C0zKtkfXh5aNbfAlPQ17MlR/UF0F7B0RnFFA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1647368043; a=rsa-sha256; cv=none; b=yFhraGoQfm3GmhRa1AAS7GkRCRB3qOTw9fEdXDWcH22EFwFxuL3xPNIIHdbZwYL7IEKLjE JxqOgemfdwN95SGw/QK7OZK7y3b7v4vBTGHX+BwI/AAfubPTovDp3oaQRnxDHyHRVRlmgl F8zRyI3++Cfo717zRBonZOp1ENQtOh93zcl1AOynKGX3sLOzAkqz/CcTmhrkMeVzrCG91v kC03LrUUVMdz2wgBgJSaPWUeEgZJxV7XCCS/qWDSuCvvv9wa+mTkQWl7L1LF+1foP5J4+r mLimzGkK2JviNMfCVWhS1OKvgGnwU2LFBXGUPD1yJJ7Byowe/pOxB+jFSltu0Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch releng/13.0 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=cf15ab553dd0dabd8718995aedbe90e3ff0bc7e1 commit cf15ab553dd0dabd8718995aedbe90e3ff0bc7e1 Author: Mathy Vanhoef AuthorDate: 2021-06-06 22:10:41 +0000 Commit: Mark Johnston CommitDate: 2022-03-15 17:43:54 +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) 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 ea1519b3381d..a23f138802dc 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 8402ade857ff..d2daaea5bda6 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 aa557fc1ec24..eaeceb9d228e 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 810dcbde7978..8ec82eef7369 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); struct mbuf *ieee80211_decap1(struct mbuf *, int *); diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index fdb84a2acb3d..510c986b13e4 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1642,7 +1642,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 43dc8b6dfeca..6d24eadc11a6 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 8eaffcf87733..f59a92b992d7 100644 --- a/sys/net80211/ieee80211_wds.c +++ b/sys/net80211/ieee80211_wds.c @@ -594,7 +594,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;