lkml.org 
[lkml]   [2020]   [Jun]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 038/101] ath9k: Fix use-after-free Read in ath9k_wmi_ctrl_rx
    Date
    From: Qiujun Huang <hqjagain@gmail.com>

    commit abeaa85054ff8cfe8b99aafc5c70ea067e5d0908 upstream.

    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/0000000000000002fc05a1d61a68@google.com
    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: syzbot+5d338854440137ea0fef@syzkaller.appspotmail.com
    Signed-off-by: Qiujun Huang <hqjagain@gmail.com>
    Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
    Link: https://lore.kernel.org/r/20200404041838.10426-3-hqjagain@gmail.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/net/wireless/ath/ath9k/hif_usb.c | 5 +++--
    drivers/net/wireless/ath/ath9k/hif_usb.h | 1 +
    drivers/net/wireless/ath/ath9k/htc_drv_init.c | 10 +++++++---
    drivers/net/wireless/ath/ath9k/wmi.c | 5 ++++-
    drivers/net/wireless/ath/ath9k/wmi.h | 3 ++-
    5 files changed, 17 insertions(+), 7 deletions(-)

    --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
    +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
    @@ -969,7 +969,7 @@ err:
    return -ENOMEM;
    }

    -static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
    +void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
    {
    usb_kill_anchored_urbs(&hif_dev->regout_submitted);
    ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
    @@ -1336,8 +1336,9 @@ static void ath9k_hif_usb_disconnect(str

    if (hif_dev->flags & HIF_USB_READY) {
    ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
    - ath9k_htc_hw_free(hif_dev->htc_handle);
    ath9k_hif_usb_dev_deinit(hif_dev);
    + ath9k_destoy_wmi(hif_dev->htc_handle->drv_priv);
    + ath9k_htc_hw_free(hif_dev->htc_handle);
    }

    usb_set_intfdata(interface, NULL);
    --- a/drivers/net/wireless/ath/ath9k/hif_usb.h
    +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
    @@ -131,5 +131,6 @@ struct hif_device_usb {

    int ath9k_hif_usb_init(void);
    void ath9k_hif_usb_exit(void);
    +void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev);

    #endif /* HTC_USB_H */
    --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
    +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
    @@ -931,8 +931,9 @@ err_init:
    int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
    u16 devid, char *product, u32 drv_info)
    {
    - struct ieee80211_hw *hw;
    + struct hif_device_usb *hif_dev;
    struct ath9k_htc_priv *priv;
    + struct ieee80211_hw *hw;
    int ret;

    hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
    @@ -967,7 +968,10 @@ int ath9k_htc_probe_device(struct htc_ta
    return 0;

    err_init:
    - ath9k_deinit_wmi(priv);
    + ath9k_stop_wmi(priv);
    + hif_dev = (struct hif_device_usb *)htc_handle->hif_dev;
    + ath9k_hif_usb_dealloc_urbs(hif_dev);
    + ath9k_destoy_wmi(priv);
    err_free:
    ieee80211_free_hw(hw);
    return ret;
    @@ -982,7 +986,7 @@ void ath9k_htc_disconnect_device(struct
    htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;

    ath9k_deinit_device(htc_handle->drv_priv);
    - ath9k_deinit_wmi(htc_handle->drv_priv);
    + ath9k_stop_wmi(htc_handle->drv_priv);
    ieee80211_free_hw(htc_handle->drv_priv->hw);
    }
    }
    --- a/drivers/net/wireless/ath/ath9k/wmi.c
    +++ b/drivers/net/wireless/ath/ath9k/wmi.c
    @@ -112,14 +112,17 @@ struct wmi *ath9k_init_wmi(struct ath9k_
    return wmi;
    }

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

    mutex_lock(&wmi->op_mutex);
    wmi->stopped = true;
    mutex_unlock(&wmi->op_mutex);
    +}

    +void ath9k_destoy_wmi(struct ath9k_htc_priv *priv)
    +{
    kfree(priv->wmi);
    }

    --- a/drivers/net/wireless/ath/ath9k/wmi.h
    +++ b/drivers/net/wireless/ath/ath9k/wmi.h
    @@ -179,7 +179,6 @@ struct wmi {
    };

    struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv);
    -void ath9k_deinit_wmi(struct ath9k_htc_priv *priv);
    int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi,
    enum htc_endpoint_id *wmi_ctrl_epid);
    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
    void ath9k_wmi_event_tasklet(unsigned long data);
    void ath9k_fatal_work(struct work_struct *work);
    void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
    +void ath9k_stop_wmi(struct ath9k_htc_priv *priv);
    +void ath9k_destoy_wmi(struct ath9k_htc_priv *priv);

    #define WMI_CMD(_wmi_cmd) \
    do { \

    \
     
     \ /
      Last update: 2020-06-19 16:38    [W:3.147 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site