Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Fix leak of a usbd_xfer_handle when a interrupt ...



details:   https://anonhg.NetBSD.org/src/rev/9ba9c2e14c67
branches:  trunk
changeset: 750847:9ba9c2e14c67
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sat Jan 16 17:03:03 2010 +0000

description:
Fix leak of a usbd_xfer_handle when a interrupt pipe is aborted then
closed:
usbd_open_pipe_intr() allocates a usbd_xfer_handle for pipe->intrxfer.
Most usb device drivers using interrupt pipes call usbd_abort_pipe()
then usbd_close_pipe(), usbd_close_pipe() is supposed to free pipe->intrxfer.
But usbd_abort_pipe() calls [uoe]hci_device_intr_abort() which,
if the xfer aborted is pipe's intrxfer, sets pipe->intrxfer to NULL.
So usbd_close_pipe() can't free it and the usbd_xfer_handle is lost.

To fix this, in usbd_abort_pipe() remember the pipe->intrxfer's value
on entrie, and if it's different after usbd_ar_pipe(), call
usbd_free_xfer with the original value.
Confirmed to fix the memory leak on close() with umodem(4) and
uplcom(4).

diffstat:

 sys/dev/usb/usbdi.c |  7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diffs (35 lines):

diff -r a38e88da8833 -r 9ba9c2e14c67 sys/dev/usb/usbdi.c
--- a/sys/dev/usb/usbdi.c       Sat Jan 16 16:12:01 2010 +0000
+++ b/sys/dev/usb/usbdi.c       Sat Jan 16 17:03:03 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usbdi.c,v 1.126 2009/11/12 07:58:32 uebayasi Exp $     */
+/*     $NetBSD: usbdi.c,v 1.127 2010/01/16 17:03:03 bouyer Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $      */
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.126 2009/11/12 07:58:32 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.127 2010/01/16 17:03:03 bouyer Exp $");
 
 #include "opt_compat_netbsd.h"
 
@@ -519,6 +519,7 @@
 {
        usbd_status err;
        int s;
+       usbd_xfer_handle intrxfer = pipe->intrxfer;
 
 #ifdef DIAGNOSTIC
        if (pipe == NULL) {
@@ -529,6 +530,8 @@
        s = splusb();
        err = usbd_ar_pipe(pipe);
        splx(s);
+       if (pipe->intrxfer != intrxfer)
+               usbd_free_xfer(intrxfer);
        return (err);
 }
 



Home | Main Index | Thread Index | Old Index