diff options
author | Harvey Harrison <harvey.harrison@gmail.com> | 2008-07-15 21:44:05 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 16:29:53 -0400 |
commit | 62bf1d762e24006fa9b6c8d56a22cf47a2310af3 (patch) | |
tree | a541e842ae0aff4040e030f320b8e6f03479a22f /net/mac80211/main.c | |
parent | 798ee9850e9bf94b4436f9c7238823322e326885 (diff) |
mac80211: explicitly check skb->len
ieee80211_get_hdrlen_from_skb internally checks the skb is long enough to
hold the full ieee80211_hdr, else it returns zero. Use ieee80211_hdrlen
which always returns the hdrlen and check the remaining room in the
skb explicitly when removing encryption headers or the qos control field.
Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 25 |
1 files changed, 11 insertions, 14 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index aa5a191598c9..f5537f90dd36 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1244,9 +1244,10 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | |||
1244 | struct ieee80211_key *key, | 1244 | struct ieee80211_key *key, |
1245 | struct sk_buff *skb) | 1245 | struct sk_buff *skb) |
1246 | { | 1246 | { |
1247 | int hdrlen, iv_len, mic_len; | 1247 | unsigned int hdrlen, iv_len, mic_len; |
1248 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1248 | 1249 | ||
1249 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1250 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1250 | 1251 | ||
1251 | if (!key) | 1252 | if (!key) |
1252 | goto no_key; | 1253 | goto no_key; |
@@ -1268,24 +1269,20 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | |||
1268 | goto no_key; | 1269 | goto no_key; |
1269 | } | 1270 | } |
1270 | 1271 | ||
1271 | if (skb->len >= mic_len && | 1272 | if (skb->len >= hdrlen + mic_len && |
1272 | !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 1273 | !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
1273 | skb_trim(skb, skb->len - mic_len); | 1274 | skb_trim(skb, skb->len - mic_len); |
1274 | if (skb->len >= iv_len && skb->len > hdrlen) { | 1275 | if (skb->len >= hdrlen + iv_len) { |
1275 | memmove(skb->data + iv_len, skb->data, hdrlen); | 1276 | memmove(skb->data + iv_len, skb->data, hdrlen); |
1276 | skb_pull(skb, iv_len); | 1277 | hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); |
1277 | } | 1278 | } |
1278 | 1279 | ||
1279 | no_key: | 1280 | no_key: |
1280 | { | 1281 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
1281 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1282 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1282 | u16 fc = le16_to_cpu(hdr->frame_control); | 1283 | memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, |
1283 | if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { | 1284 | hdrlen - IEEE80211_QOS_CTL_LEN); |
1284 | fc &= ~IEEE80211_STYPE_QOS_DATA; | 1285 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); |
1285 | hdr->frame_control = cpu_to_le16(fc); | ||
1286 | memmove(skb->data + 2, skb->data, hdrlen - 2); | ||
1287 | skb_pull(skb, 2); | ||
1288 | } | ||
1289 | } | 1286 | } |
1290 | } | 1287 | } |
1291 | 1288 | ||