Commit c7b70a64 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-4.19-final' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

I wrote:
  "USB fixes for 4.19-final

   Here are a small number of last-minute USB driver fixes

   Included here are:
     - spectre fix for usb storage gadgets
     - xhci fixes
     - cdc-acm fixes
     - usbip fixes for reported problems

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

* tag 'usb-4.19-final' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: gadget: storage: Fix Spectre v1 vulnerability
  USB: fix the usbfs flag sanitization for control transfers
  usb: xhci: pci: Enable Intel USB role mux on Apollo Lake platforms
  usb: roles: intel_xhci: Fix Unbalanced pm_runtime_enable
  cdc-acm: correct counting of UART states in serial state notification
  cdc-acm: do not reset notification buffer index upon urb unlinking
  cdc-acm: fix race between reset and control messaging
  usb: usbip: Fix BUG: KASAN: slab-out-of-bounds in vhci_hub_control()
  selftests: usbip: add wait after attach and before checking port status
parents b2a205ff 9ae24af3
...@@ -310,17 +310,17 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf) ...@@ -310,17 +310,17 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
if (difference & ACM_CTRL_DSR) if (difference & ACM_CTRL_DSR)
acm->iocount.dsr++; acm->iocount.dsr++;
if (difference & ACM_CTRL_BRK)
acm->iocount.brk++;
if (difference & ACM_CTRL_RI)
acm->iocount.rng++;
if (difference & ACM_CTRL_DCD) if (difference & ACM_CTRL_DCD)
acm->iocount.dcd++; acm->iocount.dcd++;
if (difference & ACM_CTRL_FRAMING) if (newctrl & ACM_CTRL_BRK)
acm->iocount.brk++;
if (newctrl & ACM_CTRL_RI)
acm->iocount.rng++;
if (newctrl & ACM_CTRL_FRAMING)
acm->iocount.frame++; acm->iocount.frame++;
if (difference & ACM_CTRL_PARITY) if (newctrl & ACM_CTRL_PARITY)
acm->iocount.parity++; acm->iocount.parity++;
if (difference & ACM_CTRL_OVERRUN) if (newctrl & ACM_CTRL_OVERRUN)
acm->iocount.overrun++; acm->iocount.overrun++;
spin_unlock_irqrestore(&acm->read_lock, flags); spin_unlock_irqrestore(&acm->read_lock, flags);
...@@ -355,7 +355,6 @@ static void acm_ctrl_irq(struct urb *urb) ...@@ -355,7 +355,6 @@ static void acm_ctrl_irq(struct urb *urb)
case -ENOENT: case -ENOENT:
case -ESHUTDOWN: case -ESHUTDOWN:
/* this urb is terminated, clean up */ /* this urb is terminated, clean up */
acm->nb_index = 0;
dev_dbg(&acm->control->dev, dev_dbg(&acm->control->dev,
"%s - urb shutting down with status: %d\n", "%s - urb shutting down with status: %d\n",
__func__, status); __func__, status);
...@@ -1642,6 +1641,7 @@ static int acm_pre_reset(struct usb_interface *intf) ...@@ -1642,6 +1641,7 @@ static int acm_pre_reset(struct usb_interface *intf)
struct acm *acm = usb_get_intfdata(intf); struct acm *acm = usb_get_intfdata(intf);
clear_bit(EVENT_RX_STALL, &acm->flags); clear_bit(EVENT_RX_STALL, &acm->flags);
acm->nb_index = 0; /* pending control transfers are lost */
return 0; return 0;
} }
......
...@@ -1474,8 +1474,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb ...@@ -1474,8 +1474,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
u = 0; u = 0;
switch (uurb->type) { switch (uurb->type) {
case USBDEVFS_URB_TYPE_CONTROL: case USBDEVFS_URB_TYPE_CONTROL:
if (is_in)
allow_short = true;
if (!usb_endpoint_xfer_control(&ep->desc)) if (!usb_endpoint_xfer_control(&ep->desc))
return -EINVAL; return -EINVAL;
/* min 8 byte setup packet */ /* min 8 byte setup packet */
...@@ -1505,6 +1503,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb ...@@ -1505,6 +1503,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
is_in = 0; is_in = 0;
uurb->endpoint &= ~USB_DIR_IN; uurb->endpoint &= ~USB_DIR_IN;
} }
if (is_in)
allow_short = true;
snoop(&ps->dev->dev, "control urb: bRequestType=%02x " snoop(&ps->dev->dev, "control urb: bRequestType=%02x "
"bRequest=%02x wValue=%04x " "bRequest=%02x wValue=%04x "
"wIndex=%04x wLength=%04x\n", "wIndex=%04x wLength=%04x\n",
......
...@@ -221,6 +221,8 @@ ...@@ -221,6 +221,8 @@
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include <linux/nospec.h>
#include "configfs.h" #include "configfs.h"
...@@ -3152,6 +3154,7 @@ static struct config_group *fsg_lun_make(struct config_group *group, ...@@ -3152,6 +3154,7 @@ static struct config_group *fsg_lun_make(struct config_group *group,
fsg_opts = to_fsg_opts(&group->cg_item); fsg_opts = to_fsg_opts(&group->cg_item);
if (num >= FSG_MAX_LUNS) if (num >= FSG_MAX_LUNS)
return ERR_PTR(-ERANGE); return ERR_PTR(-ERANGE);
num = array_index_nospec(num, FSG_MAX_LUNS);
mutex_lock(&fsg_opts->lock); mutex_lock(&fsg_opts->lock);
if (fsg_opts->refcnt || fsg_opts->common->luns[num]) { if (fsg_opts->refcnt || fsg_opts->common->luns[num]) {
......
...@@ -179,10 +179,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -179,10 +179,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_PME_STUCK_QUIRK; xhci->quirks |= XHCI_PME_STUCK_QUIRK;
} }
if (pdev->vendor == PCI_VENDOR_ID_INTEL && if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)
xhci->quirks |= XHCI_SSIC_PORT_UNUSED; xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
xhci->quirks |= XHCI_INTEL_USB_ROLE_SW; xhci->quirks |= XHCI_INTEL_USB_ROLE_SW;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL && if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
......
...@@ -161,6 +161,8 @@ static int intel_xhci_usb_remove(struct platform_device *pdev) ...@@ -161,6 +161,8 @@ static int intel_xhci_usb_remove(struct platform_device *pdev)
{ {
struct intel_xhci_usb_data *data = platform_get_drvdata(pdev); struct intel_xhci_usb_data *data = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
usb_role_switch_unregister(data->role_sw); usb_role_switch_unregister(data->role_sw);
return 0; return 0;
} }
......
...@@ -318,8 +318,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -318,8 +318,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
struct vhci_hcd *vhci_hcd; struct vhci_hcd *vhci_hcd;
struct vhci *vhci; struct vhci *vhci;
int retval = 0; int retval = 0;
int rhport; int rhport = -1;
unsigned long flags; unsigned long flags;
bool invalid_rhport = false;
u32 prev_port_status[VHCI_HC_PORTS]; u32 prev_port_status[VHCI_HC_PORTS];
...@@ -334,8 +335,18 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -334,8 +335,18 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue, usbip_dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue,
wIndex); wIndex);
/*
* wIndex can be 0 for some request types (typeReq). rhport is
* in valid range when wIndex >= 1 and < VHCI_HC_PORTS.
*
* Reference port_status[] only with valid rhport when
* invalid_rhport is false.
*/
if (wIndex < 1 || wIndex > VHCI_HC_PORTS) {
invalid_rhport = true;
if (wIndex > VHCI_HC_PORTS) if (wIndex > VHCI_HC_PORTS)
pr_err("invalid port number %d\n", wIndex); pr_err("invalid port number %d\n", wIndex);
} else
rhport = wIndex - 1; rhport = wIndex - 1;
vhci_hcd = hcd_to_vhci_hcd(hcd); vhci_hcd = hcd_to_vhci_hcd(hcd);
...@@ -345,6 +356,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -345,6 +356,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* store old status and compare now and old later */ /* store old status and compare now and old later */
if (usbip_dbg_flag_vhci_rh) { if (usbip_dbg_flag_vhci_rh) {
if (!invalid_rhport)
memcpy(prev_port_status, vhci_hcd->port_status, memcpy(prev_port_status, vhci_hcd->port_status,
sizeof(prev_port_status)); sizeof(prev_port_status));
} }
...@@ -354,8 +366,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -354,8 +366,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh(" ClearHubFeature\n"); usbip_dbg_vhci_rh(" ClearHubFeature\n");
break; break;
case ClearPortFeature: case ClearPortFeature:
if (rhport < 0) if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex);
goto error; goto error;
}
switch (wValue) { switch (wValue) {
case USB_PORT_FEAT_SUSPEND: case USB_PORT_FEAT_SUSPEND:
if (hcd->speed == HCD_USB3) { if (hcd->speed == HCD_USB3) {
...@@ -415,9 +429,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -415,9 +429,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break; break;
case GetPortStatus: case GetPortStatus:
usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex); usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
if (wIndex < 1) { if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex); pr_err("invalid port number %d\n", wIndex);
retval = -EPIPE; retval = -EPIPE;
goto error;
} }
/* we do not care about resume. */ /* we do not care about resume. */
...@@ -513,16 +528,20 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -513,16 +528,20 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
goto error; goto error;
} }
if (rhport < 0) if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex);
goto error; goto error;
}
vhci_hcd->port_status[rhport] |= USB_PORT_STAT_SUSPEND; vhci_hcd->port_status[rhport] |= USB_PORT_STAT_SUSPEND;
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
usbip_dbg_vhci_rh( usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_POWER\n"); " SetPortFeature: USB_PORT_FEAT_POWER\n");
if (rhport < 0) if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex);
goto error; goto error;
}
if (hcd->speed == HCD_USB3) if (hcd->speed == HCD_USB3)
vhci_hcd->port_status[rhport] |= USB_SS_PORT_STAT_POWER; vhci_hcd->port_status[rhport] |= USB_SS_PORT_STAT_POWER;
else else
...@@ -531,8 +550,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -531,8 +550,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_BH_PORT_RESET: case USB_PORT_FEAT_BH_PORT_RESET:
usbip_dbg_vhci_rh( usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_BH_PORT_RESET\n"); " SetPortFeature: USB_PORT_FEAT_BH_PORT_RESET\n");
if (rhport < 0) if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex);
goto error; goto error;
}
/* Applicable only for USB3.0 hub */ /* Applicable only for USB3.0 hub */
if (hcd->speed != HCD_USB3) { if (hcd->speed != HCD_USB3) {
pr_err("USB_PORT_FEAT_BH_PORT_RESET req not " pr_err("USB_PORT_FEAT_BH_PORT_RESET req not "
...@@ -543,8 +564,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -543,8 +564,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_RESET: case USB_PORT_FEAT_RESET:
usbip_dbg_vhci_rh( usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_RESET\n"); " SetPortFeature: USB_PORT_FEAT_RESET\n");
if (rhport < 0) if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex);
goto error; goto error;
}
/* if it's already enabled, disable */ /* if it's already enabled, disable */
if (hcd->speed == HCD_USB3) { if (hcd->speed == HCD_USB3) {
vhci_hcd->port_status[rhport] = 0; vhci_hcd->port_status[rhport] = 0;
...@@ -565,8 +588,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -565,8 +588,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
default: default:
usbip_dbg_vhci_rh(" SetPortFeature: default %d\n", usbip_dbg_vhci_rh(" SetPortFeature: default %d\n",
wValue); wValue);
if (rhport < 0) if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex);
goto error; goto error;
}
if (hcd->speed == HCD_USB3) { if (hcd->speed == HCD_USB3) {
if ((vhci_hcd->port_status[rhport] & if ((vhci_hcd->port_status[rhport] &
USB_SS_PORT_STAT_POWER) != 0) { USB_SS_PORT_STAT_POWER) != 0) {
...@@ -608,7 +633,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -608,7 +633,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (usbip_dbg_flag_vhci_rh) { if (usbip_dbg_flag_vhci_rh) {
pr_debug("port %d\n", rhport); pr_debug("port %d\n", rhport);
/* Only dump valid port status */ /* Only dump valid port status */
if (rhport >= 0) { if (!invalid_rhport) {
dump_port_status_diff(prev_port_status[rhport], dump_port_status_diff(prev_port_status[rhport],
vhci_hcd->port_status[rhport], vhci_hcd->port_status[rhport],
hcd->speed == HCD_USB3); hcd->speed == HCD_USB3);
...@@ -618,8 +643,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -618,8 +643,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
spin_unlock_irqrestore(&vhci->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);
if ((vhci_hcd->port_status[rhport] & PORT_C_MASK) != 0) if (!invalid_rhport &&
(vhci_hcd->port_status[rhport] & PORT_C_MASK) != 0) {
usb_hcd_poll_rh_status(hcd); usb_hcd_poll_rh_status(hcd);
}
return retval; return retval;
} }
......
...@@ -141,6 +141,10 @@ echo "Import devices from localhost - should work" ...@@ -141,6 +141,10 @@ echo "Import devices from localhost - should work"
src/usbip attach -r localhost -b $busid; src/usbip attach -r localhost -b $busid;
echo "==============================================================" echo "=============================================================="
# Wait for sysfs file to be updated. Without this sleep, usbip port
# shows no imported devices.
sleep 3;
echo "List imported devices - expect to see imported devices"; echo "List imported devices - expect to see imported devices";
src/usbip port; src/usbip port;
echo "==============================================================" echo "=============================================================="
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment