Skip to content

Commit 2cac597

Browse files
committed
wifi: ath9k: delay all of ath9k_wmi_event_tasklet() until init is complete
jira LE-1907 cve CVE-2024-26897 Rebuild_History Non-Buildable kernel-5.14.0-427.31.1.el9_4 commit-author Toke Høiland-Jørgensen <toke@redhat.com> commit 24355fc The ath9k_wmi_event_tasklet() used in ath9k_htc assumes that all the data structures have been fully initialised by the time it runs. However, because of the order in which things are initialised, this is not guaranteed to be the case, because the device is exposed to the USB subsystem before the ath9k driver initialisation is completed. We already committed a partial fix for this in commit: 8b3046a ("ath9k_htc: fix NULL pointer dereference at ath9k_htc_tx_get_packet()") However, that commit only aborted the WMI_TXSTATUS_EVENTID command in the event tasklet, pairing it with an "initialisation complete" bit in the TX struct. It seems syzbot managed to trigger the race for one of the other commands as well, so let's just move the existing synchronisation bit to cover the whole tasklet (setting it at the end of ath9k_htc_probe_device() instead of inside ath9k_tx_init()). Link: https://lore.kernel.org/r/ed1d2c66-1193-4c81-9542-d514c29ba8b8.bugreport@ubisectech.com Fixes: 8b3046a ("ath9k_htc: fix NULL pointer dereference at ath9k_htc_tx_get_packet()") Reported-by: Ubisectech Sirius <bugreport@ubisectech.com> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://msgid.link/20240126140218.1033443-1-toke@toke.dk (cherry picked from commit 24355fc) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 7e04665 commit 2cac597

File tree

4 files changed

+11
-9
lines changed

4 files changed

+11
-9
lines changed

drivers/net/wireless/ath/ath9k/htc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ struct ath9k_htc_tx {
306306
DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM);
307307
struct timer_list cleanup_timer;
308308
spinlock_t tx_lock;
309-
bool initialized;
310309
};
311310

312311
struct ath9k_htc_tx_ctl {
@@ -515,6 +514,7 @@ struct ath9k_htc_priv {
515514
unsigned long ps_usecount;
516515
bool ps_enabled;
517516
bool ps_idle;
517+
bool initialized;
518518

519519
#ifdef CONFIG_MAC80211_LEDS
520520
enum led_brightness brightness;

drivers/net/wireless/ath/ath9k/htc_drv_init.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,10 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
966966

967967
htc_handle->drv_priv = priv;
968968

969+
/* Allow ath9k_wmi_event_tasklet() to operate. */
970+
smp_wmb();
971+
priv->initialized = true;
972+
969973
return 0;
970974

971975
err_init:

drivers/net/wireless/ath/ath9k/htc_drv_txrx.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -814,10 +814,6 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv)
814814
skb_queue_head_init(&priv->tx.data_vo_queue);
815815
skb_queue_head_init(&priv->tx.tx_failed);
816816

817-
/* Allow ath9k_wmi_event_tasklet(WMI_TXSTATUS_EVENTID) to operate. */
818-
smp_wmb();
819-
priv->tx.initialized = true;
820-
821817
return 0;
822818
}
823819

drivers/net/wireless/ath/ath9k/wmi.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
155155
}
156156
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
157157

158+
/* Check if ath9k_htc_probe_device() completed. */
159+
if (!data_race(priv->initialized)) {
160+
kfree_skb(skb);
161+
continue;
162+
}
163+
158164
hdr = (struct wmi_cmd_hdr *) skb->data;
159165
cmd_id = be16_to_cpu(hdr->command_id);
160166
wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
@@ -169,10 +175,6 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
169175
&wmi->drv_priv->fatal_work);
170176
break;
171177
case WMI_TXSTATUS_EVENTID:
172-
/* Check if ath9k_tx_init() completed. */
173-
if (!data_race(priv->tx.initialized))
174-
break;
175-
176178
spin_lock_bh(&priv->tx.tx_lock);
177179
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
178180
spin_unlock_bh(&priv->tx.tx_lock);

0 commit comments

Comments
 (0)