summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2019-10-04 08:37:06 -0400
committerJohannes Berg <johannes.berg@intel.com>2019-10-07 15:35:57 -0400
commit461c4c2b4c0731d7452bad4e77c0cdbdcea1804c (patch)
tree17ec48a63c1aa9d72ed5c50bc1e6abc65caa3afd
parent1399c59fa92984836db90538cf92397fe7caaa57 (diff)
cfg80211: fix a bunch of RCU issues in multi-bssid code
cfg80211_update_notlisted_nontrans() leaves the RCU critical session too early, while still using nontrans_ssid which is RCU protected. In addition, it performs a bunch of RCU pointer update operations such as rcu_access_pointer and rcu_assign_pointer. The caller, cfg80211_inform_bss_frame_data(), also accesses the RCU pointer without holding the lock. Just wrap all of this with bss_lock. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/20191004123706.15768-3-luca@coelho.fi Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/wireless/scan.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ff1016607f0b..aef240fdf8df 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1703,8 +1703,7 @@ cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
1703static void 1703static void
1704cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, 1704cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
1705 struct cfg80211_bss *nontrans_bss, 1705 struct cfg80211_bss *nontrans_bss,
1706 struct ieee80211_mgmt *mgmt, size_t len, 1706 struct ieee80211_mgmt *mgmt, size_t len)
1707 gfp_t gfp)
1708{ 1707{
1709 u8 *ie, *new_ie, *pos; 1708 u8 *ie, *new_ie, *pos;
1710 const u8 *nontrans_ssid, *trans_ssid, *mbssid; 1709 const u8 *nontrans_ssid, *trans_ssid, *mbssid;
@@ -1715,6 +1714,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
1715 const struct cfg80211_bss_ies *old; 1714 const struct cfg80211_bss_ies *old;
1716 u8 cpy_len; 1715 u8 cpy_len;
1717 1716
1717 lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock);
1718
1718 ie = mgmt->u.probe_resp.variable; 1719 ie = mgmt->u.probe_resp.variable;
1719 1720
1720 new_ie_len = ielen; 1721 new_ie_len = ielen;
@@ -1731,23 +1732,22 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
1731 if (!mbssid || mbssid < trans_ssid) 1732 if (!mbssid || mbssid < trans_ssid)
1732 return; 1733 return;
1733 new_ie_len -= mbssid[1]; 1734 new_ie_len -= mbssid[1];
1734 rcu_read_lock(); 1735
1735 nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID); 1736 nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
1736 if (!nontrans_ssid) { 1737 if (!nontrans_ssid)
1737 rcu_read_unlock();
1738 return; 1738 return;
1739 } 1739
1740 new_ie_len += nontrans_ssid[1]; 1740 new_ie_len += nontrans_ssid[1];
1741 rcu_read_unlock();
1742 1741
1743 /* generate new ie for nontrans BSS 1742 /* generate new ie for nontrans BSS
1744 * 1. replace SSID with nontrans BSS' SSID 1743 * 1. replace SSID with nontrans BSS' SSID
1745 * 2. skip MBSSID IE 1744 * 2. skip MBSSID IE
1746 */ 1745 */
1747 new_ie = kzalloc(new_ie_len, gfp); 1746 new_ie = kzalloc(new_ie_len, GFP_ATOMIC);
1748 if (!new_ie) 1747 if (!new_ie)
1749 return; 1748 return;
1750 new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, gfp); 1749
1750 new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC);
1751 if (!new_ies) 1751 if (!new_ies)
1752 goto out_free; 1752 goto out_free;
1753 1753
@@ -1901,6 +1901,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
1901 cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len, 1901 cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len,
1902 &non_tx_data, gfp); 1902 &non_tx_data, gfp);
1903 1903
1904 spin_lock_bh(&wiphy_to_rdev(wiphy)->bss_lock);
1905
1904 /* check if the res has other nontransmitting bss which is not 1906 /* check if the res has other nontransmitting bss which is not
1905 * in MBSSID IE 1907 * in MBSSID IE
1906 */ 1908 */
@@ -1915,8 +1917,9 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
1915 ies2 = rcu_access_pointer(tmp_bss->ies); 1917 ies2 = rcu_access_pointer(tmp_bss->ies);
1916 if (ies2->tsf < ies1->tsf) 1918 if (ies2->tsf < ies1->tsf)
1917 cfg80211_update_notlisted_nontrans(wiphy, tmp_bss, 1919 cfg80211_update_notlisted_nontrans(wiphy, tmp_bss,
1918 mgmt, len, gfp); 1920 mgmt, len);
1919 } 1921 }
1922 spin_unlock_bh(&wiphy_to_rdev(wiphy)->bss_lock);
1920 1923
1921 return res; 1924 return res;
1922} 1925}