]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blobdiff - releases/3.6.7/mac80211-check-management-frame-header-length.patch
Linux 3.6.7
[thirdparty/kernel/stable-queue.git] / releases / 3.6.7 / mac80211-check-management-frame-header-length.patch
diff --git a/releases/3.6.7/mac80211-check-management-frame-header-length.patch b/releases/3.6.7/mac80211-check-management-frame-header-length.patch
new file mode 100644 (file)
index 0000000..ba110d7
--- /dev/null
@@ -0,0 +1,52 @@
+From 4a4f1a5808c8bb0b72a4f6e5904c53fb8c9cd966 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Fri, 26 Oct 2012 00:33:36 +0200
+Subject: mac80211: check management frame header length
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 4a4f1a5808c8bb0b72a4f6e5904c53fb8c9cd966 upstream.
+
+Due to pskb_may_pull() checking the skb length, all
+non-management frames are checked on input whether
+their 802.11 header is fully present. Also add that
+check for management frames and remove a check that
+is now duplicate. This prevents accessing skb data
+beyond the frame end.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/rx.c |   12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1430,7 +1430,6 @@ ieee80211_rx_h_defragment(struct ieee802
+       frag = sc & IEEE80211_SCTL_FRAG;
+       if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
+-                 (rx->skb)->len < 24 ||
+                  is_multicast_ether_addr(hdr->addr1))) {
+               /* not fragmented */
+               goto out;
+@@ -2867,10 +2866,15 @@ static void __ieee80211_rx_handle_packet
+       if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
+               local->dot11ReceivedFragmentCount++;
+-      if (ieee80211_is_mgmt(fc))
+-              err = skb_linearize(skb);
+-      else
++      if (ieee80211_is_mgmt(fc)) {
++              /* drop frame if too short for header */
++              if (skb->len < ieee80211_hdrlen(fc))
++                      err = -ENOBUFS;
++              else
++                      err = skb_linearize(skb);
++      } else {
+               err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
++      }
+       if (err) {
+               dev_kfree_skb(skb);