From patchwork Wed Mar 14 11:01:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 10281859 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6056C60211 for ; Wed, 14 Mar 2018 11:01:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4F703285DB for ; Wed, 14 Mar 2018 11:01:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4304D28833; Wed, 14 Mar 2018 11:01:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 39A19285DB for ; Wed, 14 Mar 2018 11:01:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751440AbeCNLBm (ORCPT ); Wed, 14 Mar 2018 07:01:42 -0400 Received: from mail-lf0-f65.google.com ([209.85.215.65]:37196 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751005AbeCNLBk (ORCPT ); Wed, 14 Mar 2018 07:01:40 -0400 Received: by mail-lf0-f65.google.com with SMTP id y19-v6so4122245lfd.4; Wed, 14 Mar 2018 04:01:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=AkoMZDXfGUTa6tVJvaSZBUTy1Q4gnIKW3nBMMD1QsYg=; b=s0YYoMsAbnmJVL8bh1Sf/EjajTk5UhDmbMWJkrYbxSLlOIZLlATj2EK929mt1I0E/a DBf7a5xmasEO0xIGMMS8u0SyRqGV6GUEWRSZWWRFOcbM5fuqi98XC5j6s998IZlmLC/c zUh6P+2AMubumGvCLUrWDfahyoLRVFl+cn6B89LF8n8cQflIQmx2VAjOEAE3CfgSx+YM G6smoBLN1mwWTfIKlpc2vyQOSXrc3VcmahUwjKJ+fKtkTvzzn5KybCP6y02tYz3g1/8M bQm/fz/powvoQSpacfayYfLdKrgJ4RySLYJldrD3QKeMjc7loRiLrwySuqKR42L6UZZM 377g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=AkoMZDXfGUTa6tVJvaSZBUTy1Q4gnIKW3nBMMD1QsYg=; b=UgJu9aECIeE2MunlMkL6pr3XN1PvRJ5RlCea8ENajLvtjMyjKYfTEkKBvmmidnCTQn 6exl8OxPGudIlO/5j3GPUmVyrbhtTtJ9ddIGNTuj0gSZJqdEPQmGfWqYjtv3Y2paptLd a27M2RT28cxp0h2EWtVEMYyOlYrc4D2ghL5S1Dy4g5hx3gximZ8QNQ7KKCWsu3VU3l6E z9nlIsvAEb6IdkQjxS9km98ZpkKVb57fC+FQ0IDMhQaUSi32lOuN3oY2TT2MWOSMpPuj EBLtRTY1o1Mw8undUuTHPih3DyP09/dY75GFK8/ULqUQUiPndYm44LaiaXkIgQfJlXIY TdNg== X-Gm-Message-State: AElRT7Ghxhca4F6ZJVJ61PZo7umEHexGBQLcn/rZKN7V1XkpipZHkjMs vCO6I83kNG7/MKJHecXg2X4= X-Google-Smtp-Source: AG47ELu0NMjLrEwon9TNtQNzUSDkBr9VoJRuXZud11nvU3fs2cfTk8fGoOOApQwMHZjW4eEv0fl/QA== X-Received: by 2002:a19:5c84:: with SMTP id u4-v6mr3026940lfi.14.1521025298937; Wed, 14 Mar 2018 04:01:38 -0700 (PDT) Received: from linux-samsung.lan (ip-194-187-74-233.konfederacka.maverick.com.pl. [194.187.74.233]) by smtp.gmail.com with ESMTPSA id i8-v6sm564970lfg.90.2018.03.14.04.01.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Mar 2018 04:01:38 -0700 (PDT) From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= To: Kalle Valo Cc: Arend van Spriel , Franky Lin , Hante Meuleman , Chi-Hsien Lin , Wright Feng , Pieter-Paul Giesberts , James Hughes , linux-wireless@vger.kernel.org, brcm80211-dev-list.pdl@broadcom.com, brcm80211-dev-list@cypress.com, netdev@vger.kernel.org, =?UTF-8?q?Linus=20L=C3=BCssing?= , Felix Fietkau , bridge@lists.linux-foundation.org, =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Subject: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default Date: Wed, 14 Mar 2018 12:01:19 +0100 Message-Id: <20180314110119.13631-1-zajec5@gmail.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Rafał Miłecki Testing brcmfmac with more recent firmwares resulted in AP interfaces not working in some specific setups. Debugging resulted in discovering support for IAPP in Broadcom's firmwares. This is an obsoleted standard and its implementation is something that: 1) Most people don't need / want to use 2) Can allow local DoS attacks 3) Breaks AP interfaces in some specific bridge setups To solve issues it can cause this commit modifies brcmfmac to drop IAPP packets. If affects: 1) Rx path: driver won't be sending these unwanted packets up. 2) Tx path: driver will reject packets that would trigger STA disassociation perfromed by a firmware (possible local DoS attack). It appears there are some Broadcom's clients/users who care about this feature despite the drawbacks. They can switch it on by a newly added Kconfig option. Signed-off-by: Rafał Miłecki Reviewed-by: Arend van Spriel --- drivers/net/wireless/broadcom/brcm80211/Kconfig | 20 +++++++++++ .../wireless/broadcom/brcm80211/brcmfmac/core.c | 39 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/Kconfig b/drivers/net/wireless/broadcom/brcm80211/Kconfig index 9d99eb42d917..876787ef991a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/Kconfig +++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig @@ -68,6 +68,26 @@ config BRCMFMAC_PCIE IEEE802.11ac embedded FullMAC WLAN driver. Say Y if you want to use the driver for an PCIE wireless card. +config BRCMFMAC_IAPP + bool "Partial support for obsoleted Inter-Access Point Protocol" + depends on BRCMFMAC + ---help--- + Most of Broadcom's firmwares can send 802.11f ADD frame every + time new STA connects to the AP interface. Some recent ones + can also disassociate STA when they receive such a frame. + + It's important to understand this behavior can lead to a local + DoS security issue. Attacker may trigger disassociation of any + STA by sending a proper Ethernet frame to the wireless + interface. + + Moreover this feature may break AP interfaces in some specific + setups. This applies e.g. to the bridge with hairpin mode + enabled and IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet + generated by a firmware will get passed back to the wireless + interface and cause immediate disassociation of just-connected + STA. + config BRCM_TRACING bool "Broadcom device tracing" depends on BRCMSMAC || BRCMFMAC diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 19048526b4af..db6987015fb1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -230,6 +230,34 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev) schedule_work(&ifp->multicast_work); } +/** + * brcmf_skb_is_iapp - checks if skb is an IAPP packet + * + * @skb: skb to check + */ +static bool brcmf_skb_is_iapp(struct sk_buff *skb) +{ + const u8 iapp_l2_update_packet[6] __aligned(2) = { + 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00, + }; + unsigned char *eth_data = skb_mac_header(skb) + ETH_HLEN; +#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + const u16 *a = (const u16 *)eth_data; + const u16 *b = (const u16 *)iapp_l2_update_packet; +#endif + + if (skb->len - skb->mac_len != 6 || + !is_multicast_ether_addr(eth_hdr(skb)->h_dest)) + return false; + +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) | + ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4)))); +#else + return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])); +#endif +} + static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) { @@ -250,6 +278,12 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, goto done; } + if (!IS_ENABLED(CONFIG_BRCMFMAC_IAPP) && brcmf_skb_is_iapp(skb)) { + dev_kfree_skb(skb); + ret = -EINVAL; + goto done; + } + /* Make sure there's enough writeable headroom */ if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) { head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0); @@ -325,6 +359,11 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) { + if (!IS_ENABLED(CONFIG_BRCMFMAC_IAPP) && brcmf_skb_is_iapp(skb)) { + brcmu_pkt_buf_free_skb(skb); + return; + } + if (skb->pkt_type == PACKET_MULTICAST) ifp->ndev->stats.multicast++;