|
@@ -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) ||
|