Skip to content

Commit 2ff34c9

Browse files
committed
Merge branch 'net-lan78xx-fix-NULL-deref-and-memory-leak'
Johan Hovold says: ==================== net: lan78xx: fix NULL deref and memory leak The first two patches fix a NULL-pointer dereference at probe that can be triggered by a malicious device and a small transfer-buffer memory leak, respectively. For another subsystem I would have marked them: Cc: [email protected] # 4.3 The third one replaces the driver's current broken endpoint lookup helper, which could end up accepting incomplete interfaces and whose results weren't even useeren Johan ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents e911e99 + ea060b3 commit 2ff34c9

File tree

1 file changed

+31
-82
lines changed

1 file changed

+31
-82
lines changed

drivers/net/usb/lan78xx.c

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,6 @@ struct lan78xx_net {
377377
struct tasklet_struct bh;
378378
struct delayed_work wq;
379379

380-
struct usb_host_endpoint *ep_blkin;
381-
struct usb_host_endpoint *ep_blkout;
382-
struct usb_host_endpoint *ep_intr;
383-
384380
int msg_enable;
385381

386382
struct urb *urb_intr;
@@ -2860,78 +2856,12 @@ lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net)
28602856
return NETDEV_TX_OK;
28612857
}
28622858

2863-
static int
2864-
lan78xx_get_endpoints(struct lan78xx_net *dev, struct usb_interface *intf)
2865-
{
2866-
int tmp;
2867-
struct usb_host_interface *alt = NULL;
2868-
struct usb_host_endpoint *in = NULL, *out = NULL;
2869-
struct usb_host_endpoint *status = NULL;
2870-
2871-
for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
2872-
unsigned ep;
2873-
2874-
in = NULL;
2875-
out = NULL;
2876-
status = NULL;
2877-
alt = intf->altsetting + tmp;
2878-
2879-
for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
2880-
struct usb_host_endpoint *e;
2881-
int intr = 0;
2882-
2883-
e = alt->endpoint + ep;
2884-
switch (e->desc.bmAttributes) {
2885-
case USB_ENDPOINT_XFER_INT:
2886-
if (!usb_endpoint_dir_in(&e->desc))
2887-
continue;
2888-
intr = 1;
2889-
/* FALLTHROUGH */
2890-
case USB_ENDPOINT_XFER_BULK:
2891-
break;
2892-
default:
2893-
continue;
2894-
}
2895-
if (usb_endpoint_dir_in(&e->desc)) {
2896-
if (!intr && !in)
2897-
in = e;
2898-
else if (intr && !status)
2899-
status = e;
2900-
} else {
2901-
if (!out)
2902-
out = e;
2903-
}
2904-
}
2905-
if (in && out)
2906-
break;
2907-
}
2908-
if (!alt || !in || !out)
2909-
return -EINVAL;
2910-
2911-
dev->pipe_in = usb_rcvbulkpipe(dev->udev,
2912-
in->desc.bEndpointAddress &
2913-
USB_ENDPOINT_NUMBER_MASK);
2914-
dev->pipe_out = usb_sndbulkpipe(dev->udev,
2915-
out->desc.bEndpointAddress &
2916-
USB_ENDPOINT_NUMBER_MASK);
2917-
dev->ep_intr = status;
2918-
2919-
return 0;
2920-
}
2921-
29222859
static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
29232860
{
29242861
struct lan78xx_priv *pdata = NULL;
29252862
int ret;
29262863
int i;
29272864

2928-
ret = lan78xx_get_endpoints(dev, intf);
2929-
if (ret) {
2930-
netdev_warn(dev->net, "lan78xx_get_endpoints failed: %d\n",
2931-
ret);
2932-
return ret;
2933-
}
2934-
29352865
dev->data[0] = (unsigned long)kzalloc(sizeof(*pdata), GFP_KERNEL);
29362866

29372867
pdata = (struct lan78xx_priv *)(dev->data[0]);
@@ -3700,6 +3630,7 @@ static void lan78xx_stat_monitor(struct timer_list *t)
37003630
static int lan78xx_probe(struct usb_interface *intf,
37013631
const struct usb_device_id *id)
37023632
{
3633+
struct usb_host_endpoint *ep_blkin, *ep_blkout, *ep_intr;
37033634
struct lan78xx_net *dev;
37043635
struct net_device *netdev;
37053636
struct usb_device *udev;
@@ -3748,6 +3679,34 @@ static int lan78xx_probe(struct usb_interface *intf,
37483679

37493680
mutex_init(&dev->stats.access_lock);
37503681

3682+
if (intf->cur_altsetting->desc.bNumEndpoints < 3) {
3683+
ret = -ENODEV;
3684+
goto out2;
3685+
}
3686+
3687+
dev->pipe_in = usb_rcvbulkpipe(udev, BULK_IN_PIPE);
3688+
ep_blkin = usb_pipe_endpoint(udev, dev->pipe_in);
3689+
if (!ep_blkin || !usb_endpoint_is_bulk_in(&ep_blkin->desc)) {
3690+
ret = -ENODEV;
3691+
goto out2;
3692+
}
3693+
3694+
dev->pipe_out = usb_sndbulkpipe(udev, BULK_OUT_PIPE);
3695+
ep_blkout = usb_pipe_endpoint(udev, dev->pipe_out);
3696+
if (!ep_blkout || !usb_endpoint_is_bulk_out(&ep_blkout->desc)) {
3697+
ret = -ENODEV;
3698+
goto out2;
3699+
}
3700+
3701+
ep_intr = &intf->cur_altsetting->endpoint[2];
3702+
if (!usb_endpoint_is_int_in(&ep_intr->desc)) {
3703+
ret = -ENODEV;
3704+
goto out2;
3705+
}
3706+
3707+
dev->pipe_intr = usb_rcvintpipe(dev->udev,
3708+
usb_endpoint_num(&ep_intr->desc));
3709+
37513710
ret = lan78xx_bind(dev, intf);
37523711
if (ret < 0)
37533712
goto out2;
@@ -3759,18 +3718,7 @@ static int lan78xx_probe(struct usb_interface *intf,
37593718
netdev->max_mtu = MAX_SINGLE_PACKET_SIZE;
37603719
netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER);
37613720

3762-
dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0;
3763-
dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1;
3764-
dev->ep_intr = (intf->cur_altsetting)->endpoint + 2;
3765-
3766-
dev->pipe_in = usb_rcvbulkpipe(udev, BULK_IN_PIPE);
3767-
dev->pipe_out = usb_sndbulkpipe(udev, BULK_OUT_PIPE);
3768-
3769-
dev->pipe_intr = usb_rcvintpipe(dev->udev,
3770-
dev->ep_intr->desc.bEndpointAddress &
3771-
USB_ENDPOINT_NUMBER_MASK);
3772-
period = dev->ep_intr->desc.bInterval;
3773-
3721+
period = ep_intr->desc.bInterval;
37743722
maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
37753723
buf = kmalloc(maxp, GFP_KERNEL);
37763724
if (buf) {
@@ -3783,6 +3731,7 @@ static int lan78xx_probe(struct usb_interface *intf,
37833731
usb_fill_int_urb(dev->urb_intr, dev->udev,
37843732
dev->pipe_intr, buf, maxp,
37853733
intr_complete, dev, period);
3734+
dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
37863735
}
37873736
}
37883737

0 commit comments

Comments
 (0)