* second race in hiddev
@ 2009-01-09 10:21 Oliver Neukum
[not found] ` <200901091121.56576.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: Oliver Neukum @ 2009-01-09 10:21 UTC (permalink / raw)
To: Jiri Kosina, linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA, Alan Stern
Hi,
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
}
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.
Regards
Oliver
Signed-off-by: Oliver Neukum <oneukum-l3A5Bk7waGM@public.gmane.org>
---
@@ -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();
return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: second race in hiddev
[not found] ` <200901091121.56576.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
@ 2009-01-21 9:05 ` Jiri Kosina
2009-01-21 9:26 ` Oliver Neukum
0 siblings, 1 reply; 4+ messages in thread
From: Jiri Kosina @ 2009-01-21 9:05 UTC (permalink / raw)
To: Oliver Neukum
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA, Alan Stern
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? :) ).
> 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?
Why isn't minor_rwsem sufficient protection?
--
Jiri Kosina
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: second race in hiddev
2009-01-21 9:05 ` Jiri Kosina
@ 2009-01-21 9:26 ` Oliver Neukum
[not found] ` <200901211026.35066.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: Oliver Neukum @ 2009-01-21 9:26 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-usb, linux-input, Alan Stern
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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: second race in hiddev
[not found] ` <200901211026.35066.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
@ 2009-02-12 12:21 ` Jiri Kosina
0 siblings, 0 replies; 4+ messages in thread
From: Jiri Kosina @ 2009-02-12 12:21 UTC (permalink / raw)
To: Oliver Neukum
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA, Alan Stern
On Wed, 21 Jan 2009, Oliver Neukum wrote:
> 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.
There really doesn't seem to be any other option with usb_open() relying
on lock_kernel() still.
I have added comment to the code and applied the patch, thanks a lot
Oliver.
--
Jiri Kosina
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-02-12 12:21 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-09 10:21 second race in hiddev Oliver Neukum
[not found] ` <200901091121.56576.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
2009-01-21 9:05 ` Jiri Kosina
2009-01-21 9:26 ` Oliver Neukum
[not found] ` <200901211026.35066.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
2009-02-12 12:21 ` Jiri Kosina
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).