Skip to content

Commit abeaa85

Browse files
Qiujun HuangKalle Valo
authored andcommitted
ath9k: Fix use-after-free Read in ath9k_wmi_ctrl_rx
Free wmi later after cmd urb has been killed, as urb cb will access wmi. the case reported by syzbot: https://lore.kernel.org/linux-usb/[email protected] BUG: KASAN: use-after-free in ath9k_wmi_ctrl_rx+0x416/0x500 drivers/net/wireless/ath/ath9k/wmi.c:215 Read of size 1 at addr ffff8881cef1417c by task swapper/1/0 Call Trace: <IRQ> ath9k_wmi_ctrl_rx+0x416/0x500 drivers/net/wireless/ath/ath9k/wmi.c:215 ath9k_htc_rx_msg+0x2da/0xaf0 drivers/net/wireless/ath/ath9k/htc_hst.c:459 ath9k_hif_usb_reg_in_cb+0x1ba/0x630 drivers/net/wireless/ath/ath9k/hif_usb.c:718 __usb_hcd_giveback_urb+0x29a/0x550 drivers/usb/core/hcd.c:1650 usb_hcd_giveback_urb+0x368/0x420 drivers/usb/core/hcd.c:1716 dummy_timer+0x1258/0x32ae drivers/usb/gadget/udc/dummy_hcd.c:1966 call_timer_fn+0x195/0x6f0 kernel/time/timer.c:1404 expire_timers kernel/time/timer.c:1449 [inline] __run_timers kernel/time/timer.c:1773 [inline] __run_timers kernel/time/timer.c:1740 [inline] run_timer_softirq+0x5f9/0x1500 kernel/time/timer.c:1786 Reported-and-tested-by: [email protected] Signed-off-by: Qiujun Huang <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent ced21a4 commit abeaa85

File tree

5 files changed

+17
-7
lines changed

5 files changed

+17
-7
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
973973
return -ENOMEM;
974974
}
975975

976-
static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
976+
void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
977977
{
978978
usb_kill_anchored_urbs(&hif_dev->regout_submitted);
979979
ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
@@ -1341,8 +1341,9 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
13411341

13421342
if (hif_dev->flags & HIF_USB_READY) {
13431343
ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
1344-
ath9k_htc_hw_free(hif_dev->htc_handle);
13451344
ath9k_hif_usb_dev_deinit(hif_dev);
1345+
ath9k_destoy_wmi(hif_dev->htc_handle->drv_priv);
1346+
ath9k_htc_hw_free(hif_dev->htc_handle);
13461347
}
13471348

13481349
usb_set_intfdata(interface, NULL);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,6 @@ struct hif_device_usb {
133133

134134
int ath9k_hif_usb_init(void);
135135
void ath9k_hif_usb_exit(void);
136+
void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev);
136137

137138
#endif /* HTC_USB_H */

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -931,8 +931,9 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
931931
int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
932932
u16 devid, char *product, u32 drv_info)
933933
{
934-
struct ieee80211_hw *hw;
934+
struct hif_device_usb *hif_dev;
935935
struct ath9k_htc_priv *priv;
936+
struct ieee80211_hw *hw;
936937
int ret;
937938

938939
hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
@@ -967,7 +968,10 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
967968
return 0;
968969

969970
err_init:
970-
ath9k_deinit_wmi(priv);
971+
ath9k_stop_wmi(priv);
972+
hif_dev = (struct hif_device_usb *)htc_handle->hif_dev;
973+
ath9k_hif_usb_dealloc_urbs(hif_dev);
974+
ath9k_destoy_wmi(priv);
971975
err_free:
972976
ieee80211_free_hw(hw);
973977
return ret;
@@ -982,7 +986,7 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
982986
htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
983987

984988
ath9k_deinit_device(htc_handle->drv_priv);
985-
ath9k_deinit_wmi(htc_handle->drv_priv);
989+
ath9k_stop_wmi(htc_handle->drv_priv);
986990
ieee80211_free_hw(htc_handle->drv_priv->hw);
987991
}
988992
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,17 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)
112112
return wmi;
113113
}
114114

115-
void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
115+
void ath9k_stop_wmi(struct ath9k_htc_priv *priv)
116116
{
117117
struct wmi *wmi = priv->wmi;
118118

119119
mutex_lock(&wmi->op_mutex);
120120
wmi->stopped = true;
121121
mutex_unlock(&wmi->op_mutex);
122+
}
122123

124+
void ath9k_destoy_wmi(struct ath9k_htc_priv *priv)
125+
{
123126
kfree(priv->wmi);
124127
}
125128

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ struct wmi {
179179
};
180180

181181
struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv);
182-
void ath9k_deinit_wmi(struct ath9k_htc_priv *priv);
183182
int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi,
184183
enum htc_endpoint_id *wmi_ctrl_epid);
185184
int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
@@ -189,6 +188,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
189188
void ath9k_wmi_event_tasklet(unsigned long data);
190189
void ath9k_fatal_work(struct work_struct *work);
191190
void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
191+
void ath9k_stop_wmi(struct ath9k_htc_priv *priv);
192+
void ath9k_destoy_wmi(struct ath9k_htc_priv *priv);
192193

193194
#define WMI_CMD(_wmi_cmd) \
194195
do { \

0 commit comments

Comments
 (0)