This time we have various things - all across the board:

* MU-MIMO sniffer support in mac80211
  * a create_singlethread_workqueue() cleanup
  * interface dump filtering that was documented but not implemented
  * support for the new radiotap timestamp field
  * send delBA in two unexpected conditions (as required by the spec)
  * connect keys cleanups - allow only WEP with index 0-3
  * per-station aggregation limit to work around broken APs
  * debugfs improvement for the integrated codel algorithm
 and various other small improvements and cleanups.
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCgAGBQJX2+umAAoJEGt7eEactAAdIMkP/jMmpbxkzD64L7nTkO4APGva
 r6RmMM1SmgVD/CtVkjlBLuvo5YOTWv/vWvy6KoUESOINAx/e6T3T7bmmCOXzbsOL
 e5/YYcS1AOqgn5SdhgIj1E5cpdYIhlUGRlNJ0qEjeLLrh4/TLUNbCcuPhOYybUMz
 fUrdPKgDeWb7x9EHLENhPsVtCXWwKnkDIS4qclPZCWgRj46XM4pNB4OlvCUzGY6k
 bOqGJfrtjYjgKFDmPFqfYA4JDA56980qqO41+eEKXeMvDKNs+pSiNco130Q+uU3E
 o7tk9DMnAnCy2GihpV1ZYVkLr6O+7o9xVuenj3NRlhyd1mn2gXxLcO4AkHcrZBkf
 Ei+2L+KgnWELyqiSOaGTJKlugsgS4DDoNnFEIVjSweQ9DIoBA/Gj/6+4uZeHXJ3M
 bEjtHnCLi5CuI067uBoevwXFoMi1poWra2KnZKOZzFS5OL3xHv4//x/Wmnn2/5Jz
 ffEwVyRmTY76sLWfnwXUDClrFWAYQrpNyTryc+k3cpYKzhnseiqt+z43cBuISm00
 uh5B9PpPB8RhtUnXrL/SHRyf8YEluaidTsI2lc1LvwXOc0+Zbp73mTCgP+rzLs9p
 K2qVRiozpIXanW6hKmmaDwjKlcAKKLP0xN2v90MqwQt4YdLIKlXnll1AH2BawzuP
 OWB3n8D0I6y0PWH+Yo8o
 =s1MY
 -----END PGP SIGNATURE-----

Merge tag 'mac80211-next-for-davem-2016-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
This time we have various things - all across the board:
 * MU-MIMO sniffer support in mac80211
 * a create_singlethread_workqueue() cleanup
 * interface dump filtering that was documented but not implemented
 * support for the new radiotap timestamp field
 * send delBA in two unexpected conditions (as required by the spec)
 * connect keys cleanups - allow only WEP with index 0-3
 * per-station aggregation limit to work around broken APs
 * debugfs improvement for the integrated codel algorithm
and various other small improvements and cleanups.
====================

Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
David S. Miller 2016-09-18 22:29:08 -04:00
commit c13ed534b8
34 changed files with 484 additions and 277 deletions

View file

