Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: usb: pegasus: enable basic endpoint checking

pegasus_probe() fills URBs with hardcoded endpoint pipes without
verifying the endpoint descriptors:

- usb_rcvbulkpipe(dev, 1) for RX data
- usb_sndbulkpipe(dev, 2) for TX data
- usb_rcvintpipe(dev, 3) for status interrupts

A malformed USB device can present these endpoints with transfer types
that differ from what the driver assumes.

Add a pegasus_usb_ep enum for endpoint numbers, replacing magic
constants throughout. Add usb_check_bulk_endpoints() and
usb_check_int_endpoints() calls before any resource allocation to
verify endpoint types before use, rejecting devices with mismatched
descriptors at probe time, and avoid triggering assertion.

Similar fix to
- commit 90b7f2961798 ("net: usb: rtl8150: enable basic endpoint checking")
- commit 9e7021d2aeae ("net: usb: catc: enable basic endpoint checking")

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260222050633.410165-1-n7l8m4@u.northwestern.edu
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Ziyi Guo and committed by
Paolo Abeni
3d7e6ce3 983512f3

+30 -5
+30 -5
drivers/net/usb/pegasus.c
··· 28 28 BMSR_100FULL | BMSR_ANEGCAPABLE) 29 29 #define CARRIER_CHECK_DELAY (2 * HZ) 30 30 31 + /* 32 + * USB endpoints. 33 + */ 34 + 35 + enum pegasus_usb_ep { 36 + PEGASUS_USB_EP_CONTROL = 0, 37 + PEGASUS_USB_EP_BULK_IN = 1, 38 + PEGASUS_USB_EP_BULK_OUT = 2, 39 + PEGASUS_USB_EP_INT_IN = 3, 40 + }; 41 + 31 42 static bool loopback; 32 43 static bool mii_mode; 33 44 static char *devid; ··· 553 542 goto tl_sched; 554 543 goon: 555 544 usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, 556 - usb_rcvbulkpipe(pegasus->usb, 1), 545 + usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), 557 546 pegasus->rx_skb->data, PEGASUS_MTU, 558 547 read_bulk_callback, pegasus); 559 548 rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); ··· 593 582 return; 594 583 } 595 584 usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, 596 - usb_rcvbulkpipe(pegasus->usb, 1), 585 + usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), 597 586 pegasus->rx_skb->data, PEGASUS_MTU, 598 587 read_bulk_callback, pegasus); 599 588 try_again: ··· 721 710 ((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); 722 711 skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len); 723 712 usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb, 724 - usb_sndbulkpipe(pegasus->usb, 2), 713 + usb_sndbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_OUT), 725 714 pegasus->tx_buff, count, 726 715 write_bulk_callback, pegasus); 727 716 if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) { ··· 848 837 set_registers(pegasus, EthID, 6, net->dev_addr); 849 838 850 839 usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, 851 - usb_rcvbulkpipe(pegasus->usb, 1), 840 + usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), 852 841 pegasus->rx_skb->data, PEGASUS_MTU, 853 842 read_bulk_callback, pegasus); 854 843 if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { ··· 859 848 } 860 849 861 850 usb_fill_int_urb(pegasus->intr_urb, pegasus->usb, 862 - usb_rcvintpipe(pegasus->usb, 3), 851 + usb_rcvintpipe(pegasus->usb, PEGASUS_USB_EP_INT_IN), 863 852 pegasus->intr_buff, sizeof(pegasus->intr_buff), 864 853 intr_callback, pegasus, pegasus->intr_interval); 865 854 if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { ··· 1144 1133 pegasus_t *pegasus; 1145 1134 int dev_index = id - pegasus_ids; 1146 1135 int res = -ENOMEM; 1136 + static const u8 bulk_ep_addr[] = { 1137 + PEGASUS_USB_EP_BULK_IN | USB_DIR_IN, 1138 + PEGASUS_USB_EP_BULK_OUT | USB_DIR_OUT, 1139 + 0}; 1140 + static const u8 int_ep_addr[] = { 1141 + PEGASUS_USB_EP_INT_IN | USB_DIR_IN, 1142 + 0}; 1147 1143 1148 1144 if (pegasus_blacklisted(dev)) 1149 1145 return -ENODEV; 1146 + 1147 + /* Verify that all required endpoints are present */ 1148 + if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) || 1149 + !usb_check_int_endpoints(intf, int_ep_addr)) { 1150 + dev_err(&intf->dev, "Missing or invalid endpoints\n"); 1151 + return -ENODEV; 1152 + } 1150 1153 1151 1154 net = alloc_etherdev(sizeof(struct pegasus)); 1152 1155 if (!net)