mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
wifi: nl80211: don't take rtnl for most dumps
Most (wdev-related) dumps also take RTNL just for lookup. Apply the same logic as for pre_doit() in the previous commit to avoid the RTNL. Since I refactored the checks there into a helper to use here, it even simplifies the code. Link: https://patch.msgid.link/20261006120655.37954ad94c77.Ica4719b0054c949abf2528d9c4c13a5d6b7a1a49@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
8e3d9039d2
commit
197d5f64e3
|
|
@ -1304,6 +1304,8 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
|
|||
struct wireless_dev **wdev,
|
||||
struct nlattr **attrbuf)
|
||||
{
|
||||
struct net *netns = sock_net(cb->skb->sk);
|
||||
u32 wdev_id;
|
||||
int err;
|
||||
|
||||
if (!cb->args[0]) {
|
||||
|
|
@ -1325,61 +1327,38 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
|
|||
return err;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
*wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
|
||||
attrbuf);
|
||||
rcu_read_lock();
|
||||
*wdev = __cfg80211_wdev_from_attrs(NULL, netns, attrbuf);
|
||||
kfree(attrbuf_free);
|
||||
if (IS_ERR(*wdev)) {
|
||||
rtnl_unlock();
|
||||
rcu_read_unlock();
|
||||
return PTR_ERR(*wdev);
|
||||
}
|
||||
*rdev = wiphy_to_rdev((*wdev)->wiphy);
|
||||
mutex_lock(&(*rdev)->wiphy.mtx);
|
||||
rtnl_unlock();
|
||||
/* 0 is the first index - add 1 to parse only once */
|
||||
cb->args[0] = (*rdev)->wiphy_idx + 1;
|
||||
cb->args[1] = (*wdev)->identifier;
|
||||
wdev_id = (*wdev)->identifier;
|
||||
} else {
|
||||
/* subtract the 1 again here */
|
||||
struct wiphy *wiphy;
|
||||
struct wireless_dev *tmp;
|
||||
|
||||
rtnl_lock();
|
||||
wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
|
||||
if (!wiphy) {
|
||||
rtnl_unlock();
|
||||
rcu_read_lock();
|
||||
*rdev = cfg80211_rdev_by_wiphy_idx(cb->args[0] - 1);
|
||||
if (!*rdev) {
|
||||
rcu_read_unlock();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* The first invocation validated the wdev's netns against
|
||||
* the caller via __cfg80211_wdev_from_attrs(). The wiphy
|
||||
* may have moved netns between dumpit invocations (via
|
||||
* NL80211_CMD_SET_WIPHY_NETNS), so re-check here.
|
||||
*/
|
||||
if (!net_eq(wiphy_net(wiphy), sock_net(cb->skb->sk))) {
|
||||
rtnl_unlock();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*rdev = wiphy_to_rdev(wiphy);
|
||||
*wdev = NULL;
|
||||
|
||||
list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
|
||||
if (tmp->identifier == cb->args[1]) {
|
||||
*wdev = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*wdev) {
|
||||
rtnl_unlock();
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&(*rdev)->wiphy.mtx);
|
||||
rtnl_unlock();
|
||||
wdev_id = cb->args[1];
|
||||
}
|
||||
|
||||
get_device(&(*rdev)->wiphy.dev);
|
||||
rcu_read_unlock();
|
||||
|
||||
/* things may have changed since the lookup or the last dumpit call */
|
||||
*wdev = nl80211_lock_and_recheck(*rdev, netns, wdev_id);
|
||||
if (IS_ERR(*wdev))
|
||||
return PTR_ERR(*wdev);
|
||||
|
||||
/* 0 is the first index - add 1 to parse only once */
|
||||
cb->args[0] = (*rdev)->wiphy_idx + 1;
|
||||
cb->args[1] = wdev_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user