]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
usbip: vhci_hcd: fix NULL deref in status_show_vhci
authorAdrian Wowk <dev@adrianwowk.com>
Tue, 14 Apr 2026 01:00:49 +0000 (20:00 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 May 2026 09:34:27 +0000 (11:34 +0200)
platform_get_drvdata() can return NULL if a VHCI host controller's
probe failed (e.g. due to USB bus number exhaustion). status_show_vhci()
checked for a NULL pdev but not for a NULL hcd returned by
platform_get_drvdata(). Passing NULL to hcd_to_vhci_hcd() does not
return NULL - it returns a pointer offset of 0x260, causing a NULL
pointer dereference when that value is subsequently dereferenced.

Add a NULL check on hcd before calling hcd_to_vhci_hcd(). Move
status_show_not_ready() above status_show_vhci() to make it callable
from the new error path without a forward declaration.

Signed-off-by: Adrian Wowk <dev@adrianwowk.com>
Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://patch.msgid.link/20260414010050.158064-2-dev@adrianwowk.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/usbip/vhci_sysfs.c

index 5bc8c47788d45039364139eb96d4f45695c3f236..e4cde1645b9044ef7989fbd0620608717b51fa15 100644 (file)
@@ -59,6 +59,29 @@ static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vd
        *out += sprintf(*out, "\n");
 }
 
+static ssize_t status_show_not_ready(int pdev_nr, char *out)
+{
+       char *s = out;
+       int i = 0;
+
+       for (i = 0; i < VHCI_HC_PORTS; i++) {
+               out += sprintf(out, "hs  %04u %03u ",
+                                   (pdev_nr * VHCI_PORTS) + i,
+                                   VDEV_ST_NOTASSIGNED);
+               out += sprintf(out, "000 00000000 0000000000000000 0-0");
+               out += sprintf(out, "\n");
+       }
+
+       for (i = 0; i < VHCI_HC_PORTS; i++) {
+               out += sprintf(out, "ss  %04u %03u ",
+                                   (pdev_nr * VHCI_PORTS) + VHCI_HC_PORTS + i,
+                                   VDEV_ST_NOTASSIGNED);
+               out += sprintf(out, "000 00000000 0000000000000000 0-0");
+               out += sprintf(out, "\n");
+       }
+       return out - s;
+}
+
 /* Sysfs entry to show port status */
 static ssize_t status_show_vhci(int pdev_nr, char *out)
 {
@@ -76,6 +99,12 @@ static ssize_t status_show_vhci(int pdev_nr, char *out)
        }
 
        hcd = platform_get_drvdata(pdev);
+
+       if (!hcd) {
+               usbip_dbg_vhci_sysfs("show status error (hcd is NULL)\n");
+               return status_show_not_ready(pdev_nr, out);
+       }
+
        vhci_hcd = hcd_to_vhci_hcd(hcd);
        vhci = vhci_hcd->vhci;
 
@@ -104,29 +133,6 @@ static ssize_t status_show_vhci(int pdev_nr, char *out)
        return out - s;
 }
 
-static ssize_t status_show_not_ready(int pdev_nr, char *out)
-{
-       char *s = out;
-       int i = 0;
-
-       for (i = 0; i < VHCI_HC_PORTS; i++) {
-               out += sprintf(out, "hs  %04u %03u ",
-                                   (pdev_nr * VHCI_PORTS) + i,
-                                   VDEV_ST_NOTASSIGNED);
-               out += sprintf(out, "000 00000000 0000000000000000 0-0");
-               out += sprintf(out, "\n");
-       }
-
-       for (i = 0; i < VHCI_HC_PORTS; i++) {
-               out += sprintf(out, "ss  %04u %03u ",
-                                   (pdev_nr * VHCI_PORTS) + VHCI_HC_PORTS + i,
-                                   VDEV_ST_NOTASSIGNED);
-               out += sprintf(out, "000 00000000 0000000000000000 0-0");
-               out += sprintf(out, "\n");
-       }
-       return out - s;
-}
-
 static int status_name_to_id(const char *name)
 {
        char *c;