@@ -234,7 +234,8 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
/* Check if there has been a timeout. */
spin_lock_irqsave(&wmi->wmi_lock, flags);
- if (be16_to_cpu(hdr->seq_no) != wmi->last_seq_id) {
+ if (be16_to_cpu(hdr->seq_no) != wmi->last_seq_id ||
+ wmi->timedout) {
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
goto free_skb;
}
@@ -290,6 +291,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,
spin_lock_irqsave(&wmi->wmi_lock, flags);
wmi->last_seq_id = wmi->tx_seq_id;
+ wmi->timedout = false;
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid);
@@ -341,6 +343,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
if (!time_left) {
ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n",
wmi_cmd_to_name(cmd_id));
+ wmi->timedout = true;
mutex_unlock(&wmi->op_mutex);
return -ETIMEDOUT;
}
@@ -158,6 +158,7 @@ struct wmi {
u8 *cmd_rsp_buf;
u32 cmd_rsp_len;
bool stopped;
+ bool timedout;
struct list_head pending_tx_events;
spinlock_t event_lock;
Fix a stack-out-of-bounds write that occurs in a WMI response callback function that is called after a timeout occurs in ath9k_wmi_cmd(). The callback writes to wmi->cmd_rsp_buf, a stack-allocated buffer that could no longer be valid when a timeout occurs. Checking seq_no is insufficient as the bug can occur between the timeout and the next WMI command. Add wmi->timedout to check whether a timeout occurred. Found by a modified version of syzkaller. BUG: KASAN: stack-out-of-bounds in ath9k_wmi_ctrl_rx Write of size 4 Call Trace: memcpy ath9k_wmi_ctrl_rx ath9k_htc_rx_msg ath9k_hif_usb_reg_in_cb __usb_hcd_giveback_urb usb_hcd_giveback_urb dummy_timer call_timer_fn run_timer_softirq __do_softirq irq_exit_rcu sysvec_apic_timer_interrupt Signed-off-by: Minsuk Kang <linuxlovemin@yonsei.ac.kr> --- drivers/net/wireless/ath/ath9k/wmi.c | 5 ++++- drivers/net/wireless/ath/ath9k/wmi.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-)