aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r--net/wireless/util.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index be2ab8c59e3a..3416373a9c0c 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -5,6 +5,7 @@
5 */ 5 */
6#include <linux/bitops.h> 6#include <linux/bitops.h>
7#include <linux/etherdevice.h> 7#include <linux/etherdevice.h>
8#include <linux/slab.h>
8#include <net/cfg80211.h> 9#include <net/cfg80211.h>
9#include <net/ip.h> 10#include <net/ip.h>
10#include "core.h" 11#include "core.h"
@@ -330,11 +331,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
330 if (iftype == NL80211_IFTYPE_MESH_POINT) { 331 if (iftype == NL80211_IFTYPE_MESH_POINT) {
331 struct ieee80211s_hdr *meshdr = 332 struct ieee80211s_hdr *meshdr =
332 (struct ieee80211s_hdr *) (skb->data + hdrlen); 333 (struct ieee80211s_hdr *) (skb->data + hdrlen);
333 hdrlen += ieee80211_get_mesh_hdrlen(meshdr); 334 /* make sure meshdr->flags is on the linear part */
335 if (!pskb_may_pull(skb, hdrlen + 1))
336 return -1;
334 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { 337 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
335 memcpy(dst, meshdr->eaddr1, ETH_ALEN); 338 skb_copy_bits(skb, hdrlen +
336 memcpy(src, meshdr->eaddr2, ETH_ALEN); 339 offsetof(struct ieee80211s_hdr, eaddr1),
340 dst, ETH_ALEN);
341 skb_copy_bits(skb, hdrlen +
342 offsetof(struct ieee80211s_hdr, eaddr2),
343 src, ETH_ALEN);
337 } 344 }
345 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
338 } 346 }
339 break; 347 break;
340 case cpu_to_le16(IEEE80211_FCTL_FROMDS): 348 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
@@ -346,9 +354,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
346 if (iftype == NL80211_IFTYPE_MESH_POINT) { 354 if (iftype == NL80211_IFTYPE_MESH_POINT) {
347 struct ieee80211s_hdr *meshdr = 355 struct ieee80211s_hdr *meshdr =
348 (struct ieee80211s_hdr *) (skb->data + hdrlen); 356 (struct ieee80211s_hdr *) (skb->data + hdrlen);
349 hdrlen += ieee80211_get_mesh_hdrlen(meshdr); 357 /* make sure meshdr->flags is on the linear part */
358 if (!pskb_may_pull(skb, hdrlen + 1))
359 return -1;
350 if (meshdr->flags & MESH_FLAGS_AE_A4) 360 if (meshdr->flags & MESH_FLAGS_AE_A4)
351 memcpy(src, meshdr->eaddr1, ETH_ALEN); 361 skb_copy_bits(skb, hdrlen +
362 offsetof(struct ieee80211s_hdr, eaddr1),
363 src, ETH_ALEN);
364 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
352 } 365 }
353 break; 366 break;
354 case cpu_to_le16(0): 367 case cpu_to_le16(0):
@@ -357,7 +370,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
357 break; 370 break;
358 } 371 }
359 372
360 if (unlikely(skb->len - hdrlen < 8)) 373 if (!pskb_may_pull(skb, hdrlen + 8))
361 return -1; 374 return -1;
362 375
363 payload = skb->data + hdrlen; 376 payload = skb->data + hdrlen;