A single fix, for the MU-MIMO monitor mode, that fixes
bad SKB accesses if the SKB was paged, which is the case for the only driver supporting this - iwlwifi. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEExu3sM/nZ1eRSfR9Ha3t4Rpy0AB0FAlj1zD0ACgkQa3t4Rpy0 AB0zsRAAgQ+rAwSjMfd4HtqiM80JLOhDzjkpw3wXvJvA3eG47DIEdPp3i2rV3FjB pfFmcn/iAVoNgGwxPoFXqsSevxZ+Kv5LPhvvYeqCyOB1H8xIRQw1pHN93jHc19JT BXa/UAuZLcLNvChTWBNF2jbWeiLiErkRTFqqdveGp6FJxmfFH0GhOi0eZPCWgXOH AK35A/59rngYRXc7lZTX47i2FE49IcxUSbp/0ZLtn74VgHyHElltiEhaUva9lUki YaOOLter25HzZgsB+LpxQYOeOS88oF+8vvYbT07Vn5UpjVu6Y7WpKfCEx4BqliP5 H2VQflSXTSGH+wX5sQLmtXA5oidlNfeA3r9THsaPBXCfnqNUFTaszfs7zzAO+JNC BCtmGDiz1c6EYOjKdIpqglfsTehDHkCDnVtOdiUN4oPDqYACgXH/XdfzVwoZCQSg be5idiS6DPVFeQQ19DO+mK+Iwcn9PZ2H2NunLuAeaHd6mR1hdKN8wcSF/ipgtjpR yNyQbSFKIgtvTHiBq42IZZzLsASAI/qAgVXQFnrbR8uzYCJwVscnt7Cg0nSNIVV4 c5McdytcJ8b1NY37hNrwS9e9XJ8oJmOjOOewxciRNLKJq2NjVkB7wh4oYiCL899z fQrCvXEcIqv4m0YtnT4On1ouEn1B3A0XFSUVuIBNdec1rJK7ovg= =r4GR -----END PGP SIGNATURE----- Merge tag 'mac80211-for-davem-2017-04-18' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== A single fix, for the MU-MIMO monitor mode, that fixes bad SKB accesses if the SKB was paged, which is the case for the only driver supporting this - iwlwifi. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6324805979
@ -208,6 +208,51 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
int rtap_vendor_space)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
struct ieee80211_hdr_3addr hdr;
|
||||||
|
u8 category;
|
||||||
|
u8 action_code;
|
||||||
|
} __packed action;
|
||||||
|
|
||||||
|
if (!sdata)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(action) != IEEE80211_MIN_ACTION_SIZE + 1);
|
||||||
|
|
||||||
|
if (skb->len < rtap_vendor_space + sizeof(action) +
|
||||||
|
VHT_MUMIMO_GROUPS_DATA_LEN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!is_valid_ether_addr(sdata->u.mntr.mu_follow_addr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
skb_copy_bits(skb, rtap_vendor_space, &action, sizeof(action));
|
||||||
|
|
||||||
|
if (!ieee80211_is_action(action.hdr.frame_control))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (action.category != WLAN_CATEGORY_VHT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (action.action_code != WLAN_VHT_ACTION_GROUPID_MGMT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!ether_addr_equal(action.hdr.addr1, sdata->u.mntr.mu_follow_addr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
|
if (!skb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
|
||||||
|
skb_queue_tail(&sdata->skb_queue, skb);
|
||||||
|
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ieee80211_add_rx_radiotap_header - add radiotap header
|
* ieee80211_add_rx_radiotap_header - add radiotap header
|
||||||
*
|
*
|
||||||
@ -515,7 +560,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||||||
struct net_device *prev_dev = NULL;
|
struct net_device *prev_dev = NULL;
|
||||||
int present_fcs_len = 0;
|
int present_fcs_len = 0;
|
||||||
unsigned int rtap_vendor_space = 0;
|
unsigned int rtap_vendor_space = 0;
|
||||||
struct ieee80211_mgmt *mgmt;
|
|
||||||
struct ieee80211_sub_if_data *monitor_sdata =
|
struct ieee80211_sub_if_data *monitor_sdata =
|
||||||
rcu_dereference(local->monitor_sdata);
|
rcu_dereference(local->monitor_sdata);
|
||||||
|
|
||||||
@ -553,6 +597,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||||||
return remove_monitor_info(local, origskb, rtap_vendor_space);
|
return remove_monitor_info(local, origskb, rtap_vendor_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_vendor_space);
|
||||||
|
|
||||||
/* room for the radiotap header based on driver features */
|
/* room for the radiotap header based on driver features */
|
||||||
rt_hdrlen = ieee80211_rx_radiotap_hdrlen(local, status, origskb);
|
rt_hdrlen = ieee80211_rx_radiotap_hdrlen(local, status, origskb);
|
||||||
needed_headroom = rt_hdrlen - rtap_vendor_space;
|
needed_headroom = rt_hdrlen - rtap_vendor_space;
|
||||||
@ -618,23 +664,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||||||
ieee80211_rx_stats(sdata->dev, skb->len);
|
ieee80211_rx_stats(sdata->dev, skb->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
mgmt = (void *)skb->data;
|
|
||||||
if (monitor_sdata &&
|
|
||||||
skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 + VHT_MUMIMO_GROUPS_DATA_LEN &&
|
|
||||||
ieee80211_is_action(mgmt->frame_control) &&
|
|
||||||
mgmt->u.action.category == WLAN_CATEGORY_VHT &&
|
|
||||||
mgmt->u.action.u.vht_group_notif.action_code == WLAN_VHT_ACTION_GROUPID_MGMT &&
|
|
||||||
is_valid_ether_addr(monitor_sdata->u.mntr.mu_follow_addr) &&
|
|
||||||
ether_addr_equal(mgmt->da, monitor_sdata->u.mntr.mu_follow_addr)) {
|
|
||||||
struct sk_buff *mu_skb = skb_copy(skb, GFP_ATOMIC);
|
|
||||||
|
|
||||||
if (mu_skb) {
|
|
||||||
mu_skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
|
|
||||||
skb_queue_tail(&monitor_sdata->skb_queue, mu_skb);
|
|
||||||
ieee80211_queue_work(&local->hw, &monitor_sdata->work);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev_dev) {
|
if (prev_dev) {
|
||||||
skb->dev = prev_dev;
|
skb->dev = prev_dev;
|
||||||
netif_receive_skb(skb);
|
netif_receive_skb(skb);
|
||||||
|
Loading…
Reference in New Issue
Block a user