diff options
author | Aaron Durbin <adurbin@chromium.org> | 2015-07-31 17:08:00 -0500 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2015-08-13 16:34:09 +0200 |
commit | e3260ec29a0bce2d57ba66b99ea1d87a56e1e18a (patch) | |
tree | 82a00b6d401ea88235ec2840bcea78128f4d358d | |
parent | e33a1724b34d839fae16836a5bdde4d53a788c15 (diff) |
libpayload: usb: don't prematurely free the usb device
Before the controller's destroy_device() could interrogate
the usbdev_t object usb_detach_device() was freeing and
NULLing out the pointer. That results in all callers who
needed that object to start accessing random bits of memory.
This eventually led into free()ing memory it shouldn't which
corrupted the allocator's state. Eventually, all forward
progress was lost by way of a single ended linked list
turning into a circular list.
The culprit seems to be a bad merge in commit e00ba21.
BUG=chrome-os-partner:43419
BRANCH=None
TEST=Can boot into OS now w/o "hanging" on glados.
Original-Change-Id: I86dcaa1dbaf112ac6782e90dad40f0932f273a1f
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/290048
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Change-Id: I9135eb0f798bf7dbeccc7a033c3f8471720a0de5
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/11173
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
-rw-r--r-- | payloads/libpayload/drivers/usb/usb.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c index 69d1c39778..ffbe005e84 100644 --- a/payloads/libpayload/drivers/usb/usb.c +++ b/payloads/libpayload/drivers/usb/usb.c @@ -605,10 +605,12 @@ usb_detach_device(hci_t *controller, int devno) been called yet by the usb class driver */ if (controller->devices[devno]) { controller->devices[devno]->destroy (controller->devices[devno]); - free(controller->devices[devno]); - controller->devices[devno] = NULL; if (controller->destroy_device) controller->destroy_device(controller, devno); + /* Tear down the device itself *after* destroy_device() + * has had a chance to interoogate it. */ + free(controller->devices[devno]); + controller->devices[devno] = NULL; } } |