Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1041f509 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 97946f59 27709ae4
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -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)
+0 −123
Original line number Diff line number Diff line
@@ -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);
}

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

/*
@@ -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,
};



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

/**
@@ -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);
@@ -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;
+121 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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;
@@ -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;
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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)
+7 −2
Original line number Diff line number Diff line
@@ -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;
Loading