]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Nov 2012 14:04:27 +0000 (15:04 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Nov 2012 14:04:27 +0000 (15:04 +0100)
added patches:
mac80211-check-management-frame-header-length.patch
mac80211-fix-ssid-copy-on-ibss-join.patch
mac80211-make-sure-data-is-accessible-in-eapol-check.patch
mac80211-verify-that-skb-data-is-present.patch

queue-3.6/mac80211-check-management-frame-header-length.patch [new file with mode: 0644]
queue-3.6/mac80211-fix-ssid-copy-on-ibss-join.patch [new file with mode: 0644]
queue-3.6/mac80211-make-sure-data-is-accessible-in-eapol-check.patch [new file with mode: 0644]
queue-3.6/mac80211-verify-that-skb-data-is-present.patch [new file with mode: 0644]
queue-3.6/series

diff --git a/queue-3.6/mac80211-check-management-frame-header-length.patch b/queue-3.6/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);
diff --git a/queue-3.6/mac80211-fix-ssid-copy-on-ibss-join.patch b/queue-3.6/mac80211-fix-ssid-copy-on-ibss-join.patch
new file mode 100644 (file)
index 0000000..80c602d
--- /dev/null
@@ -0,0 +1,36 @@
+From badecb001a310408d3473b1fc2ed5aefd0bc92a9 Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <ordex@autistici.org>
+Date: Fri, 26 Oct 2012 18:54:25 +0200
+Subject: mac80211: fix SSID copy on IBSS JOIN
+
+From: Antonio Quartulli <ordex@autistici.org>
+
+commit badecb001a310408d3473b1fc2ed5aefd0bc92a9 upstream.
+
+The 'ssid' field of the cfg80211_ibss_params is a u8 pointer and
+its length is likely to be less than IEEE80211_MAX_SSID_LEN most
+of the time.
+
+This patch fixes the ssid copy in ieee80211_ibss_join() by using
+the SSID length to prevent it from reading beyond the string.
+
+Signed-off-by: Antonio Quartulli <ordex@autistici.org>
+[rewrapped commit message, small rewording]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/ibss.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -1074,7 +1074,7 @@ int ieee80211_ibss_join(struct ieee80211
+       sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
+       sdata->u.ibss.ibss_join_req = jiffies;
+-      memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
++      memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
+       sdata->u.ibss.ssid_len = params->ssid_len;
+       mutex_unlock(&sdata->u.ibss.mtx);
diff --git a/queue-3.6/mac80211-make-sure-data-is-accessible-in-eapol-check.patch b/queue-3.6/mac80211-make-sure-data-is-accessible-in-eapol-check.patch
new file mode 100644 (file)
index 0000000..1df7765
--- /dev/null
@@ -0,0 +1,49 @@
+From 6dbda2d00d466225f9db1dc695ff852443f28832 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Fri, 26 Oct 2012 00:41:23 +0200
+Subject: mac80211: make sure data is accessible in EAPOL check
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 6dbda2d00d466225f9db1dc695ff852443f28832 upstream.
+
+The code to allow EAPOL frames even when the station
+isn't yet marked associated needs to check that the
+incoming frame is long enough and due to paged RX it
+also can't assume skb->data contains the right data,
+it must use skb_copy_bits(). Fix this to avoid using
+data that doesn't really exist.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/rx.c |   16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -848,14 +848,16 @@ ieee80211_rx_h_check(struct ieee80211_rx
+                */
+               if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
+                   ieee80211_is_data_present(hdr->frame_control)) {
+-                      u16 ethertype;
+-                      u8 *payload;
++                      unsigned int hdrlen;
++                      __be16 ethertype;
+-                      payload = rx->skb->data +
+-                              ieee80211_hdrlen(hdr->frame_control);
+-                      ethertype = (payload[6] << 8) | payload[7];
+-                      if (cpu_to_be16(ethertype) ==
+-                          rx->sdata->control_port_protocol)
++                      hdrlen = ieee80211_hdrlen(hdr->frame_control);
++
++                      if (rx->skb->len < hdrlen + 8)
++                              return RX_DROP_MONITOR;
++
++                      skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
++                      if (ethertype == rx->sdata->control_port_protocol)
+                               return RX_CONTINUE;
+               }
diff --git a/queue-3.6/mac80211-verify-that-skb-data-is-present.patch b/queue-3.6/mac80211-verify-that-skb-data-is-present.patch
new file mode 100644 (file)
index 0000000..13554ca
--- /dev/null
@@ -0,0 +1,135 @@
+From 9b395bc3be1cebf0144a127c7e67d56dbdac0930 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Fri, 26 Oct 2012 00:36:40 +0200
+Subject: mac80211: verify that skb data is present
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 9b395bc3be1cebf0144a127c7e67d56dbdac0930 upstream.
+
+A number of places in the mesh code don't check that
+the frame data is present and in the skb header when
+trying to access. Add those checks and the necessary
+pskb_may_pull() calls. This prevents accessing data
+that doesn't actually exist.
+
+To do this, export ieee80211_get_mesh_hdrlen() to be
+able to use it in mac80211.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/cfg80211.h |    9 +++++++++
+ net/mac80211/rx.c      |   32 +++++++++++++++++++++++++++++++-
+ net/wireless/util.c    |    3 ++-
+ 3 files changed, 42 insertions(+), 2 deletions(-)
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -2633,6 +2633,15 @@ unsigned int ieee80211_get_hdrlen_from_s
+ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
+ /**
++ * ieee80211_get_mesh_hdrlen - get mesh extension header length
++ * @meshhdr: the mesh extension header, only the flags field
++ *    (first byte) will be accessed
++ * Returns the length of the extension header, which is always at
++ * least 6 bytes and at most 18 if address 5 and 6 are present.
++ */
++unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
++
++/**
+  * DOC: Data path helpers
+  *
+  * In addition to generic utilities, cfg80211 also offers
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -491,6 +491,11 @@ ieee80211_rx_mesh_check(struct ieee80211
+               if (ieee80211_is_action(hdr->frame_control)) {
+                       u8 category;
++
++                      /* make sure category field is present */
++                      if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
++                              return RX_DROP_MONITOR;
++
+                       mgmt = (struct ieee80211_mgmt *)hdr;
+                       category = mgmt->u.action.category;
+                       if (category != WLAN_CATEGORY_MESH_ACTION &&
+@@ -1852,6 +1857,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
+       hdr = (struct ieee80211_hdr *) skb->data;
+       hdrlen = ieee80211_hdrlen(hdr->frame_control);
++
++      /* make sure fixed part of mesh header is there, also checks skb len */
++      if (!pskb_may_pull(rx->skb, hdrlen + 6))
++              return RX_DROP_MONITOR;
++
++      mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
++
++      /* make sure full mesh header is there, also checks skb len */
++      if (!pskb_may_pull(rx->skb,
++                         hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
++              return RX_DROP_MONITOR;
++
++      /* reload pointers */
++      hdr = (struct ieee80211_hdr *) skb->data;
+       mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+       /* frame is in RMC, don't forward */
+@@ -1875,9 +1894,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
+               if (is_multicast_ether_addr(hdr->addr1)) {
+                       mpp_addr = hdr->addr3;
+                       proxied_addr = mesh_hdr->eaddr1;
+-              } else {
++              } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
++                      /* has_a4 already checked in ieee80211_rx_mesh_check */
+                       mpp_addr = hdr->addr4;
+                       proxied_addr = mesh_hdr->eaddr2;
++              } else {
++                      return RX_DROP_MONITOR;
+               }
+               rcu_read_lock();
+@@ -2314,6 +2336,10 @@ ieee80211_rx_h_action(struct ieee80211_r
+               }
+               break;
+       case WLAN_CATEGORY_SELF_PROTECTED:
++              if (len < (IEEE80211_MIN_ACTION_SIZE +
++                         sizeof(mgmt->u.action.u.self_prot.action_code)))
++                      break;
++
+               switch (mgmt->u.action.u.self_prot.action_code) {
+               case WLAN_SP_MESH_PEERING_OPEN:
+               case WLAN_SP_MESH_PEERING_CLOSE:
+@@ -2332,6 +2358,10 @@ ieee80211_rx_h_action(struct ieee80211_r
+               }
+               break;
+       case WLAN_CATEGORY_MESH_ACTION:
++              if (len < (IEEE80211_MIN_ACTION_SIZE +
++                         sizeof(mgmt->u.action.u.mesh_action.action_code)))
++                      break;
++
+               if (!ieee80211_vif_is_mesh(&sdata->vif))
+                       break;
+               if (mesh_action_is_path_sel(mgmt) &&
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -309,7 +309,7 @@ unsigned int ieee80211_get_hdrlen_from_s
+ }
+ EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
+-static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
++unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
+ {
+       int ae = meshhdr->flags & MESH_FLAGS_AE;
+       /* 802.11-2012, 8.2.4.7.3 */
+@@ -323,6 +323,7 @@ static int ieee80211_get_mesh_hdrlen(str
+               return 18;
+       }
+ }
++EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
+ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+                          enum nl80211_iftype iftype)
index 589997afa566f0d95d2d0f6a0bd87ce9e0182578..be5924085f776089da8caf1acfd6b46312e66f35 100644 (file)
@@ -20,3 +20,7 @@ drm-udl-fix-stride-issues-scanning-out-stride-width-bpp.patch
 drm-i915-clear-the-entire-sdvo-infoframe-buffer.patch
 drm-i915-fix-overlay-on-i830m.patch
 drm-i915-only-kick-out-vesafb-if-we-takeover-the-fbcon-with-kms.patch
+mac80211-check-management-frame-header-length.patch
+mac80211-verify-that-skb-data-is-present.patch
+mac80211-make-sure-data-is-accessible-in-eapol-check.patch
+mac80211-fix-ssid-copy-on-ibss-join.patch