* 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
[parent not found: <200901091121.56576.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>]
* 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
[parent not found: <200901211026.35066.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>]
* 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).