From: Greg Kroah-Hartman Date: Mon, 5 Nov 2012 14:04:27 +0000 (+0100) Subject: 3.6-stable patches X-Git-Tag: v3.0.52~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0a7d2f5fca5644d5e0738f71bf6e541605c3f496;p=thirdparty%2Fkernel%2Fstable-queue.git 3.6-stable patches 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 --- 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 index 00000000000..ba110d7b4b4 --- /dev/null +++ b/queue-3.6/mac80211-check-management-frame-header-length.patch @@ -0,0 +1,52 @@ +From 4a4f1a5808c8bb0b72a4f6e5904c53fb8c9cd966 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 26 Oct 2012 00:33:36 +0200 +Subject: mac80211: check management frame header length + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..80c602df78a --- /dev/null +++ b/queue-3.6/mac80211-fix-ssid-copy-on-ibss-join.patch @@ -0,0 +1,36 @@ +From badecb001a310408d3473b1fc2ed5aefd0bc92a9 Mon Sep 17 00:00:00 2001 +From: Antonio Quartulli +Date: Fri, 26 Oct 2012 18:54:25 +0200 +Subject: mac80211: fix SSID copy on IBSS JOIN + +From: Antonio Quartulli + +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 +[rewrapped commit message, small rewording] +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..1df77658b37 --- /dev/null +++ b/queue-3.6/mac80211-make-sure-data-is-accessible-in-eapol-check.patch @@ -0,0 +1,49 @@ +From 6dbda2d00d466225f9db1dc695ff852443f28832 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 26 Oct 2012 00:41:23 +0200 +Subject: mac80211: make sure data is accessible in EAPOL check + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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, ðertype, 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 index 00000000000..13554ca4abc --- /dev/null +++ b/queue-3.6/mac80211-verify-that-skb-data-is-present.patch @@ -0,0 +1,135 @@ +From 9b395bc3be1cebf0144a127c7e67d56dbdac0930 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 26 Oct 2012 00:36:40 +0200 +Subject: mac80211: verify that skb data is present + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-3.6/series b/queue-3.6/series index 589997afa56..be5924085f7 100644 --- a/queue-3.6/series +++ b/queue-3.6/series @@ -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