mac80211: backport brcmfmac fixes from 4.16
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
parent
0de2213eea
commit
0f1a1489a6
8 changed files with 345 additions and 3 deletions
|
@ -71,7 +71,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
|||
}
|
||||
|
||||
u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
|
||||
@@ -272,11 +256,16 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
|
||||
@@ -272,11 +256,16 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_
|
||||
u32 data = 0;
|
||||
int retval;
|
||||
|
||||
|
@ -111,7 +111,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
|||
if (ret)
|
||||
*ret = retval;
|
||||
}
|
||||
@@ -540,10 +534,13 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt)
|
||||
@@ -540,10 +534,13 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
|
||||
|
||||
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
From 933897342d0714ae1c10729cbaeecea0c6178db5 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 28 Feb 2018 21:15:19 +0100
|
||||
Subject: [PATCH] brcmfmac: add possibility to obtain firmware error
|
||||
|
||||
The feature module needs to evaluate the actual firmware error return
|
||||
upon a control command. This adds a flag to struct brcmf_if that the
|
||||
caller can set. This flag is checked to determine the error code that
|
||||
needs to be returned.
|
||||
|
||||
Fixes: b69c1df47281 ("brcmfmac: separate firmware errors from i/o errors")
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 10 ++++++++++
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 3 +++
|
||||
3 files changed, 15 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
@@ -181,6 +181,7 @@ enum brcmf_netif_stop_reason {
|
||||
* @netif_stop_lock: spinlock for update netif_stop from multiple sources.
|
||||
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
|
||||
* @pend_8021x_wait: used for signalling change in count.
|
||||
+ * @fwil_fwerr: flag indicating fwil layer should return firmware error codes.
|
||||
*/
|
||||
struct brcmf_if {
|
||||
struct brcmf_pub *drvr;
|
||||
@@ -198,6 +199,7 @@ struct brcmf_if {
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES];
|
||||
u8 ipv6addr_idx;
|
||||
+ bool fwil_fwerr;
|
||||
};
|
||||
|
||||
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
||||
@@ -104,6 +104,9 @@ static void brcmf_feat_iovar_int_get(str
|
||||
u32 data;
|
||||
int err;
|
||||
|
||||
+ /* we need to know firmware error */
|
||||
+ ifp->fwil_fwerr = true;
|
||||
+
|
||||
err = brcmf_fil_iovar_int_get(ifp, name, &data);
|
||||
if (err == 0) {
|
||||
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
|
||||
@@ -112,6 +115,8 @@ static void brcmf_feat_iovar_int_get(str
|
||||
brcmf_dbg(TRACE, "%s feature check failed: %d\n",
|
||||
brcmf_feat_names[id], err);
|
||||
}
|
||||
+
|
||||
+ ifp->fwil_fwerr = false;
|
||||
}
|
||||
|
||||
static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
|
||||
@@ -120,6 +125,9 @@ static void brcmf_feat_iovar_data_set(st
|
||||
{
|
||||
int err;
|
||||
|
||||
+ /* we need to know firmware error */
|
||||
+ ifp->fwil_fwerr = true;
|
||||
+
|
||||
err = brcmf_fil_iovar_data_set(ifp, name, data, len);
|
||||
if (err != -BRCMF_FW_UNSUPPORTED) {
|
||||
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
|
||||
@@ -128,6 +136,8 @@ static void brcmf_feat_iovar_data_set(st
|
||||
brcmf_dbg(TRACE, "%s feature check failed: %d\n",
|
||||
brcmf_feat_names[id], err);
|
||||
}
|
||||
+
|
||||
+ ifp->fwil_fwerr = false;
|
||||
}
|
||||
|
||||
#define MAX_CAPS_BUFFER_SIZE 512
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
|
||||
@@ -131,6 +131,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
|
||||
brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
|
||||
err = -EBADE;
|
||||
}
|
||||
+ if (ifp->fwil_fwerr)
|
||||
+ return fwerr;
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
From 455f3e76cfc0d893585a5f358b9ddbe9c1e1e53b Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 28 Feb 2018 21:15:20 +0100
|
||||
Subject: [PATCH] brcmfmac: fix P2P_DEVICE ethernet address generation
|
||||
|
||||
The firmware has a requirement that the P2P_DEVICE address should
|
||||
be different from the address of the primary interface. When not
|
||||
specified by user-space, the driver generates the MAC address for
|
||||
the P2P_DEVICE interface using the MAC address of the primary
|
||||
interface and setting the locally administered bit. However, the MAC
|
||||
address of the primary interface may already have that bit set causing
|
||||
the creation of the P2P_DEVICE interface to fail with -EBUSY. Fix this
|
||||
by using a random address instead to determine the P2P_DEVICE address.
|
||||
|
||||
Cc: stable@vger.kernel.org # 3.10.y
|
||||
Reported-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 24 ++++++++++------------
|
||||
1 file changed, 11 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
|
||||
@@ -462,25 +462,23 @@ static int brcmf_p2p_set_firmware(struct
|
||||
* @dev_addr: optional device address.
|
||||
*
|
||||
* P2P needs mac addresses for P2P device and interface. If no device
|
||||
- * address it specified, these are derived from the primary net device, ie.
|
||||
- * the permanent ethernet address of the device.
|
||||
+ * address it specified, these are derived from a random ethernet
|
||||
+ * address.
|
||||
*/
|
||||
static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
|
||||
{
|
||||
- struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||
- bool local_admin = false;
|
||||
+ bool random_addr = false;
|
||||
|
||||
- if (!dev_addr || is_zero_ether_addr(dev_addr)) {
|
||||
- dev_addr = pri_ifp->mac_addr;
|
||||
- local_admin = true;
|
||||
- }
|
||||
+ if (!dev_addr || is_zero_ether_addr(dev_addr))
|
||||
+ random_addr = true;
|
||||
|
||||
- /* Generate the P2P Device Address. This consists of the device's
|
||||
- * primary MAC address with the locally administered bit set.
|
||||
+ /* Generate the P2P Device Address obtaining a random ethernet
|
||||
+ * address with the locally administered bit set.
|
||||
*/
|
||||
- memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
|
||||
- if (local_admin)
|
||||
- p2p->dev_addr[0] |= 0x02;
|
||||
+ if (random_addr)
|
||||
+ eth_random_addr(p2p->dev_addr);
|
||||
+ else
|
||||
+ memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
|
||||
|
||||
/* Generate the P2P Interface Address. If the discovery and connection
|
||||
* BSSCFGs need to simultaneously co-exist, then this address must be
|
|
@ -0,0 +1,157 @@
|
|||
From 1259055170287a350cad453e9eac139c81609860 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Thu, 15 Mar 2018 08:29:09 +0100
|
||||
Subject: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
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.
|
||||
|
||||
Older firmwares were only generating 802.11f frames. Newer ones like:
|
||||
1) 10.10 (TOB) (r663589)
|
||||
2) 10.10.122.20 (r683106)
|
||||
for 4366b1 and 4366c0 respectively seem to also /respect/ 802.11f frames
|
||||
in the Tx path by performing a STA disassociation.
|
||||
|
||||
This 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 using a new module
|
||||
param.
|
||||
|
||||
This change results in only two more comparisons (check for module param
|
||||
and check for Ethernet packet length) for 99.9% of packets. Its overhead
|
||||
should be very minimal.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 ++
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/common.h | 1 +
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 57 ++++++++++++++++++++++
|
||||
3 files changed, 63 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
@@ -75,6 +75,10 @@ static int brcmf_roamoff;
|
||||
module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
|
||||
MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
|
||||
|
||||
+static int brcmf_iapp_enable;
|
||||
+module_param_named(iapp, brcmf_iapp_enable, int, 0);
|
||||
+MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
|
||||
+
|
||||
#ifdef DEBUG
|
||||
/* always succeed brcmf_bus_started() */
|
||||
static int brcmf_ignore_probe_fail;
|
||||
@@ -441,6 +445,7 @@ struct brcmf_mp_device *brcmf_get_module
|
||||
settings->feature_disable = brcmf_feature_disable;
|
||||
settings->fcmode = brcmf_fcmode;
|
||||
settings->roamoff = !!brcmf_roamoff;
|
||||
+ settings->iapp = !!brcmf_iapp_enable;
|
||||
#ifdef DEBUG
|
||||
settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
|
||||
#endif
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
|
||||
@@ -58,6 +58,7 @@ struct brcmf_mp_device {
|
||||
unsigned int feature_disable;
|
||||
int fcmode;
|
||||
bool roamoff;
|
||||
+ bool iapp;
|
||||
bool ignore_probe_fail;
|
||||
struct brcmfmac_pd_cc *country_codes;
|
||||
union {
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_l
|
||||
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)
|
||||
+{
|
||||
+ static const u8 iapp_l2_update_packet[6] __aligned(2) = {
|
||||
+ 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00,
|
||||
+ };
|
||||
+ unsigned char *eth_data;
|
||||
+#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
+ const u16 *a, *b;
|
||||
+#endif
|
||||
+
|
||||
+ if (skb->len - skb->mac_len != 6 ||
|
||||
+ !is_multicast_ether_addr(eth_hdr(skb)->h_dest))
|
||||
+ return false;
|
||||
+
|
||||
+ eth_data = skb_mac_header(skb) + ETH_HLEN;
|
||||
+#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
|
||||
+ a = (const u16 *)eth_data;
|
||||
+ b = (const u16 *)iapp_l2_update_packet;
|
||||
+
|
||||
+ 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 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xm
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ /* Some recent Broadcom's firmwares disassociate STA when they receive
|
||||
+ * an 802.11f ADD frame. 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 a just-connected STA.
|
||||
+ */
|
||||
+ if (!drvr->settings->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 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_i
|
||||
|
||||
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
{
|
||||
+ /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new
|
||||
+ * STA connects to the AP interface. This is an obsoleted standard most
|
||||
+ * users don't use, so don't pass these frames up unless requested.
|
||||
+ */
|
||||
+ if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
|
||||
+ brcmu_pkt_buf_free_skb(skb);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (skb->pkt_type == PACKET_MULTICAST)
|
||||
ifp->ndev->stats.multicast++;
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
From 9b9322db5c5a1917a66c71fe47c3848a9a31227e Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Date: Wed, 14 Mar 2018 20:02:59 +0100
|
||||
Subject: [PATCH] brcmfmac: Fix check for ISO3166 code
|
||||
|
||||
The commit "regulatory: add NUL to request alpha2" increases the length of
|
||||
alpha2 to 3. This causes a regression on brcmfmac, because
|
||||
brcmf_cfg80211_reg_notifier() expect valid ISO3166 codes in the complete
|
||||
array. So fix this accordingly.
|
||||
|
||||
Fixes: 657308f73e67 ("regulatory: add NUL to request alpha2")
|
||||
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Acked-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -6803,7 +6803,7 @@ static void brcmf_cfg80211_reg_notifier(
|
||||
return;
|
||||
|
||||
/* ignore non-ISO3166 country codes */
|
||||
- for (i = 0; i < sizeof(req->alpha2); i++)
|
||||
+ for (i = 0; i < 2; i++)
|
||||
if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
|
||||
brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
|
||||
req->alpha2[0], req->alpha2[1]);
|
|
@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -1238,6 +1238,7 @@ int __init brcmf_core_init(void)
|
||||
@@ -1295,6 +1295,7 @@ int __init brcmf_core_init(void)
|
||||
{
|
||||
if (!schedule_work(&brcmf_driver_work))
|
||||
return -EBUSY;
|
||||
|
|
Loading…
Reference in a new issue