Skip to content

Commit

Permalink
Merge tag 'usb-5.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are some small USB fixes for 5.3-rc4.

  The "biggest" one here is moving code from one file to another in
  order to fix a long-standing race condition with the creation of sysfs
  files for USB devices. Turns out that there are now userspace tools
  out there that are hitting this long-known bug, so it's time to fix
  them. Thankfully the tool-maker in this case fixed the issue :)

  The other patches in here are all fixes for reported issues. Now that
  syzbot knows how to fuzz USB drivers better, and is starting to now
  fuzz the userspace facing side of them at the same time, there will be
  more and more small fixes like these coming, which is a good thing.

  All of these have been in linux-next with no reported issues"

* tag 'usb-5.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: setup authorized_default attributes using usb_bus_notify
  usb: iowarrior: fix deadlock on disconnect
  Revert "USB: rio500: simplify locking"
  usb: usbfs: fix double-free of usb memory upon submiturb error
  usb: yurex: Fix use-after-free in yurex_delete
  usb: typec: tcpm: Ignore unsupported/unknown alternate mode requests
  xhci: Fix NULL pointer dereference at endpoint zero reset.
  usb: host: xhci-rcar: Fix timeout in xhci_suspend()
  usb: typec: ucsi: ccg: Fix uninitilized symbol error
  usb: typec: tcpm: remove tcpm dir if no children
  usb: typec: tcpm: free log buf memory when remove debug file
  usb: typec: tcpm: Add NULL check before dereferencing config
  • Loading branch information
torvalds committed Aug 10, 2019
2 parents 97946f5 + 27709ae commit 1041f50
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 165 deletions.
2 changes: 0 additions & 2 deletions drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1812,8 +1812,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
return 0;

error:
if (as && as->usbm)
dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count);
kfree(isopkt);
kfree(dr);
if (as)
Expand Down
123 changes: 0 additions & 123 deletions drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,6 @@ static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
/* wait queue for synchronous unlinks */
DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);

static inline int is_root_hub(struct usb_device *udev)
{
return (udev->parent == NULL);
}

/*-------------------------------------------------------------------------*/

/*
Expand Down Expand Up @@ -880,101 +875,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
}



/*
* Show & store the current value of authorized_default
*/
static ssize_t authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;

hcd = bus_to_hcd(usb_bus);
return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
}

static ssize_t authorized_default_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
ssize_t result;
unsigned val;
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;

hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val);
if (result == 1) {
hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
val : USB_DEVICE_AUTHORIZE_ALL;
result = size;
} else {
result = -EINVAL;
}
return result;
}
static DEVICE_ATTR_RW(authorized_default);

/*
* interface_authorized_default_show - show default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);

return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
}

/*
* interface_authorized_default_store - store default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
int rc = count;
bool val;

if (strtobool(buf, &val) != 0)
return -EINVAL;

if (val)
set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
else
clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);

return rc;
}
static DEVICE_ATTR_RW(interface_authorized_default);

/* Group all the USB bus attributes */
static struct attribute *usb_bus_attrs[] = {
&dev_attr_authorized_default.attr,
&dev_attr_interface_authorized_default.attr,
NULL,
};

static const struct attribute_group usb_bus_attr_group = {
.name = NULL, /* we want them in the same directory */
.attrs = usb_bus_attrs,
};



/*-------------------------------------------------------------------------*/

/**
Expand Down Expand Up @@ -2894,32 +2794,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
if (retval != 0)
goto err_register_root_hub;

retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
if (retval < 0) {
printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
retval);
goto error_create_attr_group;
}
if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
usb_hcd_poll_rh_status(hcd);

return retval;

error_create_attr_group:
clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
if (HC_IS_RUNNING(hcd->state))
hcd->state = HC_STATE_QUIESCING;
spin_lock_irq(&hcd_root_hub_lock);
hcd->rh_registered = 0;
spin_unlock_irq(&hcd_root_hub_lock);

#ifdef CONFIG_PM
cancel_work_sync(&hcd->wakeup_work);
#endif
cancel_work_sync(&hcd->died_work);
mutex_lock(&usb_bus_idr_lock);
usb_disconnect(&rhdev); /* Sets rhdev to NULL */
mutex_unlock(&usb_bus_idr_lock);
err_register_root_hub:
hcd->rh_pollable = 0;
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
Expand Down Expand Up @@ -2963,8 +2842,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);

usb_get_dev(rhdev);
sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);

clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
if (HC_IS_RUNNING (hcd->state))
hcd->state = HC_STATE_QUIESCING;
Expand Down
121 changes: 121 additions & 0 deletions drivers/usb/core/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/quirks.h>
#include <linux/of.h>
#include "usb.h"
Expand Down Expand Up @@ -922,6 +923,116 @@ static struct bin_attribute dev_bin_attr_descriptors = {
.size = 18 + 65535, /* dev descr + max-size raw descriptor */
};

/*
* Show & store the current value of authorized_default
*/
static ssize_t authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;

