[U-Boot] usb: hub enumeration and potential NULL ptr dereference in usb_device_info()

Bernhard Nortmann bernhard.nortmann at web.de
Wed Jun 22 11:05:26 CEST 2016


Starting with commit b19236fd1c1ef289bab9e243ee5b50d658fcac3f I am observing
a breakage of the "usb info" command on my BananaPi (Allwinner A20, sun7i),
while "usb tree" and dm commands ("dm tree", "dm uclass") are fine.
See attached usb-info-breakage.log

Tracing back the error positon from pc and lr registers pointed me to the
device_get_uclass_id() call within usb_device_info(), and suggested the
problem is caused by trying to dereference a NULL struct udevice *hub.

Therefore I added a diagnostic printf and a safeguard to this routine:

diff --git a/cmd/usb.c b/cmd/usb.c
index b83d323..a5e2463 100644
--- a/cmd/usb.c
+++ b/cmd/usb.c
@@ -610,6 +610,12 @@ static int usb_device_info(void)
          struct udevice *hub;

          device_find_first_child(bus, &hub);
+        printf("bus %p, uclass %d, hub %p: ",
+            bus, device_get_uclass_id(bus), hub);
+        if (!hub) {
+            printf("<no hub>\n");
+            continue;
+        }
          if (device_get_uclass_id(hub) == UCLASS_USB_HUB &&
              device_active(hub)) {
              show_info(hub);

And it became apparent that hub actually receives NULL values during the
device enumeration. The safeguard prevented the "data abort" error and got
"usb info" working again - see attached usb-info-fixed.log

I'm not sure why this particular problem didn't manifest earlier and
only now became apparent with the change in SPL header size /
CONFIG_SPL_TEXT_BASE. But it seems that accessing a NULL hub with
device_get_uclass_id() is clearly wrong and should be avoided.
Which brings me to two questions:

1. Is getting a NULL hub value legit when iterating UCLASS_USB devices
    the way that usb_device_info() does? If yes, the code seems to be
    lacking protection against passing it to device_get_uclass_id().

2. Why does usb_device_info() choose to enumerate hubs this way at all?
    If the routine is aiming at UCLASS_USB_HUB - which seems to be the
    purpose of the subsequent device_get_uclass_id(hub) test - and the
    device tree already provides this information (as suggested by the
    output of "dm uclass"), then why not enumerate UCLASS_USB_HUB directly?

Regards, B. Nortmann

-------------- next part --------------
A non-text attachment was scrubbed...
Name: usb-info-breakage.log
Type: application/octet-stream
Size: 3004 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160622/02f353a1/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: usb-info-fixed.log
Type: application/octet-stream
Size: 3166 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160622/02f353a1/attachment-0001.obj>


More information about the U-Boot mailing list