Fix for crash on eject after module removal

Pavel Roskin proski at gnu.org
Sat Apr 26 16:24:09 BST 2003


Hello!

The recent 2.5.x kernels panic if I remove a PCMCIA client module by 
rmmod and then do "cardctl eject":

modprobe yenta_socket
cardmgr
rmmod orinoco_cs
cardctl eject

The crash happens in unbind_request() when (*b)->driver->drv.name is
accessed.  pcmcia_unregister_driver() only sets instance on the bind to 0,
but it doesn't remove the bind.  Other fields on the bind structure, 
including "driver" remain populated with data that is no longer valid 
after the module has been removed.

The solution that works for me is to remove the whole bind (as list
element) from the lists for every socket in pcmcia_unregister_driver()
rather than wait for unbind_request() to do it for one particular socket.

The patch is attached.  It has been heavily tested.  However, please keeps 
in mind that there are many things in the PCMCIA subsystem that I don't 
understand.

I checked unregister_pccard_driver() and unbind_request() in pcmcia-cs and
Linux 2.4.x, and they are quite similar to those in 2.5.x kernels, but
they are probably called differently.

-- 
Regards,
Pavel Roskin


-------------- next part --------------
--- linux.orig/drivers/pcmcia/ds.c
+++ linux/drivers/pcmcia/ds.c
@@ -163,7 +163,7 @@ EXPORT_SYMBOL(pcmcia_register_driver);
  */
 void pcmcia_unregister_driver(struct pcmcia_driver *driver)
 {
-	socket_bind_t *b;
+	socket_bind_t **b, *c;
 	struct pcmcia_bus_socket *bus_sock;
 
 	if (driver->use_count > 0) {
@@ -171,9 +171,15 @@ void pcmcia_unregister_driver(struct pcm
 		driver->attach = NULL; driver->detach = NULL;
 		down_read(&bus_socket_list_rwsem);
 		list_for_each_entry(bus_sock, &bus_socket_list, socket_list) {
-			for (b = bus_sock->bind; b; b = b->next)
-				if (b->driver == driver) 
-					b->instance = NULL;
+			for (b = &bus_sock->bind; *b; b = &(*b)->next) {
+				if ((*b)->driver == driver) {
+					c = *b;
+					*b = c->next;
+					kfree(c);
+					if (!(*b))
+						break;
+				}
+			}
 		}
 		up_read(&bus_socket_list_rwsem);
 	}


More information about the linux-pcmcia mailing list