diff options
author | Andy Green <andy@warmcat.com> | 2007-07-27 09:43:24 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:47:41 -0400 |
commit | 9b8a74e3482f9fc077a88c13fa0ceca8feb0b772 (patch) | |
tree | 0e55e12e233d534de8df14854cdf36ae8391fc5d /net/mac80211/tx.c | |
parent | dfe6e81deaa79c85086c0cc8d85b229e444ab97f (diff) |
[MAC80211]: Improve sanity checks on injected packets
Michael Wu noticed that the skb length checking is not taken care of enough when
a packet is presented on the Monitor interface for injection.
This patch improves the sanity checking and removes fake offsets placed
into the skb network and transport header.
Signed-off-by: Andy Green <andy@warmcat.com>
Signed-off-by: Jiri Benc <jbenc@suse.cz>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 36761c7139bc..457166889cc7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1270,46 +1270,54 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1270 | struct ieee80211_tx_packet_data *pkt_data; | 1270 | struct ieee80211_tx_packet_data *pkt_data; |
1271 | struct ieee80211_radiotap_header *prthdr = | 1271 | struct ieee80211_radiotap_header *prthdr = |
1272 | (struct ieee80211_radiotap_header *)skb->data; | 1272 | (struct ieee80211_radiotap_header *)skb->data; |
1273 | u16 len; | 1273 | u16 len_rthdr; |
1274 | 1274 | ||
1275 | /* | 1275 | /* check for not even having the fixed radiotap header part */ |
1276 | * there must be a radiotap header at the | 1276 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) |
1277 | * start in this case | 1277 | goto fail; /* too short to be possibly valid */ |
1278 | */ | 1278 | |
1279 | if (unlikely(prthdr->it_version)) { | 1279 | /* is it a header version we can trust to find length from? */ |
1280 | /* only version 0 is supported */ | 1280 | if (unlikely(prthdr->it_version)) |
1281 | dev_kfree_skb(skb); | 1281 | goto fail; /* only version 0 is supported */ |
1282 | return NETDEV_TX_OK; | 1282 | |
1283 | } | 1283 | /* then there must be a radiotap header with a length we can use */ |
1284 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | ||
1285 | |||
1286 | /* does the skb contain enough to deliver on the alleged length? */ | ||
1287 | if (unlikely(skb->len < len_rthdr)) | ||
1288 | goto fail; /* skb too short for claimed rt header extent */ | ||
1284 | 1289 | ||
1285 | skb->dev = local->mdev; | 1290 | skb->dev = local->mdev; |
1286 | 1291 | ||
1287 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1292 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; |
1288 | memset(pkt_data, 0, sizeof(*pkt_data)); | 1293 | memset(pkt_data, 0, sizeof(*pkt_data)); |
1294 | /* needed because we set skb device to master */ | ||
1289 | pkt_data->ifindex = dev->ifindex; | 1295 | pkt_data->ifindex = dev->ifindex; |
1296 | |||
1290 | pkt_data->mgmt_iface = 0; | 1297 | pkt_data->mgmt_iface = 0; |
1291 | pkt_data->do_not_encrypt = 1; | 1298 | pkt_data->do_not_encrypt = 1; |
1292 | 1299 | ||
1293 | /* above needed because we set skb device to master */ | ||
1294 | |||
1295 | /* | 1300 | /* |
1296 | * fix up the pointers accounting for the radiotap | 1301 | * fix up the pointers accounting for the radiotap |
1297 | * header still being in there. We are being given | 1302 | * header still being in there. We are being given |
1298 | * a precooked IEEE80211 header so no need for | 1303 | * a precooked IEEE80211 header so no need for |
1299 | * normal processing | 1304 | * normal processing |
1300 | */ | 1305 | */ |
1301 | len = le16_to_cpu(get_unaligned(&prthdr->it_len)); | 1306 | skb_set_mac_header(skb, len_rthdr); |
1302 | skb_set_mac_header(skb, len); | ||
1303 | skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
1304 | skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
1305 | |||
1306 | /* | 1307 | /* |
1307 | * pass the radiotap header up to | 1308 | * these are just fixed to the end of the rt area since we |
1308 | * the next stage intact | 1309 | * don't have any better information and at this point, nobody cares |
1309 | */ | 1310 | */ |
1310 | dev_queue_xmit(skb); | 1311 | skb_set_network_header(skb, len_rthdr); |
1312 | skb_set_transport_header(skb, len_rthdr); | ||
1311 | 1313 | ||
1314 | /* pass the radiotap header up to the next stage intact */ | ||
1315 | dev_queue_xmit(skb); | ||
1312 | return NETDEV_TX_OK; | 1316 | return NETDEV_TX_OK; |
1317 | |||
1318 | fail: | ||
1319 | dev_kfree_skb(skb); | ||
1320 | return NETDEV_TX_OK; /* meaning, we dealt with the skb */ | ||
1313 | } | 1321 | } |
1314 | 1322 | ||
1315 | /** | 1323 | /** |