From 8a006c24809cf2e2a368fdd13d42c55c56b9772b Mon Sep 17 00:00:00 2001 From: Koen Vandeputte Date: Fri, 21 Sep 2018 13:48:53 +0200 Subject: mac80211: backport upstream fixes Backport most significant upstream fixes (excl. hwsim fixes) Refreshed all patches. Contains important fixes for CSA (Channel Switch Announcement) and A-MSDU frames. [slightly altered to apply cleanly] Signed-off-by: Koen Vandeputte --- ...oid-kernel-panic-when-building-AMSDU-from.patch | 102 +++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch (limited to 'package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch') diff --git a/package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch b/package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch new file mode 100644 index 0000000000..66993839ee --- /dev/null +++ b/package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch @@ -0,0 +1,102 @@ +From: Sara Sharon +Date: Wed, 29 Aug 2018 08:57:02 +0200 +Subject: [PATCH] mac80211: avoid kernel panic when building AMSDU from + non-linear SKB + +When building building AMSDU from non-linear SKB, we hit a +kernel panic when trying to push the padding to the tail. +Instead, put the padding at the head of the next subframe. +This also fixes the A-MSDU subframes to not have the padding +accounted in the length field and not have pad at all for +the last subframe, both required by the spec. + +Fixes: 6e0456b54545 ("mac80211: add A-MSDU tx support") +Signed-off-by: Sara Sharon +Reviewed-by: Lorenzo Bianconi +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3064,27 +3064,18 @@ void ieee80211_clear_fast_xmit(struct st + } + + static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local, +- struct sk_buff *skb, int headroom, +- int *subframe_len) ++ struct sk_buff *skb, int headroom) + { +- int amsdu_len = *subframe_len + sizeof(struct ethhdr); +- int padding = (4 - amsdu_len) & 3; +- +- if (skb_headroom(skb) < headroom || skb_tailroom(skb) < padding) { ++ if (skb_headroom(skb) < headroom) { + I802_DEBUG_INC(local->tx_expand_skb_head); + +- if (pskb_expand_head(skb, headroom, padding, GFP_ATOMIC)) { ++ if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { + wiphy_debug(local->hw.wiphy, + "failed to reallocate TX buffer\n"); + return false; + } + } + +- if (padding) { +- *subframe_len += padding; +- skb_put_zero(skb, padding); +- } +- + return true; + } + +@@ -3108,8 +3099,7 @@ static bool ieee80211_amsdu_prepare_head + if (info->control.flags & IEEE80211_TX_CTRL_AMSDU) + return true; + +- if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr), +- &subframe_len)) ++ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr))) + return false; + + data = skb_push(skb, sizeof(*amsdu_hdr)); +@@ -3176,7 +3166,8 @@ static bool ieee80211_amsdu_aggregate(st + void *data; + bool ret = false; + unsigned int orig_len; +- int n = 1, nfrags; ++ int n = 1, nfrags, pad = 0; ++ u16 hdrlen; + + if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) + return false; +@@ -3228,8 +3219,19 @@ static bool ieee80211_amsdu_aggregate(st + if (max_frags && nfrags > max_frags) + goto out; + +- if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + 2, +- &subframe_len)) ++ /* ++ * Pad out the previous subframe to a multiple of 4 by adding the ++ * padding to the next one, that's being added. Note that head->len ++ * is the length of the full A-MSDU, but that works since each time ++ * we add a new subframe we pad out the previous one to a multiple ++ * of 4 and thus it no longer matters in the next round. ++ */ ++ hdrlen = fast_tx->hdr_len - sizeof(rfc1042_header); ++ if ((head->len - hdrlen) & 3) ++ pad = 4 - ((head->len - hdrlen) & 3); ++ ++ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + ++ 2 + pad)) + goto out; + + ret = true; +@@ -3241,6 +3243,8 @@ static bool ieee80211_amsdu_aggregate(st + memcpy(data, &len, 2); + memcpy(data + 2, rfc1042_header, sizeof(rfc1042_header)); + ++ memset(skb_push(skb, pad), 0, pad); ++ + head->len += skb->len; + head->data_len += skb->len; + *frag_tail = skb; -- cgit v1.2.3