diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-04-15 16:21:34 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-15 16:21:34 -0400 |
commit | 5c01d5669356e13f0fb468944c1dd4c6a7e978ad (patch) | |
tree | fa43345288d7b25fac92b3b35360a177c4947313 /net/wireless/util.c | |
parent | fea069152614cdeefba4b2bf80afcddb9c217fc8 (diff) | |
parent | a5e944f1d955f3819503348426763e21e0413ba6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/wl12xx/wl1271_main.c
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r-- | net/wireless/util.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c index d3574a4eb3ba..3416373a9c0c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -331,11 +331,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, if (iftype == NL80211_IFTYPE_MESH_POINT) { struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - hdrlen += ieee80211_get_mesh_hdrlen(meshdr); + /* make sure meshdr->flags is on the linear part */ + if (!pskb_may_pull(skb, hdrlen + 1)) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { - memcpy(dst, meshdr->eaddr1, ETH_ALEN); - memcpy(src, meshdr->eaddr2, ETH_ALEN); + skb_copy_bits(skb, hdrlen + + offsetof(struct ieee80211s_hdr, eaddr1), + dst, ETH_ALEN); + skb_copy_bits(skb, hdrlen + + offsetof(struct ieee80211s_hdr, eaddr2), + src, ETH_ALEN); } + hdrlen += ieee80211_get_mesh_hdrlen(meshdr); } break; case cpu_to_le16(IEEE80211_FCTL_FROMDS): @@ -347,9 +354,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, if (iftype == NL80211_IFTYPE_MESH_POINT) { struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - hdrlen += ieee80211_get_mesh_hdrlen(meshdr); + /* make sure meshdr->flags is on the linear part */ + if (!pskb_may_pull(skb, hdrlen + 1)) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A4) - memcpy(src, meshdr->eaddr1, ETH_ALEN); + skb_copy_bits(skb, hdrlen + + offsetof(struct ieee80211s_hdr, eaddr1), + src, ETH_ALEN); + hdrlen += ieee80211_get_mesh_hdrlen(meshdr); } break; case cpu_to_le16(0): @@ -358,7 +370,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, break; } - if (unlikely(skb->len - hdrlen < 8)) + if (!pskb_may_pull(skb, hdrlen + 8)) return -1; payload = skb->data + hdrlen; |