Skip to content

Commit a4b46d4

Browse files
AlanSterngregkh
authored andcommitted
USB: core: Fix access violation during port device removal
Testing with KASAN and syzkaller revealed a bug in port.c:disable_store(): usb_hub_to_struct_hub() can return NULL if the hub that the port belongs to is concurrently removed, but the function does not check for this possibility before dereferencing the returned value. It turns out that the first dereference is unnecessary, since hub->intfdev is the parent of the port device, so it can be changed easily. Adding a check for hub == NULL prevents further problems. The same bug exists in the disable_show() routine, and it can be fixed the same way. Signed-off-by: Alan Stern <[email protected]> Reported-and-tested-by: Yue Sun <[email protected]> Reported-by: xingwei lee <[email protected]> Link: https://lore.kernel.org/linux-usb/CAEkJfYON+ry7xPx=AiLR9jzUNT+i_Va68ACajOC3HoacOfL1ig@mail.gmail.com/ Fixes: f061f43 ("usb: hub: port: add sysfs entry to switch port power") CC: Michael Grzeschik <[email protected]> CC: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 6d73572 commit a4b46d4

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

drivers/usb/core/port.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,15 @@ static ssize_t disable_show(struct device *dev,
5151
struct usb_port *port_dev = to_usb_port(dev);
5252
struct usb_device *hdev = to_usb_device(dev->parent->parent);
5353
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
54-
struct usb_interface *intf = to_usb_interface(hub->intfdev);
54+
struct usb_interface *intf = to_usb_interface(dev->parent);
5555
int port1 = port_dev->portnum;
5656
u16 portstatus, unused;
5757
bool disabled;
5858
int rc;
5959
struct kernfs_node *kn;
6060

61+
if (!hub)
62+
return -ENODEV;
6163
hub_get(hub);
6264
rc = usb_autopm_get_interface(intf);
6365
if (rc < 0)
@@ -101,12 +103,14 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
101103
struct usb_port *port_dev = to_usb_port(dev);
102104
struct usb_device *hdev = to_usb_device(dev->parent->parent);
103105
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
104-
struct usb_interface *intf = to_usb_interface(hub->intfdev);
106+
struct usb_interface *intf = to_usb_interface(dev->parent);
105107
int port1 = port_dev->portnum;
106108
bool disabled;
107109
int rc;
108110
struct kernfs_node *kn;
109111

112+
if (!hub)
113+
return -ENODEV;
110114
rc = kstrtobool(buf, &disabled);
111115
if (rc)
112116
return rc;

0 commit comments

Comments
 (0)