Skip to content

Commit 3d7e6ce

Browse files
haruki3hhhPaolo Abeni
authored andcommitted
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 90b7f29 ("net: usb: rtl8150: enable basic endpoint checking") - commit 9e7021d ("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>
1 parent 983512f commit 3d7e6ce

1 file changed

Lines changed: 30 additions & 5 deletions

File tree

drivers/net/usb/pegasus.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ static const char driver_name[] = "pegasus";
2828
BMSR_100FULL | BMSR_ANEGCAPABLE)
2929
#define CARRIER_CHECK_DELAY (2 * HZ)
3030

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+
3142
static bool loopback;
3243
static bool mii_mode;
3344
static char *devid;
@@ -542,7 +553,7 @@ static void read_bulk_callback(struct urb *urb)
542553
goto tl_sched;
543554
goon:
544555
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
545-
usb_rcvbulkpipe(pegasus->usb, 1),
556+
usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN),
546557
pegasus->rx_skb->data, PEGASUS_MTU,
547558
read_bulk_callback, pegasus);
548559
rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
@@ -582,7 +593,7 @@ static void rx_fixup(struct tasklet_struct *t)
582593
return;
583594
}
584595
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
585-
usb_rcvbulkpipe(pegasus->usb, 1),
596+
usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN),
586597
pegasus->rx_skb->data, PEGASUS_MTU,
587598
read_bulk_callback, pegasus);
588599
try_again:
@@ -710,7 +721,7 @@ static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb,
710721
((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
711722
skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len);
712723
usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb,
713-
usb_sndbulkpipe(pegasus->usb, 2),
724+
usb_sndbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_OUT),
714725
pegasus->tx_buff, count,
715726
write_bulk_callback, pegasus);
716727
if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
@@ -837,7 +848,7 @@ static int pegasus_open(struct net_device *net)
837848
set_registers(pegasus, EthID, 6, net->dev_addr);
838849

839850
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
840-
usb_rcvbulkpipe(pegasus->usb, 1),
851+
usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN),
841852
pegasus->rx_skb->data, PEGASUS_MTU,
842853
read_bulk_callback, pegasus);
843854
if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
@@ -848,7 +859,7 @@ static int pegasus_open(struct net_device *net)
848859
}
849860

850861
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
851-
usb_rcvintpipe(pegasus->usb, 3),
862+
usb_rcvintpipe(pegasus->usb, PEGASUS_USB_EP_INT_IN),
852863
pegasus->intr_buff, sizeof(pegasus->intr_buff),
853864
intr_callback, pegasus, pegasus->intr_interval);
854865
if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
@@ -1133,10 +1144,24 @@ static int pegasus_probe(struct usb_interface *intf,
11331144
pegasus_t *pegasus;
11341145
int dev_index = id - pegasus_ids;
11351146
int res = -ENOMEM;
1147+
static const u8 bulk_ep_addr[] = {
1148+
PEGASUS_USB_EP_BULK_IN | USB_DIR_IN,
1149+
PEGASUS_USB_EP_BULK_OUT | USB_DIR_OUT,
1150+
0};
1151+
static const u8 int_ep_addr[] = {
1152+
PEGASUS_USB_EP_INT_IN | USB_DIR_IN,
1153+
0};
11361154

11371155
if (pegasus_blacklisted(dev))
11381156
return -ENODEV;
11391157

1158+
/* Verify that all required endpoints are present */
1159+
if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
1160+
!usb_check_int_endpoints(intf, int_ep_addr)) {
1161+
dev_err(&intf->dev, "Missing or invalid endpoints\n");
1162+
return -ENODEV;
1163+
}
1164+
11401165
net = alloc_etherdev(sizeof(struct pegasus));
11411166
if (!net)
11421167
goto out;

0 commit comments

Comments
 (0)