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:33:32 +0000
commit0ca65009a4daedf633d6059449f219f26f180c90 (patch)
treef96a557998f828290d1fb1c2bded9410f07dfef4
parentf8368a1b220d003b849b3666d3109718fc9436b5 (diff)
downloadbcm4389-android-gs-bluejay-5.10-t-qpr1-beta-2.tar.gz
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;