@ -1252,7 +1252,7 @@ static int __init cfg80211_init(void)
if (err)
goto out_fail_reg;
cfg80211_wq = create_singlethread_workqueue("cfg80211");
cfg80211_wq = alloc_ordered_workqueue("cfg80211", WQ_MEM_RECLAIM);
if (!cfg80211_wq) {
err = -ENOMEM;
goto out_fail_wq;

View file

@ -249,9 +249,9 @@ struct cfg80211_event {
};
struct cfg80211_cached_keys {
struct key_params params[6];
u8 data[6][WLAN_MAX_KEY_LEN];
int def, defmgmt;
struct key_params params[4];
u8 data[4][WLAN_KEY_LEN_WEP104];
int def;
};
enum cfg80211_chan_mode {

View file

@ -114,6 +114,9 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
}
}
if (WARN_ON(connkeys && connkeys->def < 0))
return -EINVAL;
if (WARN_ON(wdev->connect_keys))
kzfree(wdev->connect_keys);
wdev->connect_keys = connkeys;
@ -284,18 +287,16 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
if (!netif_running(wdev->netdev))
return 0;
if (wdev->wext.keys) {
if (wdev->wext.keys)
wdev->wext.keys->def = wdev->wext.default_key;
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
}
wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
if (wdev->wext.keys) {
if (wdev->wext.keys && wdev->wext.keys->def != -1) {
ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
if (!ck)
return -ENOMEM;
for (i = 0; i < 6; i++)
for (i = 0; i < 4; i++)
ck->params[i].key = ck->data[i];
}
err = __cfg80211_join_ibss(rdev, wdev->netdev,

View file

@ -222,7 +222,7 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
ASSERT_WDEV_LOCK(wdev);
if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
if (!key || !key_len || key_idx < 0 || key_idx > 4)
if (!key || !key_len || key_idx < 0 || key_idx > 3)
return -EINVAL;
if (wdev->current_bss &&

View file

@ -848,13 +848,21 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
struct nlattr *key;
struct cfg80211_cached_keys *result;
int rem, err, def = 0;
bool have_key = false;
nla_for_each_nested(key, keys, rem) {
have_key = true;
break;
}
if (!have_key)
return NULL;
result = kzalloc(sizeof(*result), GFP_KERNEL);
if (!result)
return ERR_PTR(-ENOMEM);
result->def = -1;
result->defmgmt = -1;
nla_for_each_nested(key, keys, rem) {
memset(&parse, 0, sizeof(parse));
@ -866,7 +874,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
err = -EINVAL;
if (!parse.p.key)
goto error;
if (parse.idx < 0 || parse.idx > 4)
if (parse.idx < 0 || parse.idx > 3)
goto error;
if (parse.def) {
if (def)
@ -881,16 +889,24 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
parse.idx, false, NULL);
if (err)
goto error;
if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
err = -EINVAL;
goto error;
}
result->params[parse.idx].cipher = parse.p.cipher;
result->params[parse.idx].key_len = parse.p.key_len;
result->params[parse.idx].key = result->data[parse.idx];
memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
if (parse.p.cipher == WLAN_CIPHER_SUITE_WEP40 ||
parse.p.cipher == WLAN_CIPHER_SUITE_WEP104) {
if (no_ht)
*no_ht = true;
}
/* must be WEP key if we got here */
if (no_ht)
*no_ht = true;
}
if (result->def < 0) {
err = -EINVAL;
goto error;
}
return result;
@ -2525,10 +2541,35 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
int if_idx = 0;
int wp_start = cb->args[0];
int if_start = cb->args[1];
int filter_wiphy = -1;
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
rtnl_lock();
if (!cb->args[2]) {
struct nl80211_dump_wiphy_state state = {
.filter_wiphy = -1,
};
int ret;
ret = nl80211_dump_wiphy_parse(skb, cb, &state);
if (ret)
return ret;
filter_wiphy = state.filter_wiphy;
/*
* if filtering, set cb->args[2] to +1 since 0 is the default
* value needed to determine that parsing is necessary.
*/
if (filter_wiphy >= 0)
cb->args[2] = filter_wiphy + 1;
else
cb->args[2] = -1;
} else if (cb->args[2] > 0) {
filter_wiphy = cb->args[2] - 1;
}
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
continue;
@ -2536,6 +2577,10 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
wp_idx++;
continue;
}
if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
continue;
if_idx = 0;
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
@ -7359,7 +7404,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
(key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
key.p.key_len != WLAN_KEY_LEN_WEP104))
return -EINVAL;
if (key.idx > 4)
if (key.idx > 3)
return -EINVAL;
} else {
key.p.key_len = 0;
@ -7977,6 +8022,8 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
}
data = nla_nest_start(skb, attr);
if (!data)
goto nla_put_failure;
((void **)skb->cb)[0] = rdev;
((void **)skb->cb)[1] = hdr;
@ -9406,18 +9453,27 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
if (!freqs)
return -ENOBUFS;
for (i = 0; i < req->n_channels; i++)
nla_put_u32(msg, i, req->channels[i]->center_freq);
for (i = 0; i < req->n_channels; i++) {
if (nla_put_u32(msg, i, req->channels[i]->center_freq))
return -ENOBUFS;
}
nla_nest_end(msg, freqs);
if (req->n_match_sets) {
matches = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
if (!matches)
return -ENOBUFS;
for (i = 0; i < req->n_match_sets; i++) {
match = nla_nest_start(msg, i);
nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
req->match_sets[i].ssid.ssid_len,
req->match_sets[i].ssid.ssid);
if (!match)
return -ENOBUFS;
if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
req->match_sets[i].ssid.ssid_len,
req->match_sets[i].ssid.ssid))
return -ENOBUFS;
nla_nest_end(msg, match);
}
nla_nest_end(msg, matches);
@ -9429,6 +9485,9 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
for (i = 0; i < req->n_scan_plans; i++) {
scan_plan = nla_nest_start(msg, i + 1);
if (!scan_plan)
return -ENOBUFS;
if (!scan_plan ||
nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
req->scan_plans[i].interval) ||

View file

@ -352,52 +352,48 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *rdev)
__cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
}
const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
const u8 *match, int match_len,
int match_offset)
{
while (len > 2 && ies[0] != eid) {
/* match_offset can't be smaller than 2, unless match_len is
* zero, in which case match_offset must be zero as well.
*/
if (WARN_ON((match_len && match_offset < 2) ||
(!match_len && match_offset)))
return NULL;
while (len >= 2 && len >= ies[1] + 2) {
if ((ies[0] == eid) &&
(ies[1] + 2 >= match_offset + match_len) &&
!memcmp(ies + match_offset, match, match_len))
return ies;
len -= ies[1] + 2;
ies += ies[1] + 2;
}
if (len < 2)
return NULL;
if (len < 2 + ies[1])
return NULL;
return ies;
return NULL;
}
EXPORT_SYMBOL(cfg80211_find_ie);
EXPORT_SYMBOL(cfg80211_find_ie_match);
const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
const u8 *ies, int len)
{
struct ieee80211_vendor_ie *ie;
const u8 *pos = ies, *end = ies + len;
int ie_oui;
const u8 *ie;
u8 match[] = { oui >> 16, oui >> 8, oui, oui_type };
int match_len = (oui_type < 0) ? 3 : sizeof(match);
if (WARN_ON(oui_type > 0xff))
return NULL;
while (pos < end) {
pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos,
end - pos);
if (!pos)
return NULL;
ie = cfg80211_find_ie_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,
match, match_len, 2);
ie = (struct ieee80211_vendor_ie *)pos;
if (ie && (ie[1] < 4))
return NULL;
/* make sure we can access ie->len */
BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1);
if (ie->len < sizeof(*ie))
goto cont;
ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
if (ie_oui == oui &&
(oui_type < 0 || ie->oui_type == oui_type))
return pos;
cont:
pos += 2 + ie->len;
}
return NULL;
return ie;
}
EXPORT_SYMBOL(cfg80211_find_vendor_ie);

