From: Stanislaw Gruszka Date: Wed, 19 Feb 2014 12:15:17 +0000 (+0100) Subject: ath9k: protect tid->sched check X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=21f8aaee0c62708654988ce092838aa7df4d25d8;p=linux-beck.git ath9k: protect tid->sched check We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That is race condition which can result of doing list_del(&tid->list) twice (second time with poisoned list node) and cause crash like shown below: [424271.637220] BUG: unable to handle kernel paging request at 00100104 [424271.637328] IP: [] ath_tx_aggr_sleep+0x62/0xe0 [ath9k] ... [424271.639953] Call Trace: [424271.639998] [] ? ath9k_get_survey+0x110/0x110 [ath9k] [424271.640083] [] ath9k_sta_notify+0x42/0x50 [ath9k] [424271.640177] [] sta_ps_start+0x8f/0x1c0 [mac80211] [424271.640258] [] ? free_compound_page+0x2e/0x40 [424271.640346] [] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211] [424271.640437] [] ? kmem_cache_free+0x1d8/0x1f0 [424271.640510] [] ? kfree_skbmem+0x34/0x90 [424271.640578] [] ? put_page+0x2c/0x40 [424271.640640] [] ? kfree_skbmem+0x34/0x90 [424271.640706] [] ? kfree_skbmem+0x34/0x90 [424271.640787] [] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211] [424271.640897] [] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211] [424271.641009] [] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211] [424271.641104] [] ? ip_output+0x7e/0xd0 [424271.641182] [] ieee80211_rx+0x307/0x7c0 [mac80211] [424271.641266] [] ath_rx_tasklet+0x88e/0xf70 [ath9k] [424271.641358] [] ? ieee80211_rx+0x1dc/0x7c0 [mac80211] [424271.641445] [] ath9k_tasklet+0xcb/0x130 [ath9k] Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=70551 Reported-and-tested-by: Max Sydorenko Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 0a75e2f68c9d..4f4ce83f7ab4 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, for (tidno = 0, tid = &an->tid[tidno]; tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { - if (!tid->sched) - continue; - ac = tid->ac; txq = ac->txq; ath_txq_lock(sc, txq); + if (!tid->sched) { + ath_txq_unlock(sc, txq); + continue; + } + buffered = ath_tid_has_buffered(tid); tid->sched = false;