diff options
Diffstat (limited to 'package/kernel/mac80211/patches/352-mac80211-fix-use-after-free-in-defragmentation.patch')
-rw-r--r-- | package/kernel/mac80211/patches/352-mac80211-fix-use-after-free-in-defragmentation.patch | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/352-mac80211-fix-use-after-free-in-defragmentation.patch b/package/kernel/mac80211/patches/352-mac80211-fix-use-after-free-in-defragmentation.patch new file mode 100644 index 0000000000..f7472e0a4e --- /dev/null +++ b/package/kernel/mac80211/patches/352-mac80211-fix-use-after-free-in-defragmentation.patch @@ -0,0 +1,50 @@ +From: Johannes Berg <johannes.berg@intel.com> +Date: Mon, 3 Nov 2014 14:29:09 +0100 +Subject: [PATCH] mac80211: fix use-after-free in defragmentation + +Upon receiving the last fragment, all but the first fragment +are freed, but the multicast check for statistics at the end +of the function refers to the current skb (the last fragment) +causing a use-after-free bug. + +Since multicast frames cannot be fragmented and we check for +this early in the function, just modify that check to also +do the accounting to fix the issue. + +Cc: stable@vger.kernel.org +Reported-by: Yosef Khyal <yosefx.khyal@intel.com> +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1678,11 +1678,14 @@ ieee80211_rx_h_defragment(struct ieee802 + sc = le16_to_cpu(hdr->seq_ctrl); + frag = sc & IEEE80211_SCTL_FRAG; + +- if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || +- is_multicast_ether_addr(hdr->addr1))) { +- /* not fragmented */ ++ if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) ++ goto out; ++ ++ if (is_multicast_ether_addr(hdr->addr1)) { ++ rx->local->dot11MulticastReceivedFrameCount++; + goto out; + } ++ + I802_DEBUG_INC(rx->local->rx_handlers_fragments); + + if (skb_linearize(rx->skb)) +@@ -1775,10 +1778,7 @@ ieee80211_rx_h_defragment(struct ieee802 + out: + if (rx->sta) + rx->sta->rx_packets++; +- if (is_multicast_ether_addr(hdr->addr1)) +- rx->local->dot11MulticastReceivedFrameCount++; +- else +- ieee80211_led_rx(rx->local); ++ ieee80211_led_rx(rx->local); + return RX_CONTINUE; + } + |