linux/drivers/base
Daniel Ritz 4c898c7f2f [PATCH] Driver Core: fis bus rescan devices race
bus_rescan_devices_helper() does not hold the dev->sem when it checks for
!dev->driver().  device_attach() holds the sem, but calls again
device_bind_driver() even when dev->driver is set.

What happens is that a first device_attach() call (module insertion time)
is on the way binding the device to a driver.  Another thread calls
bus_rescan_devices().  Now when bus_rescan_devices_helper() checks for
dev->driver it is still NULL 'cos the the prior device_attach() is not yet
finished.  But as soon as the first one releases the dev->sem the second
device_attach() tries to rebind the already bound device again.
device_bind_driver() does this blindly which leads to a corrupt
driver->klist_devices list (the device links itself, the head points to the
device).  Later a call to device_release_driver() sets dev->driver to NULL
and breaks the link it has to itself on knode_driver.  Rmmoding the driver
later calls driver_detach() which leads to an endless loop 'cos the list
head in klist_devices still points to the device.  And since dev->driver is
NULL it's stuck with the same device forever.  Boom.  And rmmod hangs.

Very easy to reproduce with new-style pcmcia and a 16bit card.  Just loop
modprobe <pcmcia-modules> ;cardctl eject; rmmod <card driver, pcmcia
modules>.

Easiest fix is to check if the device is already bound to a driver in
device_bind_driver().  This avoids the double binding.

Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-22 07:58:24 -07:00
..
power [PATCH] swsusp: switch pm_message_t to struct 2005-09-05 00:06:16 -07:00
attribute_container.c [PATCH] drivers/base/*: use kzalloc instead of kmalloc+memset 2005-09-13 08:22:27 -07:00
base.h [PATCH] driver core: Add the ability to bind drivers to devices from userspace 2005-06-29 22:48:04 -07:00
bus.c [PATCH] fix klist semantics for lists which have elements removed on traversal 2005-09-07 18:26:54 -07:00
class.c [PATCH] drivers/base/*: use kzalloc instead of kmalloc+memset 2005-09-13 08:22:27 -07:00
core.c [PATCH] fix klist semantics for lists which have elements removed on traversal 2005-09-07 18:26:54 -07:00
cpu.c [PATCH] generate hotplug events for cpu online 2005-06-25 16:24:31 -07:00
dd.c [PATCH] Driver Core: fis bus rescan devices race 2005-09-22 07:58:24 -07:00
dmapool.c [PATCH] dmapool: Fix "nocast type" warnings 2005-09-10 10:06:29 -07:00
driver.c [PATCH] fix klist semantics for lists which have elements removed on traversal 2005-09-07 18:26:54 -07:00
firmware_class.c [PATCH] drivers/base/*: use kzalloc instead of kmalloc+memset 2005-09-13 08:22:27 -07:00
firmware.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
init.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
Kconfig Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
Makefile [PATCH] Move device/driver code to drivers/base/dd.c 2005-06-20 15:15:13 -07:00
map.c [PATCH] drivers/base/*: use kzalloc instead of kmalloc+memset 2005-09-13 08:22:27 -07:00
node.c [PATCH] VM: add page_state info to per-node meminfo 2005-09-05 00:05:49 -07:00
platform.c [PATCH] drivers/base/*: use kzalloc instead of kmalloc+memset 2005-09-13 08:22:27 -07:00
sys.c [PATCH] Driver core: hande sysdev suspend failure 2005-09-05 16:03:12 -07:00
transport_class.c [SCSI] fix transport class corner case after rework 2005-08-28 11:14:06 -05:00