Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Remove race introduced by using usbd_sync_transf...



details:   https://anonhg.NetBSD.org/src/rev/7f6f4b524fd6
branches:  trunk
changeset: 789657:7f6f4b524fd6
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Aug 30 12:59:19 2013 +0000

description:
Remove race introduced by using usbd_sync_transfer_sig with a callback
that use the xfer cv (or does wake up on the xfer). The xfer has likely
been freed or re-used.

While here update utoppy(4) to use usbd_sync_transfer_sig.

Fixes PR/48151

diffstat:

 sys/dev/usb/usbdi_util.c |  43 ++++++++++---------------------------------
 sys/dev/usb/utoppy.c     |  43 +++++++------------------------------------
 2 files changed, 17 insertions(+), 69 deletions(-)

diffs (163 lines):

diff -r 3374c7077b5b -r 7f6f4b524fd6 sys/dev/usb/usbdi_util.c
--- a/sys/dev/usb/usbdi_util.c  Fri Aug 30 12:58:22 2013 +0000
+++ b/sys/dev/usb/usbdi_util.c  Fri Aug 30 12:59:19 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usbdi_util.c,v 1.60 2013/08/24 08:21:55 skrll Exp $    */
+/*     $NetBSD: usbdi_util.c,v 1.61 2013/08/30 12:59:19 skrll Exp $    */
 
 /*
  * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.60 2013/08/24 08:21:55 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.61 2013/08/30 12:59:19 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -415,19 +415,6 @@
        return (usbd_do_request(dev, &req, conf));
 }
 
-Static void usbd_bulk_transfer_cb(usbd_xfer_handle xfer,
-                                 usbd_private_handle priv, usbd_status status);
-Static void
-usbd_bulk_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
-                     usbd_status status)
-{
-
-       if (xfer->pipe->device->bus->lock)
-               cv_broadcast(&xfer->cv);
-       else
-               wakeup(xfer);   /* XXXSMP ok */
-}
-
 usbd_status
 usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
                   u_int16_t flags, u_int32_t timeout, void *buf,
@@ -435,33 +422,21 @@
 {
        usbd_status err;
 
-       usbd_setup_xfer(xfer, pipe, 0, buf, *size,
-                       flags, timeout, usbd_bulk_transfer_cb);
+       usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout, NULL);
+
        DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
+       err = usbd_sync_transfer_sig(xfer);
 
-       err = usbd_sync_transfer_sig(xfer);
        usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
        DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
        if (err) {
                DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
                usbd_clear_endpoint_stall(pipe);
        }
+
        return (err);
 }
 
-Static void usbd_intr_transfer_cb(usbd_xfer_handle xfer,
-                                 usbd_private_handle priv, usbd_status status);
-Static void
-usbd_intr_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
-                     usbd_status status)
-{
-
-       if (xfer->pipe->device->bus->lock)
-               cv_broadcast(&xfer->cv);
-       else
-               wakeup(xfer);   /* XXXSMP ok */
-}
-
 usbd_status
 usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
                   u_int16_t flags, u_int32_t timeout, void *buf,
@@ -469,11 +444,13 @@
 {
        usbd_status err;
 
-       usbd_setup_xfer(xfer, pipe, 0, buf, *size,
-                       flags, timeout, usbd_intr_transfer_cb);
+       usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout, NULL);
+
        DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size));
        err = usbd_sync_transfer_sig(xfer);
+
        usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
+
        DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size));
        if (err) {
                DPRINTF(("usbd_intr_transfer: error=%d\n", err));
diff -r 3374c7077b5b -r 7f6f4b524fd6 sys/dev/usb/utoppy.c
--- a/sys/dev/usb/utoppy.c      Fri Aug 30 12:58:22 2013 +0000
+++ b/sys/dev/usb/utoppy.c      Fri Aug 30 12:59:19 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: utoppy.c,v 1.21 2012/10/27 17:18:38 chs Exp $  */
+/*     $NetBSD: utoppy.c,v 1.22 2013/08/30 12:59:19 skrll Exp $        */
 
 /*-
  * Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: utoppy.c,v 1.21 2012/10/27 17:18:38 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: utoppy.c,v 1.22 2013/08/30 12:59:19 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -512,47 +512,18 @@
 }
 #endif
 
-/*
- * Very much like usbd_bulk_transfer(), except don't catch signals
- */
-static void
-utoppy_bulk_transfer_cb(usbd_xfer_handle xfer,
-    usbd_private_handle priv,
-    usbd_status status)
-{
-
-       if (xfer->pipe->device->bus->lock)
-               cv_broadcast(&xfer->cv);
-       else
-               wakeup(xfer);
-}
-
 static usbd_status
 utoppy_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
     u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size,
     const char *lbl)
 {
        usbd_status err;
-       int s, error;
+
+       usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout, NULL);
 
-       usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout,
-           utoppy_bulk_transfer_cb);
-       usbd_lock_pipe(pipe);   /* don't want callback until tsleep() */
-       err = usbd_transfer(xfer);
-       if (err != USBD_IN_PROGRESS) {
-               usbd_unlock_pipe(pipe);
-               return (err);
-       }
-       if (pipe->device->bus->lock)
-               error = cv_wait_sig(&xfer->cv, pipe->device->bus->lock);
-       else
-               error = tsleep((void *)xfer, PZERO, lbl, 0);
-       usbd_unlock_pipe(pipe);
-       if (error) {
-               usbd_abort_pipe(pipe);
-               return (USBD_INTERRUPTED);
-       }
-       usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
+       err = usbd_sync_transfer_sig(xfer);
+
+       usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
        return (err);
 }
 



Home | Main Index | Thread Index | Old Index