Hi again,
The CDC ACM driver assumes that the acm_disconnect function is always
called with the control interface as argument but this is not always the
case. If it is called with the data interface first then
acm_disconnect calls usb_driver_release_interface with the data interface and causes the kernel to crash.


I have attached a patch which checks which of the interfaces acm_disconnect is called with and calls usb_driver_release_interface
with the other one.


/Brian

Signed-off-by: [EMAIL PROTECTED]

diff -u linux-2.6.11-bk7.clean/drivers/usb/class/cdc-acm.c 
linux-2.6.11-bk7/drivers/usb/class/cdc-acm.c
--- linux-2.6.11-bk7.clean/drivers/usb/class/cdc-acm.c  2005-03-12 
22:43:31.000000000 +0100
+++ linux-2.6.11-bk7/drivers/usb/class/cdc-acm.c        2005-03-13 
01:35:14.000000000 +0100
@@ -790,6 +790,7 @@
 {
        struct acm *acm = usb_get_intfdata (intf);
        struct usb_device *usb_dev = interface_to_usbdev(intf);
+       struct usb_interface *other_interface = NULL;
 
        if (!acm || !acm->dev) {
                dbg("disconnect on nonexisting interface");
@@ -810,7 +811,14 @@
        usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, 
acm->read_dma);
        usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, 
acm->ctrl_dma);
 
-       usb_driver_release_interface(&acm_driver, acm->data);
+       if (intf == acm->data)
+               other_interface = acm->control;
+       else if (intf == acm->control)
+               other_interface = acm->data;
+       else
+               BUG();
+
+       usb_driver_release_interface(&acm_driver, other_interface);
 
        if (!acm->used) {
                tty_unregister_device(acm_tty_driver, acm->minor);

Reply via email to