hcd = bus_to_hcd(usb_bus);
return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
}

static ssize_t authorized_default_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
ssize_t result;
unsigned int val;
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;

hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val);
if (result == 1) {
hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
val : USB_DEVICE_AUTHORIZE_ALL;
result = size;
} else {
result = -EINVAL;
}
return result;
}
static DEVICE_ATTR_RW(authorized_default);

/*
* interface_authorized_default_show - show default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);

return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
}

/*
* interface_authorized_default_store - store default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
int rc = count;
bool val;

if (strtobool(buf, &val) != 0)
return -EINVAL;

if (val)
set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
else
clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);

return rc;
}
static DEVICE_ATTR_RW(interface_authorized_default);

/* Group all the USB bus attributes */
static struct attribute *usb_bus_attrs[] = {
&dev_attr_authorized_default.attr,
&dev_attr_interface_authorized_default.attr,
NULL,
};

static const struct attribute_group usb_bus_attr_group = {
.name = NULL, /* we want them in the same directory */
.attrs = usb_bus_attrs,
};


static int add_default_authorized_attributes(struct device *dev)
{
int rc = 0;

if (is_usb_device(dev))
rc = sysfs_create_group(&dev->kobj, &usb_bus_attr_group);

return rc;
}

static void remove_default_authorized_attributes(struct device *dev)
{
if (is_usb_device(dev)) {
sysfs_remove_group(&dev->kobj, &usb_bus_attr_group);
}
}

int usb_create_sysfs_dev_files(struct usb_device *udev)
{
struct device *dev = &udev->dev;
Expand All @@ -938,7 +1049,14 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
retval = add_power_attributes(dev);
if (retval)
goto error;

if (is_root_hub(udev)) {
retval = add_default_authorized_attributes(dev);
if (retval)
goto error;
}
return retval;

error:
usb_remove_sysfs_dev_files(udev);
return retval;
Expand All @@ -948,6 +1066,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
{
struct device *dev = &udev->dev;

if (is_root_hub(udev))
remove_default_authorized_attributes(dev);

remove_power_attributes(dev);
remove_persist_attributes(dev);
device_remove_bin_file(dev, &dev_bin_attr_descriptors);
Expand Down
5 changes: 5 additions & 0 deletions drivers/usb/core/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ static inline int is_usb_port(const struct device *dev)
return dev->type == &usb_port_device_type;
}

static inline int is_root_hub(struct usb_device *udev)
{
return (udev->parent == NULL);
}

/* Do the same for device drivers and interface drivers. */

static inline int is_usb_device_driver(struct device_driver *drv)
Expand Down
9 changes: 7 additions & 2 deletions drivers/usb/host/xhci-rcar.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,15 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
* pointers. So, this driver clears the AC64 bit of xhci->hcc_params
* to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in
* xhci_gen_setup().
*
* And, since the firmware/internal CPU control the USBSTS.STS_HALT
* and the process speed is down when the roothub port enters U3,
* long delay for the handshake of STS_HALT is neeed in xhci_suspend().
*/
if (xhci_rcar_is_gen2(hcd->self.controller) ||
xhci_rcar_is_gen3(hcd->self.controller))
xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
xhci_rcar_is_gen3(hcd->self.controller)) {
xhci->quirks |= XHCI_NO_64BIT_SUPPORT | XHCI_SLOW_SUSPEND;
}

if (!xhci_rcar_wait_for_pll_active(hcd))
return -ETIMEDOUT;
Expand Down
10 changes: 10 additions & 0 deletions drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -3089,8 +3089,18 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
return;
udev = (struct usb_device *) host_ep->hcpriv;
vdev = xhci->devs[udev->slot_id];

/*
* vdev may be lost due to xHC restore error and re-initialization
* during S3/S4 resume. A new vdev will be allocated later by
* xhci_discover_or_reset_device()
*/
if (!udev->slot_id || !vdev)
return;
ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = &vdev->eps[ep_index];
if (!ep)
return;

/* Bail out if toggle is already being cleared by a endpoint reset */
if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
Expand Down
7 changes: 4 additions & 3 deletions drivers/usb/misc/iowarrior.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,19 +866,20 @@ static void iowarrior_disconnect(struct usb_interface *interface)
dev = usb_get_intfdata(interface);
mutex_lock(&iowarrior_open_disc_lock);
usb_set_intfdata(interface, NULL);
/* prevent device read, write and ioctl */
dev->present = 0;

minor = dev->minor;
mutex_unlock(&iowarrior_open_disc_lock);
/* give back our minor - this will call close() locks need to be dropped at this point*/

/* give back our minor */
usb_deregister_dev(interface, &iowarrior_class);

mutex_lock(&dev->mutex);

/* prevent device read, write and ioctl */
dev->present = 0;

mutex_unlock(&dev->mutex);
mutex_unlock(&iowarrior_open_disc_lock);

if (dev->opened) {
/* There is a process that holds a filedescriptor to the device ,
Expand Down
Loading

0 comments on commit 1041f50

Please sign in to comment.