Fix two problems in umass:
 * usb xfers being freed before being removed from pipe, leading to null deref
 * config_activate requests not supported, which leads to config_deactivate requests not being passed through. Spotted by jmcneill@

Added mechanism to usbdi allowing the default pipe to be aborted
This commit is contained in:
jmorse 2008-12-12 05:35:11 +00:00
parent 0107bf153f
commit beb501f394
3 changed files with 33 additions and 15 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: umass.c,v 1.129 2008/09/06 21:49:00 rmind Exp $ */
/* $NetBSD: umass.c,v 1.130 2008/12/12 05:35:11 jmorse Exp $ */
/*
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -124,7 +124,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.129 2008/09/06 21:49:00 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.130 2008/12/12 05:35:11 jmorse Exp $");
#include "atapibus.h"
#include "scsibus.h"
@ -692,7 +692,11 @@ umass_activate(device_t dev, enum devact act)
switch (act) {
case DVACT_ACTIVATE:
rv = EOPNOTSUPP;
if (scbus == NULL || scbus->sc_child == NULL)
break;
rv = config_activate(scbus->sc_child);
DPRINTF(UDMASS_USB, ("%s: umass activate: child "
"returned %d\n", USBDEVNAME(sc->sc_dev), rv));
break;
case DVACT_DEACTIVATE:
@ -700,7 +704,7 @@ umass_activate(device_t dev, enum devact act)
if (scbus == NULL || scbus->sc_child == NULL)
break;
rv = config_deactivate(scbus->sc_child);
DPRINTF(UDMASS_USB, ("%s: umass_activate: child "
DPRINTF(UDMASS_USB, ("%s: umass_deactivate: child "
"returned %d\n", USBDEVNAME(sc->sc_dev), rv));
break;
}
@ -714,20 +718,24 @@ umass_disco(struct umass_softc *sc)
DPRINTF(UDMASS_GEN, ("umass_disco\n"));
/* Remove all the pipes. */
for (i = 0 ; i < UMASS_NEP ; i++) {
if (sc->sc_pipe[i] != NULL) {
usbd_abort_pipe(sc->sc_pipe[i]);
usbd_close_pipe(sc->sc_pipe[i]);
sc->sc_pipe[i] = NULL;
}
}
/* Some xfers may be queued in the default pipe */
usbd_abort_default_pipe(sc->sc_udev);
/* Free the xfers. */
for (i = 0; i < XFER_NR; i++)
if (sc->transfer_xfer[i] != NULL) {
usbd_free_xfer(sc->transfer_xfer[i]);
sc->transfer_xfer[i] = NULL;
}
/* Remove all the pipes. */
for (i = 0 ; i < UMASS_NEP ; i++) {
if (sc->sc_pipe[i] != NULL) {
usbd_close_pipe(sc->sc_pipe[i]);
sc->sc_pipe[i] = NULL;
}
}
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi.c,v 1.124 2008/10/11 05:07:20 jmcneill Exp $ */
/* $NetBSD: usbdi.c,v 1.125 2008/12/12 05:35:11 jmorse 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.124 2008/10/11 05:07:20 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.125 2008/12/12 05:35:11 jmorse Exp $");
#include "opt_compat_netbsd.h"
@ -505,6 +505,15 @@ usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index)
return (iface->endpoints[index].edesc);
}
/* Some drivers may wish to abort requests on the default pipe, *
* but there is no mechanism for getting a handle on it. */
usbd_status
usbd_abort_default_pipe(struct usbd_device *device)
{
return usbd_abort_pipe(device->default_pipe);
}
usbd_status
usbd_abort_pipe(usbd_pipe_handle pipe)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi.h,v 1.76 2008/04/28 20:24:01 martin Exp $ */
/* $NetBSD: usbdi.h,v 1.77 2008/12/12 05:35:11 jmorse Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $ */
/*
@ -112,6 +112,7 @@ void usbd_get_xfer_status(usbd_xfer_handle, usbd_private_handle *,
usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor
(usbd_interface_handle, u_int8_t);
usbd_status usbd_abort_pipe(usbd_pipe_handle);
usbd_status usbd_abort_default_pipe(usbd_device_handle);
usbd_status usbd_clear_endpoint_stall(usbd_pipe_handle);
usbd_status usbd_clear_endpoint_stall_async(usbd_pipe_handle);
void usbd_clear_endpoint_toggle(usbd_pipe_handle);