Bug 188771

Summary: Function lan78xx_probe() does not set error code when the call to usb_alloc_urb() fails
Product: Drivers Reporter: bianpan (bianpan2010)
Component: NetworkAssignee: drivers_network (drivers_network)
Status: RESOLVED CODE_FIX    
Severity: normal    
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: linux-4.9-rc6 Subsystem:
Regression: No Bisected commit-id:
Attachments: The patch fixes the bug

Description bianpan 2016-11-25 10:57:40 UTC
Function usb_alloc_urb() returns a NULL pointer if there is no enough memory. In function lan78xx_probe() defined in drivers/net/usb/lan78xx.c, function usb_alloc_urb() is called (at line 3396) and its return value is checked (at line 3397). If the return value is NULL, it jumps to label "out" and returns the value of variable ret. However, after the check of ret at line 3374, the value of ret is 0. As a result, function lan78xx_probe() may returns 0 (indicates success) even if there are errors. Maybe it is better to assign "-ENOMEM" to ret before the jump instruction at line 3399. Codes related to this bug are shown as follows.

lan78xx_probe @@ drivers/net/usb/lan78xx.c
3320 static int lan78xx_probe(struct usb_interface *intf,
3321              const struct usb_device_id *id)
3322 {
3323     struct lan78xx_net *dev;
3324     struct net_device *netdev;
3325     struct usb_device *udev;
3326     int ret;
         ...
3373     ret = lan78xx_bind(dev, intf);
3374     if (ret < 0)
3375         goto out2;
3376     strcpy(netdev->name, "eth%d");
         ...
3393     maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
3394     buf = kmalloc(maxp, GFP_KERNEL);
3395     if (buf) {
3396         dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
3397         if (!dev->urb_intr) {
3398             kfree(buf);
                 // insert "ret = -ENOMEM" before the jump instruction?
3399             goto out3; 
3400         } else {
3401             usb_fill_int_urb(dev->urb_intr, dev->udev,
3402                      dev->pipe_intr, buf, maxp,
3403                      intr_complete, dev, period);
3404         }
3405     }
         ...
3428     return 0;
3429 
3430 out3:
3431     lan78xx_unbind(dev, intf);
3432 out2:
3433     free_netdev(netdev);
3434 out1:
3435     usb_put_dev(udev);
3436 
3437     return ret;
3438 }

Thanks very much!
Comment 1 bianpan 2017-05-11 23:52:27 UTC
Created attachment 256415 [details]
The patch fixes the bug

The patch has been merged into the latest version of the Linux kernel. So I will close the bug.