| From foo@baz Fri Jul 3 20:00:25 PDT 2015 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Wed, 17 Jun 2015 13:54:54 +0200 |
| Subject: mac80211: fix locking in update_vlan_tailroom_need_count() |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| [ Upstream commit 51f458d9612177f69c2e2c437034ae15f93078e7 ] |
| |
| 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: f9dca80b98ca ("mac80211: fix AP_VLAN crypto tailroom calculation") |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/mac80211/key.c | 13 ++++++++++--- |
| 1 file changed, 10 insertions(+), 3 deletions(-) |
| |
| --- a/net/mac80211/key.c |
| +++ b/net/mac80211/key.c |
| @@ -66,12 +66,15 @@ update_vlan_tailroom_need_count(struct i |
| if (sdata->vif.type != NL80211_IFTYPE_AP) |
| 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; |
| |
| - mutex_unlock(&sdata->local->mtx); |
| + rcu_read_unlock(); |
| } |
| |
| static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) |
| @@ -95,6 +98,8 @@ static void increment_tailroom_need_coun |
| * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net |
| */ |
| |
| + assert_key_lock(sdata->local); |
| + |
| update_vlan_tailroom_need_count(sdata, 1); |
| |
| if (!sdata->crypto_tx_tailroom_needed_cnt++) { |
| @@ -109,6 +114,8 @@ static void increment_tailroom_need_coun |
| static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata, |
| int delta) |
| { |
| + assert_key_lock(sdata->local); |
| + |
| WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt < delta); |
| |
| update_vlan_tailroom_need_count(sdata, -delta); |