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