--- /dev/null
+From linville@tuxdriver.com Wed Oct 31 09:02:49 2007
+From: Andy Green <andy@warmcat.com>
+Date: Tue, 9 Oct 2007 22:46:34 -0400
+Subject: mac80211: Improve sanity checks on injected packets
+To: stable@kernel.org
+Cc: warmcat <andy@warmcat.com>, "John W. Linville" <linville@tuxdriver.com>
+Message-ID: <11919843971189-git-send-email-linville@tuxdriver.com>
+
+From: Andy Green <andy@warmcat.com>
+
+patch 9b8a74e3482f9fc077a88c13fa0ceca8feb0b772 in mainline.
+
+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: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/ieee80211.c | 48 +++++++++++++++++++++++++++--------------------
+ 1 file changed, 28 insertions(+), 20 deletions(-)
+
+--- a/net/mac80211/ieee80211.c
++++ b/net/mac80211/ieee80211.c
+@@ -1680,46 +1680,54 @@ int ieee80211_monitor_start_xmit(struct
+ 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);
++
++ /* 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 */
+ }
+
+