View file

@ -1043,6 +1043,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
connect->crypto.ciphers_pairwise[0] = cipher;
}
}
} else {
if (WARN_ON(connkeys))
return -EINVAL;
}
wdev->connect_keys = connkeys;

View file

@ -57,7 +57,7 @@ static ssize_t addresses_show(struct device *dev,
return sprintf(buf, "%pM\n", wiphy->perm_addr);
for (i = 0; i < wiphy->n_addresses; i++)
buf += sprintf(buf, "%pM\n", &wiphy->addresses[i].addr);
buf += sprintf(buf, "%pM\n", wiphy->addresses[i].addr);
return buf - start;
}

View file

@ -218,7 +218,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
struct key_params *params, int key_idx,
bool pairwise, const u8 *mac_addr)
{
if (key_idx > 5)
if (key_idx < 0 || key_idx > 5)
return -EINVAL;
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
@ -249,7 +249,13 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
/* Disallow BIP (group-only) cipher as pairwise cipher */
if (pairwise)
return -EINVAL;
if (key_idx < 4)
return -EINVAL;
break;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
if (key_idx > 3)
return -EINVAL;
default:
break;
}
@ -906,7 +912,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
if (!wdev->connect_keys)
return;
for (i = 0; i < 6; i++) {
for (i = 0; i < 4; i++) {
if (!wdev->connect_keys->params[i].cipher)
continue;
if (rdev_add_key(rdev, dev, i, false, NULL,
@ -919,9 +925,6 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
netdev_err(dev, "failed to set defkey %d\n", i);
continue;
}
if (wdev->connect_keys->defmgmt == i)
if (rdev_set_default_mgmt_key(rdev, dev, i))
netdev_err(dev, "failed to set mgtdef %d\n", i);
}
kzfree(wdev->connect_keys);

View file

@ -408,10 +408,10 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
if (!wdev->wext.keys) {
wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
GFP_KERNEL);
GFP_KERNEL);
if (!wdev->wext.keys)
return -ENOMEM;
for (i = 0; i < 6; i++)
for (i = 0; i < 4; i++)
wdev->wext.keys->params[i].key =
wdev->wext.keys->data[i];
}
@ -460,7 +460,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
if (err == -ENOENT)
err = 0;
if (!err) {
if (!addr) {
if (!addr && idx < 4) {
memset(wdev->wext.keys->data[idx], 0,
sizeof(wdev->wext.keys->data[idx]));
wdev->wext.keys->params[idx].key_len = 0;
@ -487,6 +487,9 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
err = 0;
if (wdev->current_bss)
err = rdev_add_key(rdev, dev, idx, pairwise, addr, params);
else if (params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
params->cipher != WLAN_CIPHER_SUITE_WEP104)
return -EINVAL;
if (err)
return err;

View file

@ -35,7 +35,6 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
if (wdev->wext.keys) {
wdev->wext.keys->def = wdev->wext.default_key;
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
if (wdev->wext.default_key != -1)
wdev->wext.connect.privacy = true;
}
@ -43,11 +42,11 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
if (!wdev->wext.connect.ssid_len)
return 0;
if (wdev->wext.keys) {
if (wdev->wext.keys && wdev->wext.keys->def != -1) {
ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
if (!ck)
return -ENOMEM;
for (i = 0; i < 6; i++)
for (i = 0; i < 4; i++)
ck->params[i].key = ck->data[i];
}