Android t qpr1 beta 2 release 0.5
bcmdhd: HOST_SFH_LLC - unclone the skb in xmit handler if it is in cloned state

Problem:
In HOST_SFH_LLC feature the ethernet header in the skb->data is replaced with SFH+LLC header.
In android world, if an application applies a packet filter, then the kernel clones the skb and hands over the same to the filter.
Cloning of skb does not copy the skb->data area. So when the upper layer application reads the packet received from the packet filter
it may see a wrong ethernet address due to the HOST_SFH_LLC feature having replaced ethernet header with SFH+LLC.
Ex:- in adb bugreport, ARP request Tx is wrongly classified as ARP request Rx and the source mac address is shown as some invalid addr aa:aa:03:00:00:00
2021-06-16T10:49:19.744 - RX aa:aa:03:00:00:00 > 4a:8b:35:18:00:24 arp who-has 192.168.1.100
[4A8B35180024AAAA03000000080600010800060400018E914A8B3518C0A801658C1645CE7F5DC0A80164]

Solution:
As per GG kernel team [b/214957620]:
"To be clear: it is up to the *writer* to call skb_unclone() before writing to make sure they *own* the skb.
(or perhaps if this is some header only change, then something like skb_header_unclone(), skb_cow() or even skb_cow_head() maybe more appropriate - though I don't know the intricacies of using those interfaces: I'm sure netdev@vger mailing list could help, or you could look at other (wifi?) network drivers and what they do - this can't be a rare problem)"

Analysis:
Analysed other wireless drivers in the kernel code, and found that there too before any modification of cloned skb data, either skb copy or clone or equivalent operation is done.
ex:-
/drivers/net/wireless/intel/ipw2x00/libipw_tx.c - libipw_xmit()
net/mac80211/tx.c - ieee80211_xmit()

Fix:
Call skb_unclone on the skb in dhd_start_xmit() if skb_cloned for the skb returns true.

Bug: 214957620
Test: sanity test and performance test are passed.

Change-Id: Idc97e9c0c09b2fcf79c645bd56077309d899cd18
Signed-off-by: Sungjoon Park <sungjoon.park@broadcom.corp-partner.google.com>
1 file changed
tree: f96a557998f828290d1fb1c2bded9410f07dfef4
  1. include/
  2. aiutils.c
  3. bcm_app_utils.c
  4. bcm_l2_filter.c
  5. bcmbloom.c
  6. bcmevent.c
  7. bcmsdh.c
  8. bcmsdh_linux.c
  9. bcmsdh_sdmmc.c
  10. bcmsdh_sdmmc_linux.c
  11. bcmsdspi.h
  12. bcmsdspi_linux.c
  13. bcmsdstd.h
  14. bcmspibrcm.c
  15. bcmstdlib_s.c
  16. bcmutils.c
  17. bcmwifi_channels.c
  18. bcmxtlv.c
  19. BUILD.bazel
  20. copyrights.json
  21. dhd.h
  22. dhd_bitpack.h
  23. dhd_bus.h
  24. dhd_buzzz.h
  25. dhd_cdc.c
  26. dhd_cfg80211.c
  27. dhd_cfg80211.h
  28. dhd_common.c
  29. dhd_custom_cis.c
  30. dhd_custom_google.c
  31. dhd_custom_gpio.c
  32. dhd_custom_memprealloc.c
  33. dhd_custom_msm.c
  34. dhd_dbg.h
  35. dhd_dbg_ring.c
  36. dhd_dbg_ring.h
  37. dhd_debug.c
  38. dhd_debug.h
  39. dhd_debug_linux.c
  40. dhd_event_log_filter.c
  41. dhd_event_log_filter.h
  42. dhd_flowring.c
  43. dhd_flowring.h
  44. dhd_ip.c
  45. dhd_ip.h
  46. dhd_linux.c
  47. dhd_linux.h
  48. dhd_linux_exportfs.c
  49. dhd_linux_lb.c
  50. dhd_linux_pktdump.c
  51. dhd_linux_pktdump.h
  52. dhd_linux_platdev.c
  53. dhd_linux_priv.h
  54. dhd_linux_rx.c
  55. dhd_linux_sched.c
  56. dhd_linux_sock_qos.h
  57. dhd_linux_tx.c
  58. dhd_linux_tx.h
  59. dhd_linux_wq.c
  60. dhd_linux_wq.h
  61. dhd_log_dump.c
  62. dhd_log_dump.h
  63. dhd_mschdbg.c
  64. dhd_mschdbg.h
  65. dhd_msgbuf.c
  66. dhd_pcie.c
  67. dhd_pcie.h
  68. dhd_pcie_linux.c
  69. dhd_pktlog.c
  70. dhd_pktlog.h
  71. dhd_plat.h
  72. dhd_pno.c
  73. dhd_pno.h
  74. dhd_proto.h
  75. dhd_rtt.c
  76. dhd_rtt.h
  77. dhd_sdio.c
  78. dhd_statlog.c
  79. dhd_statlog.h
  80. dhd_wlfc.c
  81. dhd_wlfc.h
  82. frag.c
  83. fwpkg_utils.c
  84. hnd_pktpool.c
  85. hnd_pktq.c
  86. hndlhl.c
  87. hndmem.c
  88. hndpmu.c
  89. Kbuild
  90. Kconfig
  91. linux_osl.c
  92. linux_osl_priv.h
  93. linux_pkt.c
  94. Makefile
  95. pcie_core.c
  96. sbutils.c
  97. siutils.c
  98. siutils_priv.h
  99. wb_regon_coordinator.c
  100. wifi_stats.h
  101. wl_android.c
  102. wl_android.h
  103. wl_cfg80211.c
  104. wl_cfg80211.h
  105. wl_cfg_btcoex.c
  106. wl_cfg_cellavoid.c
  107. wl_cfg_cellavoid.h
  108. wl_cfgnan.c
  109. wl_cfgnan.h
  110. wl_cfgp2p.c
  111. wl_cfgp2p.h
  112. wl_cfgscan.c
  113. wl_cfgscan.h
  114. wl_cfgvendor.c
  115. wl_cfgvendor.h
  116. wl_cfgvif.c
  117. wl_cfgvif.h
  118. wl_linux_mon.c
  119. wl_roam.c
  120. wldev_common.c