Commit 51f458d9 authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller

mac80211: fix locking in update_vlan_tailroom_need_count()

Unfortunately, Michal's change to fix AP_VLAN crypto tailroom
caused a locking issue that was reported by lockdep, but only
in a few cases - the issue was a classic ABBA deadlock caused
by taking the mtx after the key_mtx, where normally they're
taken the other way around.

As the key mutex protects the field in question (I'm adding a
few annotations to make that clear) only the iteration needs
to be protected, but we can also iterate the interface list
with just RCU protection while holding the key mutex.

Fixes: f9dca80b ("mac80211: fix AP_VLAN crypto tailroom calculation")
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7b48f457
...@@ -66,12 +66,15 @@ update_vlan_tailroom_need_count(struct ieee80211_sub_if_data *sdata, int delta) ...@@ -66,12 +66,15 @@ update_vlan_tailroom_need_count(struct ieee80211_sub_if_data *sdata, int delta)
if (sdata->vif.type != NL80211_IFTYPE_AP) if (sdata->vif.type != NL80211_IFTYPE_AP)
return; return;
mutex_lock(&sdata->local->mtx); /* crypto_tx_tailroom_needed_cnt is protected by this */
assert_key_lock(sdata->local);
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) rcu_read_lock();
list_for_each_entry_rcu(vlan, &sdata->u.ap.vlans, u.vlan.list)
vlan->crypto_tx_tailroom_needed_cnt += delta; vlan->crypto_tx_tailroom_needed_cnt += delta;
mutex_unlock(&sdata->local->mtx); rcu_read_unlock();
} }
static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
...@@ -95,6 +98,8 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) ...@@ -95,6 +98,8 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
* http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
*/ */
assert_key_lock(sdata->local);
update_vlan_tailroom_need_count(sdata, 1); update_vlan_tailroom_need_count(sdata, 1);
if (!sdata->crypto_tx_tailroom_needed_cnt++) { if (!sdata->crypto_tx_tailroom_needed_cnt++) {
...@@ -109,6 +114,8 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) ...@@ -109,6 +114,8 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata, static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata,
int delta) int delta)
{ {
assert_key_lock(sdata->local);
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt < delta); WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt < delta);
update_vlan_tailroom_need_count(sdata, -delta); update_vlan_tailroom_need_count(sdata, -delta);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment