Return-path: Received: from mail-ww0-f44.google.com ([74.125.82.44]:50567 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753683Ab1B1RrB (ORCPT ); Mon, 28 Feb 2011 12:47:01 -0500 From: Alessio Igor Bogani To: Larry Finger , Chaoming Li Cc: linux-wireless@vger.kernel.org, LKML , Tim Bird , Alessio Igor Bogani Subject: [PATCH] rtlwifi: Add the missing rcu_read_lock/unlock Date: Mon, 28 Feb 2011 18:46:44 +0100 Message-Id: <1298915204-2648-1-git-send-email-abogani@kernel.org> In-Reply-To: <4D6AC9EE.2070904@lwfinger.net> References: <4D6AC9EE.2070904@lwfinger.net> Sender: linux-wireless-owner@vger.kernel.org List-ID: =================================================== [ INFO: suspicious rcu_dereference_check() usage. ] --------------------------------------------------- net/mac80211/sta_info.c:125 invoked rcu_dereference_check() without protection! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 5 locks held by wpa_supplicant/468: #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x14/0x20 #1: (&rdev->mtx){+.+.+.}, at: [] cfg80211_mgd_wext_siwfreq+0x6b/0x170 [cfg80211] #2: (&rdev->devlist_mtx){+.+.+.}, at: [] cfg80211_mgd_wext_siwfreq+0x77/0x170 [cfg80211] #3: (&wdev->mtx){+.+.+.}, at: [] cfg80211_mgd_wext_siwfreq+0x84/0x170 [cfg80211] #4: (&rtlpriv->locks.conf_mutex){+.+.+.}, at: [] rtl_op_bss_info_changed+0x26/0xc10 [rtlwifi] stack backtrace: Pid: 468, comm: wpa_supplicant Not tainted 2.6.38-rc6+ #79 Call Trace: [] ? lockdep_rcu_dereference+0xaa/0xb0 [] ? sta_info_get_bss+0x19c/0x1b0 [mac80211] [] ? ieee80211_find_sta+0x22/0x40 [mac80211] [] ? rtl_op_bss_info_changed+0x1cc/0xc10 [rtlwifi] [] ? __mutex_unlock_slowpath+0x14c/0x160 [] ? mutex_unlock+0xd/0x10 [] ? rtl_op_config+0x120/0x310 [rtlwifi] [] ? trace_hardirqs_on+0xb/0x10 [] ? ieee80211_bss_info_change_notify+0xf9/0x1f0 [mac80211] [] ? rtl_op_bss_info_changed+0x0/0xc10 [rtlwifi] [] ? ieee80211_set_channel+0xbf/0xd0 [mac80211] [] ? cfg80211_set_freq+0x121/0x180 [cfg80211] [] ? ieee80211_set_channel+0x0/0xd0 [mac80211] [] ? cfg80211_mgd_wext_siwfreq+0x12b/0x170 [cfg80211] [] ? cfg80211_wext_siwfreq+0x9b/0x100 [cfg80211] [] ? sub_preempt_count+0x7b/0xb0 [] ? ioctl_standard_call+0x74/0x3b0 [] ? rtnl_lock+0x14/0x20 [] ? cfg80211_wext_siwfreq+0x0/0x100 [cfg80211] [] ? __dev_get_by_name+0x8d/0xb0 [] ? wext_handle_ioctl+0x16b/0x180 [] ? cfg80211_wext_siwfreq+0x0/0x100 [cfg80211] [] ? dev_ioctl+0x5ba/0x720 [] ? __lock_acquire+0x3e7/0x19b0 [] ? sock_ioctl+0x1eb/0x290 [] ? lock_release_non_nested+0x95/0x2f0 [] ? sock_ioctl+0x0/0x290 [] ? do_vfs_ioctl+0x7d/0x5c0 [] ? might_fault+0x62/0xb0 [] ? fget_light+0x226/0x390 [] ? might_fault+0xa8/0xb0 [] ? sys_ioctl+0x87/0x90 [] ? sysenter_do_call+0x12/0x38 This work was supported by a hardware donation from the CE Linux Forum. Signed-off-by: Alessio Igor Bogani --- drivers/net/wireless/rtlwifi/core.c | 4 ++++ drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 5 ++++- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 059ab03..e4f4aee 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -551,6 +551,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("BSS_CHANGED_HT\n")); + rcu_read_lock(); sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { @@ -563,6 +564,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, mac->current_ampdu_factor = sta->ht_cap.ampdu_factor; } + rcu_read_unlock(); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY, (u8 *) (&mac->max_mss_density)); @@ -614,6 +616,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, else mac->mode = WIRELESS_MODE_G; + rcu_read_lock(); sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { @@ -648,6 +651,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, */ } } + rcu_read_unlock(); /*mac80211 just give us CCK rates any time *So we add G rate in basic rates when diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 8a67372..e14f743 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -730,7 +730,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid); + struct ieee80211_sta *sta; u8 *pdesc = (u8 *) pdesc_tx; struct rtl_tcb_desc tcb_desc; u8 *qc = ieee80211_get_qos_ctl(hdr); @@ -810,10 +810,13 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_LINIP(pdesc, 0); SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); } + rcu_read_unlock(); if (info->control.hw_key) { struct ieee80211_key_conf *keyconf = diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 659e0ca..d0b0d43 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -504,7 +504,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid); + struct ieee80211_sta *sta; struct rtl_tcb_desc tcb_desc; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; @@ -562,10 +562,13 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_BW(txdesc, 0); SET_TX_DESC_DATA_SC(txdesc, 0); } + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); } + rcu_read_unlock(); if (info->control.hw_key) { struct ieee80211_key_conf *keyconf = info->control.hw_key; switch (keyconf->cipher) { -- 1.7.4.1