diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 129 |
1 files changed, 59 insertions, 70 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1f0de6d74daa..de10e3c0e2a4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -302,8 +302,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
302 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, | 302 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, |
303 | [NL80211_ATTR_PID] = { .type = NLA_U32 }, | 303 | [NL80211_ATTR_PID] = { .type = NLA_U32 }, |
304 | [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, | 304 | [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, |
305 | [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, | 305 | [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN }, |
306 | .len = WLAN_PMKID_LEN }, | ||
307 | [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, | 306 | [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, |
308 | [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, | 307 | [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, |
309 | [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, | 308 | [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, |
@@ -359,6 +358,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
359 | [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, | 358 | [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, |
360 | [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, | 359 | [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, |
361 | [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, | 360 | [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, |
361 | [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 }, | ||
362 | [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, | 362 | [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, |
363 | [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, | 363 | [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, |
364 | [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, | 364 | [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, |
@@ -492,21 +492,17 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
492 | { | 492 | { |
493 | int err; | 493 | int err; |
494 | 494 | ||
495 | rtnl_lock(); | ||
496 | |||
497 | if (!cb->args[0]) { | 495 | if (!cb->args[0]) { |
498 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 496 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
499 | nl80211_fam.attrbuf, nl80211_fam.maxattr, | 497 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
500 | nl80211_policy); | 498 | nl80211_policy); |
501 | if (err) | 499 | if (err) |
502 | goto out_unlock; | 500 | return err; |
503 | 501 | ||
504 | *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), | 502 | *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), |
505 | nl80211_fam.attrbuf); | 503 | nl80211_fam.attrbuf); |
506 | if (IS_ERR(*wdev)) { | 504 | if (IS_ERR(*wdev)) |
507 | err = PTR_ERR(*wdev); | 505 | return PTR_ERR(*wdev); |
508 | goto out_unlock; | ||
509 | } | ||
510 | *rdev = wiphy_to_rdev((*wdev)->wiphy); | 506 | *rdev = wiphy_to_rdev((*wdev)->wiphy); |
511 | /* 0 is the first index - add 1 to parse only once */ | 507 | /* 0 is the first index - add 1 to parse only once */ |
512 | cb->args[0] = (*rdev)->wiphy_idx + 1; | 508 | cb->args[0] = (*rdev)->wiphy_idx + 1; |
@@ -516,10 +512,8 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
516 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); | 512 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); |
517 | struct wireless_dev *tmp; | 513 | struct wireless_dev *tmp; |
518 | 514 | ||
519 | if (!wiphy) { | 515 | if (!wiphy) |
520 | err = -ENODEV; | 516 | return -ENODEV; |
521 | goto out_unlock; | ||
522 | } | ||
523 | *rdev = wiphy_to_rdev(wiphy); | 517 | *rdev = wiphy_to_rdev(wiphy); |
524 | *wdev = NULL; | 518 | *wdev = NULL; |
525 | 519 | ||
@@ -530,21 +524,11 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
530 | } | 524 | } |
531 | } | 525 | } |
532 | 526 | ||
533 | if (!*wdev) { | 527 | if (!*wdev) |
534 | err = -ENODEV; | 528 | return -ENODEV; |
535 | goto out_unlock; | ||
536 | } | ||
537 | } | 529 | } |
538 | 530 | ||
539 | return 0; | 531 | return 0; |
540 | out_unlock: | ||
541 | rtnl_unlock(); | ||
542 | return err; | ||
543 | } | ||
544 | |||
545 | static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) | ||
546 | { | ||
547 | rtnl_unlock(); | ||
548 | } | 532 | } |
549 | 533 | ||
550 | /* IE validation */ | 534 | /* IE validation */ |
@@ -3884,9 +3868,10 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
3884 | int sta_idx = cb->args[2]; | 3868 | int sta_idx = cb->args[2]; |
3885 | int err; | 3869 | int err; |
3886 | 3870 | ||
3871 | rtnl_lock(); | ||
3887 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 3872 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
3888 | if (err) | 3873 | if (err) |
3889 | return err; | 3874 | goto out_err; |
3890 | 3875 | ||
3891 | if (!wdev->netdev) { | 3876 | if (!wdev->netdev) { |
3892 | err = -EINVAL; | 3877 | err = -EINVAL; |
@@ -3922,7 +3907,7 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
3922 | cb->args[2] = sta_idx; | 3907 | cb->args[2] = sta_idx; |
3923 | err = skb->len; | 3908 | err = skb->len; |
3924 | out_err: | 3909 | out_err: |
3925 | nl80211_finish_wdev_dump(rdev); | 3910 | rtnl_unlock(); |
3926 | 3911 | ||
3927 | return err; | 3912 | return err; |
3928 | } | 3913 | } |
@@ -4639,9 +4624,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
4639 | int path_idx = cb->args[2]; | 4624 | int path_idx = cb->args[2]; |
4640 | int err; | 4625 | int err; |
4641 | 4626 | ||
4627 | rtnl_lock(); | ||
4642 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 4628 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
4643 | if (err) | 4629 | if (err) |
4644 | return err; | 4630 | goto out_err; |
4645 | 4631 | ||
4646 | if (!rdev->ops->dump_mpath) { | 4632 | if (!rdev->ops->dump_mpath) { |
4647 | err = -EOPNOTSUPP; | 4633 | err = -EOPNOTSUPP; |
@@ -4675,7 +4661,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
4675 | cb->args[2] = path_idx; | 4661 | cb->args[2] = path_idx; |
4676 | err = skb->len; | 4662 | err = skb->len; |
4677 | out_err: | 4663 | out_err: |
4678 | nl80211_finish_wdev_dump(rdev); | 4664 | rtnl_unlock(); |
4679 | return err; | 4665 | return err; |
4680 | } | 4666 | } |
4681 | 4667 | ||
@@ -4835,9 +4821,10 @@ static int nl80211_dump_mpp(struct sk_buff *skb, | |||
4835 | int path_idx = cb->args[2]; | 4821 | int path_idx = cb->args[2]; |
4836 | int err; | 4822 | int err; |
4837 | 4823 | ||
4824 | rtnl_lock(); | ||
4838 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 4825 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
4839 | if (err) | 4826 | if (err) |
4840 | return err; | 4827 | goto out_err; |
4841 | 4828 | ||
4842 | if (!rdev->ops->dump_mpp) { | 4829 | if (!rdev->ops->dump_mpp) { |
4843 | err = -EOPNOTSUPP; | 4830 | err = -EOPNOTSUPP; |
@@ -4870,7 +4857,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, | |||
4870 | cb->args[2] = path_idx; | 4857 | cb->args[2] = path_idx; |
4871 | err = skb->len; | 4858 | err = skb->len; |
4872 | out_err: | 4859 | out_err: |
4873 | nl80211_finish_wdev_dump(rdev); | 4860 | rtnl_unlock(); |
4874 | return err; | 4861 | return err; |
4875 | } | 4862 | } |
4876 | 4863 | ||
@@ -5718,6 +5705,10 @@ static int validate_scan_freqs(struct nlattr *freqs) | |||
5718 | struct nlattr *attr1, *attr2; | 5705 | struct nlattr *attr1, *attr2; |
5719 | int n_channels = 0, tmp1, tmp2; | 5706 | int n_channels = 0, tmp1, tmp2; |
5720 | 5707 | ||
5708 | nla_for_each_nested(attr1, freqs, tmp1) | ||
5709 | if (nla_len(attr1) != sizeof(u32)) | ||
5710 | return 0; | ||
5711 | |||
5721 | nla_for_each_nested(attr1, freqs, tmp1) { | 5712 | nla_for_each_nested(attr1, freqs, tmp1) { |
5722 | n_channels++; | 5713 | n_channels++; |
5723 | /* | 5714 | /* |
@@ -6806,9 +6797,12 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) | |||
6806 | int start = cb->args[2], idx = 0; | 6797 | int start = cb->args[2], idx = 0; |
6807 | int err; | 6798 | int err; |
6808 | 6799 | ||
6800 | rtnl_lock(); | ||
6809 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 6801 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
6810 | if (err) | 6802 | if (err) { |
6803 | rtnl_unlock(); | ||
6811 | return err; | 6804 | return err; |
6805 | } | ||
6812 | 6806 | ||
6813 | wdev_lock(wdev); | 6807 | wdev_lock(wdev); |
6814 | spin_lock_bh(&rdev->bss_lock); | 6808 | spin_lock_bh(&rdev->bss_lock); |
@@ -6831,7 +6825,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) | |||
6831 | wdev_unlock(wdev); | 6825 | wdev_unlock(wdev); |
6832 | 6826 | ||
6833 | cb->args[2] = idx; | 6827 | cb->args[2] = idx; |
6834 | nl80211_finish_wdev_dump(rdev); | 6828 | rtnl_unlock(); |
6835 | 6829 | ||
6836 | return skb->len; | 6830 | return skb->len; |
6837 | } | 6831 | } |
@@ -6915,9 +6909,10 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) | |||
6915 | int res; | 6909 | int res; |
6916 | bool radio_stats; | 6910 | bool radio_stats; |
6917 | 6911 | ||
6912 | rtnl_lock(); | ||
6918 | res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 6913 | res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
6919 | if (res) | 6914 | if (res) |
6920 | return res; | 6915 | goto out_err; |
6921 | 6916 | ||
6922 | /* prepare_wdev_dump parsed the attributes */ | 6917 | /* prepare_wdev_dump parsed the attributes */ |
6923 | radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; | 6918 | radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; |
@@ -6958,7 +6953,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) | |||
6958 | cb->args[2] = survey_idx; | 6953 | cb->args[2] = survey_idx; |
6959 | res = skb->len; | 6954 | res = skb->len; |
6960 | out_err: | 6955 | out_err: |
6961 | nl80211_finish_wdev_dump(rdev); | 6956 | rtnl_unlock(); |
6962 | return res; | 6957 | return res; |
6963 | } | 6958 | } |
6964 | 6959 | ||
@@ -10158,17 +10153,13 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
10158 | void *data = NULL; | 10153 | void *data = NULL; |
10159 | unsigned int data_len = 0; | 10154 | unsigned int data_len = 0; |
10160 | 10155 | ||
10161 | rtnl_lock(); | ||
10162 | |||
10163 | if (cb->args[0]) { | 10156 | if (cb->args[0]) { |
10164 | /* subtract the 1 again here */ | 10157 | /* subtract the 1 again here */ |
10165 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); | 10158 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); |
10166 | struct wireless_dev *tmp; | 10159 | struct wireless_dev *tmp; |
10167 | 10160 | ||
10168 | if (!wiphy) { | 10161 | if (!wiphy) |
10169 | err = -ENODEV; | 10162 | return -ENODEV; |
10170 | goto out_unlock; | ||
10171 | } | ||
10172 | *rdev = wiphy_to_rdev(wiphy); | 10163 | *rdev = wiphy_to_rdev(wiphy); |
10173 | *wdev = NULL; | 10164 | *wdev = NULL; |
10174 | 10165 | ||
@@ -10189,13 +10180,11 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
10189 | nl80211_fam.attrbuf, nl80211_fam.maxattr, | 10180 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
10190 | nl80211_policy); | 10181 | nl80211_policy); |
10191 | if (err) | 10182 | if (err) |
10192 | goto out_unlock; | 10183 | return err; |
10193 | 10184 | ||
10194 | if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] || | 10185 | if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] || |
10195 | !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) { | 10186 | !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) |
10196 | err = -EINVAL; | 10187 | return -EINVAL; |
10197 | goto out_unlock; | ||
10198 | } | ||
10199 | 10188 | ||
10200 | *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), | 10189 | *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), |
10201 | nl80211_fam.attrbuf); | 10190 | nl80211_fam.attrbuf); |
@@ -10204,10 +10193,8 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
10204 | 10193 | ||
10205 | *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), | 10194 | *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), |
10206 | nl80211_fam.attrbuf); | 10195 | nl80211_fam.attrbuf); |
10207 | if (IS_ERR(*rdev)) { | 10196 | if (IS_ERR(*rdev)) |
10208 | err = PTR_ERR(*rdev); | 10197 | return PTR_ERR(*rdev); |
10209 | goto out_unlock; | ||
10210 | } | ||
10211 | 10198 | ||
10212 | vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]); | 10199 | vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]); |
10213 | subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]); | 10200 | subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]); |
@@ -10220,19 +10207,15 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
10220 | if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) | 10207 | if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) |
10221 | continue; | 10208 | continue; |
10222 | 10209 | ||
10223 | if (!vcmd->dumpit) { | 10210 | if (!vcmd->dumpit) |
10224 | err = -EOPNOTSUPP; | 10211 | return -EOPNOTSUPP; |
10225 | goto out_unlock; | ||
10226 | } | ||
10227 | 10212 | ||
10228 | vcmd_idx = i; | 10213 | vcmd_idx = i; |
10229 | break; | 10214 | break; |
10230 | } | 10215 | } |
10231 | 10216 | ||
10232 | if (vcmd_idx < 0) { | 10217 | if (vcmd_idx < 0) |
10233 | err = -EOPNOTSUPP; | 10218 | return -EOPNOTSUPP; |
10234 | goto out_unlock; | ||
10235 | } | ||
10236 | 10219 | ||
10237 | if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) { | 10220 | if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) { |
10238 | data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]); | 10221 | data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]); |
@@ -10249,9 +10232,6 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, | |||
10249 | 10232 | ||
10250 | /* keep rtnl locked in successful case */ | 10233 | /* keep rtnl locked in successful case */ |
10251 | return 0; | 10234 | return 0; |
10252 | out_unlock: | ||
10253 | rtnl_unlock(); | ||
10254 | return err; | ||
10255 | } | 10235 | } |
10256 | 10236 | ||
10257 | static int nl80211_vendor_cmd_dump(struct sk_buff *skb, | 10237 | static int nl80211_vendor_cmd_dump(struct sk_buff *skb, |
@@ -10266,9 +10246,10 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb, | |||
10266 | int err; | 10246 | int err; |
10267 | struct nlattr *vendor_data; | 10247 | struct nlattr *vendor_data; |
10268 | 10248 | ||
10249 | rtnl_lock(); | ||
10269 | err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev); | 10250 | err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev); |
10270 | if (err) | 10251 | if (err) |
10271 | return err; | 10252 | goto out; |
10272 | 10253 | ||
10273 | vcmd_idx = cb->args[2]; | 10254 | vcmd_idx = cb->args[2]; |
10274 | data = (void *)cb->args[3]; | 10255 | data = (void *)cb->args[3]; |
@@ -10277,18 +10258,26 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb, | |||
10277 | 10258 | ||
10278 | if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV | | 10259 | if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV | |
10279 | WIPHY_VENDOR_CMD_NEED_NETDEV)) { | 10260 | WIPHY_VENDOR_CMD_NEED_NETDEV)) { |
10280 | if (!wdev) | 10261 | if (!wdev) { |
10281 | return -EINVAL; | 10262 | err = -EINVAL; |
10263 | goto out; | ||
10264 | } | ||
10282 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV && | 10265 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV && |
10283 | !wdev->netdev) | 10266 | !wdev->netdev) { |
10284 | return -EINVAL; | 10267 | err = -EINVAL; |
10268 | goto out; | ||
10269 | } | ||
10285 | 10270 | ||
10286 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) { | 10271 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) { |
10287 | if (wdev->netdev && | 10272 | if (wdev->netdev && |
10288 | !netif_running(wdev->netdev)) | 10273 | !netif_running(wdev->netdev)) { |
10289 | return -ENETDOWN; | 10274 | err = -ENETDOWN; |
10290 | if (!wdev->netdev && !wdev->p2p_started) | 10275 | goto out; |
10291 | return -ENETDOWN; | 10276 | } |
10277 | if (!wdev->netdev && !wdev->p2p_started) { | ||
10278 | err = -ENETDOWN; | ||
10279 | goto out; | ||
10280 | } | ||
10292 | } | 10281 | } |
10293 | } | 10282 | } |
10294 | 10283 | ||