329-v4.16-0002-brcmfmac-drop-Inter-Access-Point-Protocol-packets-by.patch 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. From 1259055170287a350cad453e9eac139c81609860 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
  3. Date: Thu, 15 Mar 2018 08:29:09 +0100
  4. Subject: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. Testing brcmfmac with more recent firmwares resulted in AP interfaces
  9. not working in some specific setups. Debugging resulted in discovering
  10. support for IAPP in Broadcom's firmwares.
  11. Older firmwares were only generating 802.11f frames. Newer ones like:
  12. 1) 10.10 (TOB) (r663589)
  13. 2) 10.10.122.20 (r683106)
  14. for 4366b1 and 4366c0 respectively seem to also /respect/ 802.11f frames
  15. in the Tx path by performing a STA disassociation.
  16. This obsoleted standard and its implementation is something that:
  17. 1) Most people don't need / want to use
  18. 2) Can allow local DoS attacks
  19. 3) Breaks AP interfaces in some specific bridge setups
  20. To solve issues it can cause this commit modifies brcmfmac to drop IAPP
  21. packets. If affects:
  22. 1) Rx path: driver won't be sending these unwanted packets up.
  23. 2) Tx path: driver will reject packets that would trigger STA
  24. disassociation perfromed by a firmware (possible local DoS attack).
  25. It appears there are some Broadcom's clients/users who care about this
  26. feature despite the drawbacks. They can switch it on using a new module
  27. param.
  28. This change results in only two more comparisons (check for module param
  29. and check for Ethernet packet length) for 99.9% of packets. Its overhead
  30. should be very minimal.
  31. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
  32. Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
  33. Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  34. ---
  35. .../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 ++
  36. .../wireless/broadcom/brcm80211/brcmfmac/common.h | 1 +
  37. .../wireless/broadcom/brcm80211/brcmfmac/core.c | 57 ++++++++++++++++++++++
  38. 3 files changed, 63 insertions(+)
  39. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
  40. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
  41. @@ -73,6 +73,10 @@ static int brcmf_roamoff;
  42. module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
  43. MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
  44. +static int brcmf_iapp_enable;
  45. +module_param_named(iapp, brcmf_iapp_enable, int, 0);
  46. +MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
  47. +
  48. #ifdef DEBUG
  49. /* always succeed brcmf_bus_started() */
  50. static int brcmf_ignore_probe_fail;
  51. @@ -287,6 +291,7 @@ struct brcmf_mp_device *brcmf_get_module
  52. settings->feature_disable = brcmf_feature_disable;
  53. settings->fcmode = brcmf_fcmode;
  54. settings->roamoff = !!brcmf_roamoff;
  55. + settings->iapp = !!brcmf_iapp_enable;
  56. #ifdef DEBUG
  57. settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
  58. #endif
  59. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
  60. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
  61. @@ -58,6 +58,7 @@ struct brcmf_mp_device {
  62. unsigned int feature_disable;
  63. int fcmode;
  64. bool roamoff;
  65. + bool iapp;
  66. bool ignore_probe_fail;
  67. struct brcmfmac_pd_cc *country_codes;
  68. union {
  69. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
  70. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
  71. @@ -191,6 +191,37 @@ static void brcmf_netdev_set_multicast_l
  72. schedule_work(&ifp->multicast_work);
  73. }
  74. +/**
  75. + * brcmf_skb_is_iapp - checks if skb is an IAPP packet
  76. + *
  77. + * @skb: skb to check
  78. + */
  79. +static bool brcmf_skb_is_iapp(struct sk_buff *skb)
  80. +{
  81. + static const u8 iapp_l2_update_packet[6] __aligned(2) = {
  82. + 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00,
  83. + };
  84. + unsigned char *eth_data;
  85. +#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
  86. + const u16 *a, *b;
  87. +#endif
  88. +
  89. + if (skb->len - skb->mac_len != 6 ||
  90. + !is_multicast_ether_addr(eth_hdr(skb)->h_dest))
  91. + return false;
  92. +
  93. + eth_data = skb_mac_header(skb) + ETH_HLEN;
  94. +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
  95. + return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) |
  96. + ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4))));
  97. +#else
  98. + a = (const u16 *)eth_data;
  99. + b = (const u16 *)iapp_l2_update_packet;
  100. +
  101. + return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]));
  102. +#endif
  103. +}
  104. +
  105. static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
  106. struct net_device *ndev)
  107. {
  108. @@ -210,6 +241,23 @@ static netdev_tx_t brcmf_netdev_start_xm
  109. goto done;
  110. }
  111. + /* Some recent Broadcom's firmwares disassociate STA when they receive
  112. + * an 802.11f ADD frame. This behavior can lead to a local DoS security
  113. + * issue. Attacker may trigger disassociation of any STA by sending a
  114. + * proper Ethernet frame to the wireless interface.
  115. + *
  116. + * Moreover this feature may break AP interfaces in some specific
  117. + * setups. This applies e.g. to the bridge with hairpin mode enabled and
  118. + * IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware
  119. + * will get passed back to the wireless interface and cause immediate
  120. + * disassociation of a just-connected STA.
  121. + */
  122. + if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
  123. + dev_kfree_skb(skb);
  124. + ret = -EINVAL;
  125. + goto done;
  126. + }
  127. +
  128. /* Make sure there's enough writable headroom*/
  129. ret = skb_cow_head(skb, drvr->hdrlen);
  130. if (ret < 0) {
  131. @@ -277,6 +325,15 @@ void brcmf_txflowblock_if(struct brcmf_i
  132. void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
  133. {
  134. + /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new
  135. + * STA connects to the AP interface. This is an obsoleted standard most
  136. + * users don't use, so don't pass these frames up unless requested.
  137. + */
  138. + if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
  139. + brcmu_pkt_buf_free_skb(skb);
  140. + return;
  141. + }
  142. +
  143. if (skb->pkt_type == PACKET_MULTICAST)
  144. ifp->stats.multicast++;