summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSungjoon Park <sungjoon.park@broadcom.corp-partner.google.com>2022-07-29 16:32:58 +0900
committerRoger Wang <wangroger@google.com>2022-08-25 10:32:41 +0000
commit3b6f5c50f9438ddd87e36048ed35ce8e687c27f3 (patch)
tree736297f5f6499c322e75e63d3d1b19fb9911a7ac
parent2e9acaefb82f551bb9d618ae50cd241e0c94a728 (diff)
downloadbcm4389-3b6f5c50f9438ddd87e36048ed35ce8e687c27f3.tar.gz
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>
-rw-r--r--dhd_linux_tx.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/dhd_linux_tx.c b/dhd_linux_tx.c
index d370c03..3631a0a 100644
--- a/dhd_linux_tx.c
+++ b/dhd_linux_tx.c
@@ -698,6 +698,25 @@ BCMFASTPATH(dhd_start_xmit)(struct sk_buff *skb, struct net_device *net)
bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, __FUNCTION__, __LINE__);
+#ifdef HOST_SFH_LLC
+ /* if upper layer has cloned the skb, ex:- packet filter
+ * unclone the skb, otherwise due to host sfh llc insertion
+ * the upper layer packet capture will show wrong ethernet DA/SA
+ */
+ if (unlikely(skb_cloned(skb))) {
+ int res = 0;
+ gfp_t gfp_flags = CAN_SLEEP() ? GFP_KERNEL : GFP_ATOMIC;
+ res = skb_unclone(skb, gfp_flags);
+ if (res) {
+ DHD_ERROR_RLMT(("%s: sbk_unclone fails ! err = %d\n",
+ __FUNCTION__, res));
+#ifdef CUSTOMER_HW2_DEBUG
+ return -ENOMEM;
+#endif /* CUSTOMER_HW2_DEBUG */
+ }
+ }
+#endif /* HOST_SFH_LLC */
+
/* re-align socket buffer if "skb->data" is odd address */
if (((unsigned long)(skb->data)) & 0x1) {
unsigned char *data = skb->data;