cfg80211: fix locking in nl80211_set_wiphy

Luis reports that there's a circular locking dependency;
this is because cfg80211_dev_rename() will acquire the
cfg80211_mutex while the device mutex is held, while
this normally is done the other way around. The solution
is to open-code the device-getting in nl80211_set_wiphy
and require holding the mutex around cfg80211_dev_rename
rather than acquiring it within.

Also fix a bug -- rtnl locking is expected by drivers so
we need to provide it.

Reported-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Johannes Berg
2009-03-24 09:35:46 +01:00
committed by John W. Linville
parent 3832c287f1
commit 4bbf4d5658
3 changed files with 33 additions and 28 deletions

View File

@@ -366,16 +366,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
int result = 0, rem_txq_params = 0;
struct nlattr *nl_txq_params;
rdev = cfg80211_get_dev_from_info(info);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
rtnl_lock();
if (info->attrs[NL80211_ATTR_WIPHY_NAME]) {
mutex_lock(&cfg80211_mutex);
rdev = __cfg80211_drv_from_info(info);
if (IS_ERR(rdev)) {
result = PTR_ERR(rdev);
goto unlock;
}
mutex_lock(&rdev->mtx);
if (info->attrs[NL80211_ATTR_WIPHY_NAME])
result = cfg80211_dev_rename(
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
if (result)
goto bad_res;
}
mutex_unlock(&cfg80211_mutex);
if (result)
goto bad_res;
if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
struct ieee80211_txq_params txq_params;
@@ -471,7 +481,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
bad_res:
cfg80211_put_dev(rdev);
mutex_unlock(&rdev->mtx);
unlock:
rtnl_unlock();
return result;
}