NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/39322: Memoryleaks in Ohci Driver (USB)

>Number:         39322
>Category:       kern
>Synopsis:       Memoryleaks in Ohci Driver (USB)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Aug 08 08:55:00 +0000 2008
>Originator:     Andreas Jacobs
>Release:        CVS Head from 2008-08-07
LANCOM Systems GmbH
I do not use the NetBSD operating system itself but only its USB-Stack ported 
to another OS.
If you attach an Ohci and later detach it again, it does not free all the 
memory it has allocated:

1) In ohci.c:715 init_ohci() calls usb_allocmem to allocate a memory block to 
which a reference is stored in sc->sc_hccadma. This block is never deallocated

2) In ohci.c:706 init_ohci() creates an empty SIMPLEQ sc->sc_free_xfers to hold 
a reserve of unused xfers. ohci_allocx() later tries to take new xfers from 
that queue or creates new xfers via malloc if that queue is emtpy. ohci_freex() 
returns xfers back to that queue. This is fine as long as the ohci is attached, 
but when the ohci vanishes, the xfers should be deallocated, because there 
isn't any longer a way to use them again.

Thank you for fixing this
Andreas Jacobs
Attach and detach an Ohci over and over again. This is hard to do, if that chip 
is part of your PC, but is possible, if you use a UMTS/HSPA modem attached via 
1) Deallocate the sc->sc_hccadma block in ohci_detach() via usb_freemem()
2) Deallocate all xfers in sc->sc_free_xfers in ohci_detach()

Here is a patch for that, in universal diff format with 3 lines of context:

Index: ohci.c
RCS file: /cvsroot/src/sys/dev/usb/ohci.c,v
retrieving revision 1.195
diff -U3 -r1.195 ohci.c
--- ohci.c      28 Jun 2008 17:42:53 -0000      1.195
+++ ohci.c      8 Aug 2008 08:29:39 -0000
@@ -385,6 +385,7 @@
 ohci_detach(struct ohci_softc *sc, int flags)
        int rv = 0;
+       usbd_xfer_handle xfer;

        if (sc->sc_child != NULL)
                rv = config_detach(sc->sc_child, flags);
@@ -397,6 +398,11 @@
        usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */

        /* free data structures XXX */
+       usb_freemem(&sc->sc_bus, &sc->sc_hccadma);
+       while((xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers)) != NULL) {
+               SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
+               k_free(xfer, M_USB);
+       }

        return (rv);

Home | Main Index | Thread Index | Old Index