Skip to content

Commit e6eb815

Browse files
Qiujun Huanggregkh
Qiujun Huang
authored andcommitted
ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb
commit 2bbcaae upstream. In ath9k_hif_usb_rx_cb interface number is assumed to be 0. usb_ifnum_to_if(urb->dev, 0) But it isn't always true. The case reported by syzbot: https://lore.kernel.org/linux-usb/[email protected] usb 2-1: new high-speed USB device number 2 using dummy_hcd usb 2-1: config 1 has an invalid interface number: 2 but max is 0 usb 2-1: config 1 has no interface number 0 usb 2-1: New USB device found, idVendor=0cf3, idProduct=9271, bcdDevice= 1.08 usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 general protection fault, probably for non-canonical address 0xdffffc0000000015: 0000 [#1] SMP KASAN KASAN: null-ptr-deref in range [0x00000000000000a8-0x00000000000000af] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.6.0-rc5-syzkaller #0 Call Trace __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 __do_softirq+0x21e/0x950 kernel/softirq.c:292 invoke_softirq kernel/softirq.c:373 [inline] irq_exit+0x178/0x1a0 kernel/softirq.c:413 exiting_irq arch/x86/include/asm/apic.h:546 [inline] smp_apic_timer_interrupt+0x141/0x540 arch/x86/kernel/apic/apic.c:1146 apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:829 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] Cc: Viktor Jägersküpper <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 6d4448c commit e6eb815

File tree

2 files changed

+42
-11
lines changed

2 files changed

+42
-11
lines changed

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

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,9 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
643643

644644
static void ath9k_hif_usb_rx_cb(struct urb *urb)
645645
{
646-
struct sk_buff *skb = (struct sk_buff *) urb->context;
647-
struct hif_device_usb *hif_dev =
648-
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
646+
struct rx_buf *rx_buf = (struct rx_buf *)urb->context;
647+
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
648+
struct sk_buff *skb = rx_buf->skb;
649649
int ret;
650650

651651
if (!skb)
@@ -685,14 +685,15 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
685685
return;
686686
free:
687687
kfree_skb(skb);
688+
kfree(rx_buf);
688689
}
689690

690691
static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
691692
{
692-
struct sk_buff *skb = (struct sk_buff *) urb->context;
693+
struct rx_buf *rx_buf = (struct rx_buf *)urb->context;
694+
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
695+
struct sk_buff *skb = rx_buf->skb;
693696
struct sk_buff *nskb;
694-
struct hif_device_usb *hif_dev =
695-
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
696697
int ret;
697698

698699
if (!skb)
@@ -750,6 +751,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
750751
return;
751752
free:
752753
kfree_skb(skb);
754+
kfree(rx_buf);
753755
urb->context = NULL;
754756
}
755757

@@ -795,7 +797,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
795797
init_usb_anchor(&hif_dev->mgmt_submitted);
796798

797799
for (i = 0; i < MAX_TX_URB_NUM; i++) {
798-
tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
800+
tx_buf = kzalloc(sizeof(*tx_buf), GFP_KERNEL);
799801
if (!tx_buf)
800802
goto err;
801803

@@ -832,15 +834,22 @@ static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
832834

833835
static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
834836
{
835-
struct urb *urb = NULL;
837+
struct rx_buf *rx_buf = NULL;
836838
struct sk_buff *skb = NULL;
839+
struct urb *urb = NULL;
837840
int i, ret;
838841

839842
init_usb_anchor(&hif_dev->rx_submitted);
840843
spin_lock_init(&hif_dev->rx_lock);
841844

842845
for (i = 0; i < MAX_RX_URB_NUM; i++) {
843846

847+
rx_buf = kzalloc(sizeof(*rx_buf), GFP_KERNEL);
848+
if (!rx_buf) {
849+
ret = -ENOMEM;
850+
goto err_rxb;
851+
}
852+
844853
/* Allocate URB */
845854
urb = usb_alloc_urb(0, GFP_KERNEL);
846855
if (urb == NULL) {
@@ -855,11 +864,14 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
855864
goto err_skb;
856865
}
857866

867+
rx_buf->hif_dev = hif_dev;
868+
rx_buf->skb = skb;
869+
858870
usb_fill_bulk_urb(urb, hif_dev->udev,
859871
usb_rcvbulkpipe(hif_dev->udev,
860872
USB_WLAN_RX_PIPE),
861873
skb->data, MAX_RX_BUF_SIZE,
862-
ath9k_hif_usb_rx_cb, skb);
874+
ath9k_hif_usb_rx_cb, rx_buf);
863875

864876
/* Anchor URB */
865877
usb_anchor_urb(urb, &hif_dev->rx_submitted);
@@ -885,6 +897,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
885897
err_skb:
886898
usb_free_urb(urb);
887899
err_urb:
900+
kfree(rx_buf);
901+
err_rxb:
888902
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
889903
return ret;
890904
}
@@ -896,14 +910,21 @@ static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev)
896910

897911
static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
898912
{
899-
struct urb *urb = NULL;
913+
struct rx_buf *rx_buf = NULL;
900914
struct sk_buff *skb = NULL;
915+
struct urb *urb = NULL;
901916
int i, ret;
902917

903918
init_usb_anchor(&hif_dev->reg_in_submitted);
904919

905920
for (i = 0; i < MAX_REG_IN_URB_NUM; i++) {
906921

922+
rx_buf = kzalloc(sizeof(*rx_buf), GFP_KERNEL);
923+
if (!rx_buf) {
924+
ret = -ENOMEM;
925+
goto err_rxb;
926+
}
927+
907928
/* Allocate URB */
908929
urb = usb_alloc_urb(0, GFP_KERNEL);
909930
if (urb == NULL) {
@@ -918,11 +939,14 @@ static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
918939
goto err_skb;
919940
}
920941

942+
rx_buf->hif_dev = hif_dev;
943+
rx_buf->skb = skb;
944+
921945
usb_fill_int_urb(urb, hif_dev->udev,
922946
usb_rcvintpipe(hif_dev->udev,
923947
USB_REG_IN_PIPE),
924948
skb->data, MAX_REG_IN_BUF_SIZE,
925-
ath9k_hif_usb_reg_in_cb, skb, 1);
949+
ath9k_hif_usb_reg_in_cb, rx_buf, 1);
926950

927951
/* Anchor URB */
928952
usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
@@ -948,6 +972,8 @@ static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
948972
err_skb:
949973
usb_free_urb(urb);
950974
err_urb:
975+
kfree(rx_buf);
976+
err_rxb:
951977
ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
952978
return ret;
953979
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ struct tx_buf {
8686
struct list_head list;
8787
};
8888

89+
struct rx_buf {
90+
struct sk_buff *skb;
91+
struct hif_device_usb *hif_dev;
92+
};
93+
8994
#define HIF_USB_TX_STOP BIT(0)
9095
#define HIF_USB_TX_FLUSH BIT(1)
9196

0 commit comments

Comments
 (0)