Re: second race in hiddev

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Wednesday 21 January 2009 10:05:22 schrieb Jiri Kosina:
> On Fri, 9 Jan 2009, Oliver Neukum wrote:
> 
> > upon further thought this code is still racy.
> > 
> > 	retval = usb_register_dev(usbhid->intf, &hiddev_class);
> > 
> > here you open a window during which open can happen
> > 
> > 	if (retval) {
> > 		err_hid("Not able to get a minor for this device.");
> > 		hid->hiddev = NULL;
> > 		kfree(hiddev);
> > 		return -1;
> > 	} else {
> > 		hid->minor = usbhid->intf->minor;
> > 		hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
> > 
> > and will fail because hiddev_table hasn't been updated
> 
> Indeed, thanks for catching that. It's a small race window and not very 
> probably to be hit (or users aren't that fast, right? :) ).

Users may not be that fast. Udev scripts may be. At least I hope we
want our udev fast and we've seen SMIs running for hundreds
of milliseconds.

> > The obvious fix of using a mutex to guard hiddev_table doesn't work 
> > because usb_open() and usb_register_dev() take minor_rwsem and we'd have 
> > an AB-BA deadlock. We need a lock usb_open() also takes in the right 
> > order and that leaves only one option, BKL. I don't like it but I see no 
> > alternative.
> [ ... ]
> > @@ -878,16 +878,19 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
> >  	hiddev->hid = hid;
> >  	hiddev->exist = 1;
> >  
> > +	lock_kernel();
> >  	retval = usb_register_dev(usbhid->intf, &hiddev_class);
> >  	if (retval) {
> >  		err_hid("Not able to get a minor for this device.");
> >  		hid->hiddev = NULL;
> > +		unlock_kernel();
> >  		kfree(hiddev);
> >  		return -1;
> >  	} else {
> >  		hid->minor = usbhid->intf->minor;
> >  		hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
> >  	}
> > +	unlock_kernel();
> 
> This is really not nice and I would like to avoid pulling BKL in as much 
> as possible.
> 
> What exactly is the lock_kernel() in usb_open() protecting from anyway?

I guess it wasn't removed because
a) disconnect() used to take BKL
b) nobody was ready to check all open() methods for dependency on BKL
 
> Why isn't minor_rwsem sufficient protection?

It is dropped too early. It is held only while a device is registered, not
during enough of probing.

	Regards
		Oliver
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux