USB: Check and set the Device object state appropriately.

The Device object gets an ID before it begins initializing, and
loses its ID after it fully finishes tearing down, so simply
verifying the Device object is non-NULL is not enough to verify
that we can use it. We need to call InitCheck() every time.

In Device itself, we should also unset fInitOK when beginning
teardown, so that anyone who still has a handle can no longer
use this Device object while teardown occurs (which, depending
on the number of pipes, pending transfers, etc. may take some
time.)

Fixes #14949 and almost certainly any other USB-related KDLs
in these codepaths.
This commit is contained in:
Augustin Cavalier
2019-05-17 16:24:06 -04:00
parent f8fdf848d0
commit dd249016c2
2 changed files with 63 additions and 33 deletions
@@ -321,6 +321,9 @@ Device::Device(Object* parent, int8 hubAddress, uint8 hubPort,
Device::~Device()
{
// Unset fInitOK to indicate we are tearing down.
fInitOK = false;
delete fDefaultPipe;
if (fConfigurations == NULL) {
+60 -33
View File
@@ -219,65 +219,80 @@ uninstall_notify(const char *driverName)
const usb_device_descriptor *
get_device_descriptor(usb_device device)
get_device_descriptor(usb_device dev)
{
TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", device);
Object *object = gUSBStack->GetObject(device);
TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return NULL;
return ((Device *)object)->DeviceDescriptor();
return device->DeviceDescriptor();
}
const usb_configuration_info *
get_nth_configuration(usb_device device, uint32 index)
get_nth_configuration(usb_device dev, uint32 index)
{
TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
device, index);
Object *object = gUSBStack->GetObject(device);
dev, index);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return NULL;
return ((Device *)object)->ConfigurationAt((int32)index);
return device->ConfigurationAt((int32)index);
}
const usb_configuration_info *
get_configuration(usb_device device)
get_configuration(usb_device dev)
{
TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", device);
Object *object = gUSBStack->GetObject(device);
TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return NULL;
return ((Device *)object)->Configuration();
return device->Configuration();
}
status_t
set_configuration(usb_device device,
set_configuration(usb_device dev,
const usb_configuration_info *configuration)
{
TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", device,
TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev,
configuration);
Object *object = gUSBStack->GetObject(device);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return B_NO_INIT;
return ((Device *)object)->SetConfiguration(configuration);
return device->SetConfiguration(configuration);
}
status_t
set_alt_interface(usb_device device, const usb_interface_info *interface)
set_alt_interface(usb_device dev, const usb_interface_info *interface)
{
TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", device, interface);
Object *object = gUSBStack->GetObject(device);
TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return B_NO_INIT;
return ((Device *)object)->SetAltInterface(interface);
return device->SetAltInterface(interface);
}
@@ -321,50 +336,59 @@ get_status(usb_id handle, uint16 *status)
status_t
get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID,
void *data, size_t dataLength, size_t *actualLength)
{
TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
"%" B_PRIuSIZE ", %p)\n",
device, type, index, languageID, data, dataLength, actualLength);
Object *object = gUSBStack->GetObject(device);
dev, type, index, languageID, data, dataLength, actualLength);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return B_NO_INIT;
return ((Device *)object)->GetDescriptor(type, index, languageID,
return device->GetDescriptor(type, index, languageID,
data, dataLength, actualLength);
}
status_t
send_request(usb_device device, uint8 requestType, uint8 request,
send_request(usb_device dev, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
{
TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
"%d, %p, %p)\n", device, requestType, request, value, index, length,
"%d, %p, %p)\n", dev, requestType, request, value, index, length,
data, actualLength);
Object *object = gUSBStack->GetObject(device);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return B_NO_INIT;
return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request,
return device->DefaultPipe()->SendRequest(requestType, request,
value, index, length, data, length, actualLength);
}
status_t
queue_request(usb_device device, uint8 requestType, uint8 request,
queue_request(usb_device dev, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data,
usb_callback_func callback, void *callbackCookie)
{
TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
" %u, %p, %p, %p)\n", device, requestType, request, value, index,
" %u, %p, %p, %p)\n", dev, requestType, request, value, index,
length, data, callback, callbackCookie);
Object *object = gUSBStack->GetObject(device);
Object *object = gUSBStack->GetObject(dev);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return B_NO_INIT;
return ((Device *)object)->DefaultPipe()->QueueRequest(requestType,
return device->DefaultPipe()->QueueRequest(requestType,
request, value, index, length, data, length, callback, callbackCookie);
}
@@ -487,9 +511,12 @@ usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_BAD_VALUE;
Device *device = (Device *)object;
if (device->InitCheck() != B_OK)
return B_NO_INIT;
uint32 index = 0;
return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
return device->BuildDeviceName((char *)buffer, &index,
bufferSize, NULL);
}
}