Skip to content

Commit

Permalink
[MAC80211]: Improve sanity checks on injected packets
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andy Green authored and David S. Miller committed Oct 10, 2007
1 parent dfe6e81 commit 9b8a74e
Showing 1 changed file with 28 additions and 20 deletions.
48 changes: 28 additions & 20 deletions net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1270,46 +1270,54 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct ieee80211_tx_packet_data *pkt_data;
struct ieee80211_radiotap_header *prthdr =
(struct ieee80211_radiotap_header *)skb->data;
u16 len;
u16 len_rthdr;

/*
* there must be a radiotap header at the
* start in this case
*/
if (unlikely(prthdr->it_version)) {
/* only version 0 is supported */
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
/* check for not even having the fixed radiotap header part */
if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
goto fail; /* too short to be possibly valid */

/* is it a header version we can trust to find length from? */
if (unlikely(prthdr->it_version))
goto fail; /* only version 0 is supported */

/* 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;

pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(pkt_data, 0, sizeof(*pkt_data));
/* needed because we set skb device to master */
pkt_data->ifindex = dev->ifindex;

pkt_data->mgmt_iface = 0;
pkt_data->do_not_encrypt = 1;

/* above needed because we set skb device to master */

/*
* fix up the pointers accounting for the radiotap
* header still being in there. We are being given
* a precooked IEEE80211 header so no need for
* normal processing
*/
len = le16_to_cpu(get_unaligned(&prthdr->it_len));
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));

skb_set_mac_header(skb, len_rthdr);
/*
* pass the radiotap header up to
* the next stage intact
* these are just fixed to the end of the rt area since we
* 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;

fail:
dev_kfree_skb(skb);
return NETDEV_TX_OK; /* meaning, we dealt with the skb */
}

/**
Expand Down

0 comments on commit 9b8a74e

Please sign in to comment.