aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-03-24 04:35:46 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:13:20 -0400
commit4bbf4d56583dd52c429d88f43cb614bdbe5deea6 (patch)
tree7a3f902a08820342254e0d67607fe870b02620b3 /net/wireless/nl80211.c
parent3832c287f11ba001bbe48e9be8c59cb9f71f6b43 (diff)
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>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8808431bd581..353e1a4ece83 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -366,16 +366,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
366 int result = 0, rem_txq_params = 0; 366 int result = 0, rem_txq_params = 0;
367 struct nlattr *nl_txq_params; 367 struct nlattr *nl_txq_params;
368 368
369 rdev = cfg80211_get_dev_from_info(info); 369 rtnl_lock();
370 if (IS_ERR(rdev)) 370
371 return PTR_ERR(rdev); 371 mutex_lock(&cfg80211_mutex);
372
373 rdev = __cfg80211_drv_from_info(info);
374 if (IS_ERR(rdev)) {
375 result = PTR_ERR(rdev);
376 goto unlock;
377 }
372 378
373 if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { 379 mutex_lock(&rdev->mtx);
380
381 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
374 result = cfg80211_dev_rename( 382 result = cfg80211_dev_rename(
375 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); 383 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
376 if (result) 384
377 goto bad_res; 385 mutex_unlock(&cfg80211_mutex);
378 } 386
387 if (result)
388 goto bad_res;
379 389
380 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { 390 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
381 struct ieee80211_txq_params txq_params; 391 struct ieee80211_txq_params txq_params;
@@ -471,7 +481,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
471 481
472 482
473 bad_res: 483 bad_res:
474 cfg80211_put_dev(rdev); 484 mutex_unlock(&rdev->mtx);
485 unlock:
486 rtnl_unlock();
475 return result; 487 return result;
476} 488}
477 489