summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShuah Khan <skhan@linuxfoundation.org>2021-02-11 00:21:07 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-07 15:47:41 +0300
commitee898d95f44678781ab23863fc1041dd1fe083a1 (patch)
tree702d227280aff29700498b7fd4627c9fcca880b4
parent0b8dfb61f29a56fe4f44e2ced6d216bd494f2781 (diff)
downloadlinux-ee898d95f44678781ab23863fc1041dd1fe083a1.tar.xz
ath10k: hold RCU lock when calling ieee80211_find_sta_by_ifaddr()
[ Upstream commit 09078368d516918666a0122f2533dc73676d3d7e ] ieee80211_find_sta_by_ifaddr() must be called under the RCU lock and the resulting pointer is only valid under RCU lock as well. Fix ath10k_wmi_tlv_op_pull_peer_stats_info() to hold RCU lock before it calls ieee80211_find_sta_by_ifaddr() and release it when the resulting pointer is no longer needed. This problem was found while reviewing code to debug RCU warn from ath10k_wmi_tlv_parse_peer_stats_info(). Link: https://lore.kernel.org/linux-wireless/7230c9e5-2632-b77e-c4f9-10eca557a5bb@linuxfoundation.org/ Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/20210210212107.40373-1-skhan@linuxfoundation.org Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 3ec71f52e8fe..d38276ac375e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -445,13 +445,13 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
case WMI_TDLS_TEARDOWN_REASON_TX:
case WMI_TDLS_TEARDOWN_REASON_RSSI:
case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
+ rcu_read_lock();
station = ieee80211_find_sta_by_ifaddr(ar->hw,
ev->peer_macaddr.addr,
NULL);
if (!station) {
ath10k_warn(ar, "did not find station from tdls peer event");
- kfree(tb);
- return;
+ goto exit;
}
arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
ieee80211_tdls_oper_request(
@@ -462,6 +462,9 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
);
break;
}
+
+exit:
+ rcu_read_unlock();
kfree(tb);
}