mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 21:44:06 +08:00
USB: core: Fix access violation during port device removal
commita4b46d450c
upstream. 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 <stern@rowland.harvard.edu> Reported-and-tested-by: Yue Sun <samsun1006219@gmail.com> Reported-by: xingwei lee <xrivendell7@gmail.com> Link: https://lore.kernel.org/linux-usb/CAEkJfYON+ry7xPx=AiLR9jzUNT+i_Va68ACajOC3HoacOfL1ig@mail.gmail.com/ Fixes:f061f43d74
("usb: hub: port: add sysfs entry to switch port power") CC: Michael Grzeschik <m.grzeschik@pengutronix.de> CC: stable@vger.kernel.org Link: https://lore.kernel.org/r/393aa580-15a5-44ca-ad3b-6462461cd313@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7fce5501d7
commit
63533549ff
@ -50,13 +50,15 @@ static ssize_t disable_show(struct device *dev,
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
struct usb_device *hdev = to_usb_device(dev->parent->parent);
|
||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||
struct usb_interface *intf = to_usb_interface(hub->intfdev);
|
||||
struct usb_interface *intf = to_usb_interface(dev->parent);
|
||||
int port1 = port_dev->portnum;
|
||||
u16 portstatus, unused;
|
||||
bool disabled;
|
||||
int rc;
|
||||
struct kernfs_node *kn;
|
||||
|
||||
if (!hub)
|
||||
return -ENODEV;
|
||||
hub_get(hub);
|
||||
rc = usb_autopm_get_interface(intf);
|
||||
if (rc < 0)
|
||||
@ -100,12 +102,14 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
struct usb_device *hdev = to_usb_device(dev->parent->parent);
|
||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||
struct usb_interface *intf = to_usb_interface(hub->intfdev);
|
||||
struct usb_interface *intf = to_usb_interface(dev->parent);
|
||||
int port1 = port_dev->portnum;
|
||||
bool disabled;
|
||||
int rc;
|
||||
struct kernfs_node *kn;
|
||||
|
||||
if (!hub)
|
||||
return -ENODEV;
|
||||
rc = kstrtobool(buf, &disabled);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
Loading…
Reference in New Issue
Block a user