Commit 9b8a74e3 authored by Andy Green's avatar Andy Green Committed by David S. Miller

[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: default avatarAndy Green <andy@warmcat.com>
Signed-off-by: default avatarJiri Benc <jbenc@suse.cz>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent dfe6e81d
...@@ -1270,46 +1270,54 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, ...@@ -1270,46 +1270,54 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct ieee80211_tx_packet_data *pkt_data; struct ieee80211_tx_packet_data *pkt_data;
struct ieee80211_radiotap_header *prthdr = struct ieee80211_radiotap_header *prthdr =
(struct ieee80211_radiotap_header *)skb->data; (struct ieee80211_radiotap_header *)skb->data;
u16 len; u16 len_rthdr;
/* /* check for not even having the fixed radiotap header part */
* there must be a radiotap header at the if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
* start in this case goto fail; /* too short to be possibly valid */
*/
if (unlikely(prthdr->it_version)) { /* is it a header version we can trust to find length from? */
/* only version 0 is supported */ if (unlikely(prthdr->it_version))
dev_kfree_skb(skb); goto fail; /* only version 0 is supported */
return NETDEV_TX_OK;
} /* then there must be a radiotap header with a length we can use */
len_rthdr = ieee80211_get_radiotap_len(skb->data);
/* does the skb contain enough to deliver on the alleged length? */
if (unlikely(skb->len < len_rthdr))
goto fail; /* skb too short for claimed rt header extent */
skb->dev = local->mdev; skb->dev = local->mdev;
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(pkt_data, 0, sizeof(*pkt_data)); memset(pkt_data, 0, sizeof(*pkt_data));
/* needed because we set skb device to master */
pkt_data->ifindex = dev->ifindex; pkt_data->ifindex = dev->ifindex;
pkt_data->mgmt_iface = 0; pkt_data->mgmt_iface = 0;
pkt_data->do_not_encrypt = 1; pkt_data->do_not_encrypt = 1;
/* above needed because we set skb device to master */
/* /*
* fix up the pointers accounting for the radiotap * fix up the pointers accounting for the radiotap
* header still being in there. We are being given * header still being in there. We are being given
* a precooked IEEE80211 header so no need for * a precooked IEEE80211 header so no need for
* normal processing * normal processing
*/ */
len = le16_to_cpu(get_unaligned(&prthdr->it_len)); skb_set_mac_header(skb, len_rthdr);
skb_set_mac_header(skb, len);
skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr));
skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr));
/* /*
* pass the radiotap header up to * these are just fixed to the end of the rt area since we
* the next stage intact * don't have any better information and at this point, nobody cares
*/ */
dev_queue_xmit(skb); skb_set_network_header(skb, len_rthdr);
skb_set_transport_header(skb, len_rthdr);
/* pass the radiotap header up to the next stage intact */
dev_queue_xmit(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
fail:
dev_kfree_skb(skb);
return NETDEV_TX_OK; /* meaning, we dealt with the skb */
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment