|
@@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|
|
int wiphy_idx = -1;
|
|
|
int ifidx = -1;
|
|
|
|
|
|
- assert_cfg80211_lock();
|
|
|
+ ASSERT_RTNL();
|
|
|
|
|
|
if (!have_ifidx && !have_wdev_id)
|
|
|
return ERR_PTR(-EINVAL);
|
|
@@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|
|
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
|
|
|
continue;
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
|
|
if (have_ifidx && wdev->netdev &&
|
|
|
wdev->netdev->ifindex == ifidx) {
|
|
@@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
|
|
|
if (result)
|
|
|
break;
|
|
@@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|
|
struct cfg80211_registered_device *rdev = NULL, *tmp;
|
|
|
struct net_device *netdev;
|
|
|
|
|
|
- assert_cfg80211_lock();
|
|
|
+ ASSERT_RTNL();
|
|
|
|
|
|
if (!attrs[NL80211_ATTR_WIPHY] &&
|
|
|
!attrs[NL80211_ATTR_IFINDEX] &&
|
|
@@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|
|
tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
|
|
|
if (tmp) {
|
|
|
/* make sure wdev exists */
|
|
|
- mutex_lock(&tmp->devlist_mtx);
|
|
|
list_for_each_entry(wdev, &tmp->wdev_list, list) {
|
|
|
if (wdev->identifier != (u32)wdev_id)
|
|
|
continue;
|
|
|
found = true;
|
|
|
break;
|
|
|
}
|
|
|
- mutex_unlock(&tmp->devlist_mtx);
|
|
|
|
|
|
if (!found)
|
|
|
tmp = NULL;
|
|
@@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|
|
/*
|
|
|
* This function returns a pointer to the driver
|
|
|
* that the genl_info item that is passed refers to.
|
|
|
- * If successful, it returns non-NULL and also locks
|
|
|
- * the driver's mutex!
|
|
|
- *
|
|
|
- * This means that you need to call cfg80211_unlock_rdev()
|
|
|
- * before being allowed to acquire &cfg80211_mutex!
|
|
|
- *
|
|
|
- * This is necessary because we need to lock the global
|
|
|
- * mutex to get an item off the list safely, and then
|
|
|
- * we lock the rdev mutex so it doesn't go away under us.
|
|
|
- *
|
|
|
- * We don't want to keep cfg80211_mutex locked
|
|
|
- * for all the time in order to allow requests on
|
|
|
- * other interfaces to go through at the same time.
|
|
|
*
|
|
|
* The result of this can be a PTR_ERR and hence must
|
|
|
* be checked with IS_ERR() for errors.
|
|
@@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|
|
static struct cfg80211_registered_device *
|
|
|
cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
|
|
|
{
|
|
|
- struct cfg80211_registered_device *rdev;
|
|
|
-
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
- rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
|
|
|
-
|
|
|
- /* if it is not an error we grab the lock on
|
|
|
- * it to assure it won't be going away while
|
|
|
- * we operate on it */
|
|
|
- if (!IS_ERR(rdev))
|
|
|
- mutex_lock(&rdev->mtx);
|
|
|
-
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
-
|
|
|
- return rdev;
|
|
|
+ return __cfg80211_rdev_from_attrs(netns, info->attrs);
|
|
|
}
|
|
|
|
|
|
/* policy for the attributes */
|
|
@@ -456,7 +426,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
|
|
|
int err;
|
|
|
|
|
|
rtnl_lock();
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
|
|
|
if (!cb->args[0]) {
|
|
|
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
|
@@ -485,14 +454,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
|
|
|
*rdev = wiphy_to_dev(wiphy);
|
|
|
*wdev = NULL;
|
|
|
|
|
|
- mutex_lock(&(*rdev)->devlist_mtx);
|
|
|
list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
|
|
|
if (tmp->identifier == cb->args[1]) {
|
|
|
*wdev = tmp;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- mutex_unlock(&(*rdev)->devlist_mtx);
|
|
|
|
|
|
if (!*wdev) {
|
|
|
err = -ENODEV;
|
|
@@ -500,19 +467,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- cfg80211_lock_rdev(*rdev);
|
|
|
-
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
return 0;
|
|
|
out_unlock:
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
rtnl_unlock();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
|
|
|
{
|
|
|
- cfg80211_unlock_rdev(rdev);
|
|
|
rtnl_unlock();
|
|
|
}
|
|
|
|
|
@@ -1568,7 +1530,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
struct nlattr **tb = nl80211_fam.attrbuf;
|
|
|
int res;
|
|
|
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
+ rtnl_lock();
|
|
|
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
|
|
tb, nl80211_fam.maxattr, nl80211_policy);
|
|
|
if (res == 0) {
|
|
@@ -1582,10 +1544,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
|
|
|
|
|
|
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
|
|
|
- if (!netdev) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
+ if (!netdev)
|
|
|
return -ENODEV;
|
|
|
- }
|
|
|
if (netdev->ieee80211_ptr) {
|
|
|
dev = wiphy_to_dev(
|
|
|
netdev->ieee80211_ptr->wiphy);
|
|
@@ -1629,7 +1589,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
!skb->len &&
|
|
|
cb->min_dump_alloc < 4096) {
|
|
|
cb->min_dump_alloc = 4096;
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
return 1;
|
|
|
}
|
|
|
idx--;
|
|
@@ -1638,7 +1597,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
} while (cb->args[1] > 0);
|
|
|
break;
|
|
|
}
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
+ rtnl_unlock();
|
|
|
|
|
|
cb->args[0] = idx;
|
|
|
|
|
@@ -1793,7 +1752,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
|
|
if (result)
|
|
|
return result;
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
switch (iftype) {
|
|
|
case NL80211_IFTYPE_AP:
|
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
@@ -1817,7 +1775,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
|
|
default:
|
|
|
result = -EINVAL;
|
|
|
}
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
|
|
|
return result;
|
|
|
}
|
|
@@ -1866,6 +1823,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|
|
u32 frag_threshold = 0, rts_threshold = 0;
|
|
|
u8 coverage_class = 0;
|
|
|
|
|
|
+ ASSERT_RTNL();
|
|
|
+
|
|
|
/*
|
|
|
* Try to find the wiphy and netdev. Normally this
|
|
|
* function shouldn't need the netdev, but this is
|
|
@@ -1875,31 +1834,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|
|
* also passed a netdev to set_wiphy, so that it is
|
|
|
* possible to let that go to the right netdev!
|
|
|
*/
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
|
|
|
if (info->attrs[NL80211_ATTR_IFINDEX]) {
|
|
|
int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
|
|
|
|
|
|
netdev = dev_get_by_index(genl_info_net(info), ifindex);
|
|
|
- if (netdev && netdev->ieee80211_ptr) {
|
|
|
+ if (netdev && netdev->ieee80211_ptr)
|
|
|
rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
|
|
|
- mutex_lock(&rdev->mtx);
|
|
|
- } else
|
|
|
+ else
|
|
|
netdev = NULL;
|
|
|
}
|
|
|
|
|
|
if (!netdev) {
|
|
|
rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
|
|
|
info->attrs);
|
|
|
- if (IS_ERR(rdev)) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
+ if (IS_ERR(rdev))
|
|
|
return PTR_ERR(rdev);
|
|
|
- }
|
|
|
wdev = NULL;
|
|
|
netdev = NULL;
|
|
|
result = 0;
|
|
|
-
|
|
|
- mutex_lock(&rdev->mtx);
|
|
|
} else
|
|
|
wdev = netdev->ieee80211_ptr;
|
|
|
|
|
@@ -1912,8 +1865,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|
|
result = cfg80211_dev_rename(
|
|
|
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
|
|
|
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
-
|
|
|
if (result)
|
|
|
goto bad_res;
|
|
|
|
|
@@ -2120,7 +2071,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
|
|
|
bad_res:
|
|
|
- mutex_unlock(&rdev->mtx);
|
|
|
if (netdev)
|
|
|
dev_put(netdev);
|
|
|
return result;
|
|
@@ -2218,7 +2168,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|
|
struct cfg80211_registered_device *rdev;
|
|
|
struct wireless_dev *wdev;
|
|
|
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
+ rtnl_lock();
|
|
|
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
|
|
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
|
|
|
continue;
|
|
@@ -2228,7 +2178,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|
|
}
|
|
|
if_idx = 0;
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
|
|
if (if_idx < if_start) {
|
|
|
if_idx++;
|
|
@@ -2237,17 +2186,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|
|
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
|
|
|
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
|
|
rdev, wdev) < 0) {
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
goto out;
|
|
|
}
|
|
|
if_idx++;
|
|
|
}
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
|
|
|
wp_idx++;
|
|
|
}
|
|
|
out:
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
+ rtnl_unlock();
|
|
|
|
|
|
cb->args[0] = wp_idx;
|
|
|
cb->args[1] = if_idx;
|
|
@@ -2480,11 +2427,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
|
|
spin_lock_init(&wdev->mgmt_registrations_lock);
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
wdev->identifier = ++rdev->wdev_id;
|
|
|
list_add_rcu(&wdev->list, &rdev->wdev_list);
|
|
|
rdev->devlist_generation++;
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
@@ -2993,8 +2938,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
|
|
struct wireless_dev *wdev;
|
|
|
bool ret = false;
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
-
|
|
|
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
|
|
if (wdev->iftype != NL80211_IFTYPE_AP &&
|
|
|
wdev->iftype != NL80211_IFTYPE_P2P_GO)
|
|
@@ -3008,8 +2951,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
-
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -3171,13 +3112,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|
|
params.radar_required = true;
|
|
|
}
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
|
|
|
params.chandef.chan,
|
|
|
CHAN_MODE_SHARED,
|
|
|
radar_detect_width);
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
-
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -4914,18 +4852,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|
|
void *hdr = NULL;
|
|
|
struct nlattr *nl_reg_rules;
|
|
|
unsigned int i;
|
|
|
- int err = -EINVAL;
|
|
|
-
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
|
|
|
if (!cfg80211_regdomain)
|
|
|
- goto out;
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
- if (!msg) {
|
|
|
- err = -ENOBUFS;
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ if (!msg)
|
|
|
+ return -ENOBUFS;
|
|
|
|
|
|
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
|
|
|
NL80211_CMD_GET_REG);
|
|
@@ -4984,8 +4917,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|
|
nla_nest_end(msg, nl_reg_rules);
|
|
|
|
|
|
genlmsg_end(msg, hdr);
|
|
|
- err = genlmsg_reply(msg, info);
|
|
|
- goto out;
|
|
|
+ return genlmsg_reply(msg, info);
|
|
|
|
|
|
nla_put_failure_rcu:
|
|
|
rcu_read_unlock();
|
|
@@ -4993,10 +4925,7 @@ nla_put_failure:
|
|
|
genlmsg_cancel(msg, hdr);
|
|
|
put_failure:
|
|
|
nlmsg_free(msg);
|
|
|
- err = -EMSGSIZE;
|
|
|
-out:
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
- return err;
|
|
|
+ return -EMSGSIZE;
|
|
|
}
|
|
|
|
|
|
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
|
@@ -5062,12 +4991,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
-
|
|
|
r = set_regdom(rd);
|
|
|
/* set_regdom took ownership */
|
|
|
rd = NULL;
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
|
|
|
bad_reg:
|
|
|
kfree(rd);
|
|
@@ -5117,7 +5043,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (!rdev->ops->scan)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- mutex_lock(&rdev->sched_scan_mtx);
|
|
|
if (rdev->scan_req) {
|
|
|
err = -EBUSY;
|
|
|
goto unlock;
|
|
@@ -5303,7 +5228,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
|
|
|
unlock:
|
|
|
- mutex_unlock(&rdev->sched_scan_mtx);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -5375,8 +5299,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|
|
if (ie_len > wiphy->max_sched_scan_ie_len)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- mutex_lock(&rdev->sched_scan_mtx);
|
|
|
-
|
|
|
if (rdev->sched_scan_req) {
|
|
|
err = -EINPROGRESS;
|
|
|
goto out;
|
|
@@ -5544,7 +5466,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|
|
out_free:
|
|
|
kfree(request);
|
|
|
out:
|
|
|
- mutex_unlock(&rdev->sched_scan_mtx);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -5552,17 +5473,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
|
|
|
struct genl_info *info)
|
|
|
{
|
|
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
|
|
- int err;
|
|
|
|
|
|
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
|
|
!rdev->ops->sched_scan_stop)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- mutex_lock(&rdev->sched_scan_mtx);
|
|
|
- err = __cfg80211_stop_sched_scan(rdev, false);
|
|
|
- mutex_unlock(&rdev->sched_scan_mtx);
|
|
|
-
|
|
|
- return err;
|
|
|
+ return __cfg80211_stop_sched_scan(rdev, false);
|
|
|
}
|
|
|
|
|
|
static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|
@@ -5594,12 +5510,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|
|
if (!rdev->ops->start_radar_detection)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
|
|
|
chandef.chan, CHAN_MODE_SHARED,
|
|
|
BIT(chandef.width));
|
|
|
if (err)
|
|
|
- goto err_locked;
|
|
|
+ return err;
|
|
|
|
|
|
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
|
|
|
if (!err) {
|
|
@@ -5607,9 +5522,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|
|
wdev->cac_started = true;
|
|
|
wdev->cac_start_time = jiffies;
|
|
|
}
|
|
|
-err_locked:
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
-
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -6472,6 +6384,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|
|
void *data = NULL;
|
|
|
int data_len = 0;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
if (cb->args[0]) {
|
|
|
/*
|
|
|
* 0 is a valid index, but not valid for args[0],
|
|
@@ -6483,18 +6397,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|
|
nl80211_fam.attrbuf, nl80211_fam.maxattr,
|
|
|
nl80211_policy);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_err;
|
|
|
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
|
|
|
nl80211_fam.attrbuf);
|
|
|
if (IS_ERR(rdev)) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
- return PTR_ERR(rdev);
|
|
|
+ err = PTR_ERR(rdev);
|
|
|
+ goto out_err;
|
|
|
}
|
|
|
phy_idx = rdev->wiphy_idx;
|
|
|
rdev = NULL;
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
|
|
|
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
|
|
|
cb->args[1] =
|
|
@@ -6506,14 +6418,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|
|
data_len = nla_len((void *)cb->args[1]);
|
|
|
}
|
|
|
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
|
|
|
if (!rdev) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
- return -ENOENT;
|
|
|
+ err = -ENOENT;
|
|
|
+ goto out_err;
|
|
|
}
|
|
|
- cfg80211_lock_rdev(rdev);
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
|
|
|
if (!rdev->ops->testmode_dump) {
|
|
|
err = -EOPNOTSUPP;
|
|
@@ -6554,7 +6463,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|
|
/* see above */
|
|
|
cb->args[0] = phy_idx + 1;
|
|
|
out_err:
|
|
|
- cfg80211_unlock_rdev(rdev);
|
|
|
+ rtnl_unlock();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -8189,9 +8098,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (wdev->p2p_started)
|
|
|
return 0;
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
err = cfg80211_can_add_interface(rdev, wdev->iftype);
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -8200,9 +8107,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
|
|
return err;
|
|
|
|
|
|
wdev->p2p_started = true;
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
rdev->opencount++;
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -8218,11 +8123,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (!rdev->ops->stop_p2p_device)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- mutex_lock(&rdev->devlist_mtx);
|
|
|
- mutex_lock(&rdev->sched_scan_mtx);
|
|
|
cfg80211_stop_p2p_device(rdev, wdev);
|
|
|
- mutex_unlock(&rdev->sched_scan_mtx);
|
|
|
- mutex_unlock(&rdev->devlist_mtx);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -8365,11 +8266,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|
|
info->user_ptr[0] = rdev;
|
|
|
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
|
|
|
ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
|
|
|
- mutex_lock(&cfg80211_mutex);
|
|
|
+ ASSERT_RTNL();
|
|
|
+
|
|
|
wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
|
|
|
info->attrs);
|
|
|
if (IS_ERR(wdev)) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
if (rtnl)
|
|
|
rtnl_unlock();
|
|
|
return PTR_ERR(wdev);
|
|
@@ -8380,7 +8281,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|
|
|
|
|
if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
|
|
|
if (!dev) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
if (rtnl)
|
|
|
rtnl_unlock();
|
|
|
return -EINVAL;
|
|
@@ -8394,7 +8294,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|
|
if (dev) {
|
|
|
if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
|
|
|
!netif_running(dev)) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
if (rtnl)
|
|
|
rtnl_unlock();
|
|
|
return -ENETDOWN;
|
|
@@ -8403,17 +8302,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|
|
dev_hold(dev);
|
|
|
} else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
|
|
|
if (!wdev->p2p_started) {
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
if (rtnl)
|
|
|
rtnl_unlock();
|
|
|
return -ENETDOWN;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- cfg80211_lock_rdev(rdev);
|
|
|
-
|
|
|
- mutex_unlock(&cfg80211_mutex);
|
|
|
-
|
|
|
info->user_ptr[0] = rdev;
|
|
|
}
|
|
|
|
|
@@ -8423,8 +8317,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|
|
static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|
|
struct genl_info *info)
|
|
|
{
|
|
|
- if (info->user_ptr[0])
|
|
|
- cfg80211_unlock_rdev(info->user_ptr[0]);
|
|
|
if (info->user_ptr[1]) {
|
|
|
if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
|
|
|
struct wireless_dev *wdev = info->user_ptr[1];
|
|
@@ -8446,7 +8338,8 @@ static struct genl_ops nl80211_ops[] = {
|
|
|
.dumpit = nl80211_dump_wiphy,
|
|
|
.policy = nl80211_policy,
|
|
|
/* can be retrieved by unprivileged users */
|
|
|
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
|
|
|
+ .internal_flags = NL80211_FLAG_NEED_WIPHY |
|
|
|
+ NL80211_FLAG_NEED_RTNL,
|
|
|
},
|
|
|
{
|
|
|
.cmd = NL80211_CMD_SET_WIPHY,
|
|
@@ -8461,7 +8354,8 @@ static struct genl_ops nl80211_ops[] = {
|
|
|
.dumpit = nl80211_dump_interface,
|
|
|
.policy = nl80211_policy,
|
|
|
/* can be retrieved by unprivileged users */
|
|
|
- .internal_flags = NL80211_FLAG_NEED_WDEV,
|
|
|
+ .internal_flags = NL80211_FLAG_NEED_WDEV |
|
|
|
+ NL80211_FLAG_NEED_RTNL,
|
|
|
},
|
|
|
{
|
|
|
.cmd = NL80211_CMD_SET_INTERFACE,
|
|
@@ -8620,6 +8514,7 @@ static struct genl_ops nl80211_ops[] = {
|
|
|
.cmd = NL80211_CMD_GET_REG,
|
|
|
.doit = nl80211_get_reg,
|
|
|
.policy = nl80211_policy,
|
|
|
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
|
|
|
/* can be retrieved by unprivileged users */
|
|
|
},
|
|
|
{
|
|
@@ -8627,6 +8522,7 @@ static struct genl_ops nl80211_ops[] = {
|
|
|
.doit = nl80211_set_reg,
|
|
|
.policy = nl80211_policy,
|
|
|
.flags = GENL_ADMIN_PERM,
|
|
|
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
|
|
|
},
|
|
|
{
|
|
|
.cmd = NL80211_CMD_REQ_SET_REG,
|
|
@@ -9082,8 +8978,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
|
|
|
struct nlattr *nest;
|
|
|
int i;
|
|
|
|
|
|
- lockdep_assert_held(&rdev->sched_scan_mtx);
|
|
|
-
|
|
|
if (WARN_ON(!req))
|
|
|
return 0;
|
|
|
|