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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCW8oNdg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ym5xgCfQ55kmFLnpRKNvLG+ihYAoJ7OPOoAoKiXhWTF GhtlV7Qu4s6JkLBEIN2n =241b -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
c7b70a641d
|
@ -310,17 +310,17 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
|
|||
|
||||
if (difference & ACM_CTRL_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)
|
||||
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++;
|
||||
if (difference & ACM_CTRL_PARITY)
|
||||
if (newctrl & ACM_CTRL_PARITY)
|
||||
acm->iocount.parity++;
|
||||
if (difference & ACM_CTRL_OVERRUN)
|
||||
if (newctrl & ACM_CTRL_OVERRUN)
|
||||
acm->iocount.overrun++;
|
||||
spin_unlock_irqrestore(&acm->read_lock, flags);
|
||||
|
||||
|
@ -355,7 +355,6 @@ static void acm_ctrl_irq(struct urb *urb)
|
|||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
/* this urb is terminated, clean up */
|
||||
acm->nb_index = 0;
|
||||
dev_dbg(&acm->control->dev,
|
||||
"%s - urb shutting down with status: %d\n",
|
||||
__func__, status);
|
||||
|
@ -1642,6 +1641,7 @@ static int acm_pre_reset(struct usb_interface *intf)
|
|||
struct acm *acm = usb_get_intfdata(intf);
|
||||
|
||||
clear_bit(EVENT_RX_STALL, &acm->flags);
|
||||
acm->nb_index = 0; /* pending control transfers are lost */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1474,8 +1474,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
|
|||
u = 0;
|
||||
switch (uurb->type) {
|
||||
case USBDEVFS_URB_TYPE_CONTROL:
|
||||
if (is_in)
|
||||
allow_short = true;
|
||||
if (!usb_endpoint_xfer_control(&ep->desc))
|
||||
return -EINVAL;
|
||||
/* min 8 byte setup packet */
|
||||
|
@ -1505,6 +1503,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
|
|||
is_in = 0;
|
||||
uurb->endpoint &= ~USB_DIR_IN;
|
||||
}
|
||||
if (is_in)
|
||||
allow_short = true;
|
||||
snoop(&ps->dev->dev, "control urb: bRequestType=%02x "
|
||||
"bRequest=%02x wValue=%04x "
|
||||
"wIndex=%04x wLength=%04x\n",
|
||||
|
|
|
@ -221,6 +221,8 @@
|
|||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
#include <linux/nospec.h>
|
||||
|
||||
#include "configfs.h"
|
||||
|
||||
|
||||
|
@ -3152,6 +3154,7 @@ static struct config_group *fsg_lun_make(struct config_group *group,
|
|||
fsg_opts = to_fsg_opts(&group->cg_item);
|
||||
if (num >= FSG_MAX_LUNS)
|
||||
return ERR_PTR(-ERANGE);
|
||||
num = array_index_nospec(num, FSG_MAX_LUNS);
|
||||
|
||||
mutex_lock(&fsg_opts->lock);
|
||||
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)
|
|||
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
||||
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
|
||||
|
|
|
@ -161,6 +161,8 @@ static int intel_xhci_usb_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct intel_xhci_usb_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
usb_role_switch_unregister(data->role_sw);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -318,8 +318,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
struct vhci_hcd *vhci_hcd;
|
||||
struct vhci *vhci;
|
||||
int retval = 0;
|
||||
int rhport;
|
||||
int rhport = -1;
|
||||
unsigned long flags;
|
||||
bool invalid_rhport = false;
|
||||
|
||||
u32 prev_port_status[VHCI_HC_PORTS];
|
||||
|
||||
|
@ -334,9 +335,19 @@ 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,
|
||||
wIndex);
|
||||
|
||||
if (wIndex > VHCI_HC_PORTS)
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
rhport = wIndex - 1;
|
||||
/*
|
||||
* 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)
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
} else
|
||||
rhport = wIndex - 1;
|
||||
|
||||
vhci_hcd = hcd_to_vhci_hcd(hcd);
|
||||
vhci = vhci_hcd->vhci;
|
||||
|
@ -345,8 +356,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
|
||||
/* store old status and compare now and old later */
|
||||
if (usbip_dbg_flag_vhci_rh) {
|
||||
memcpy(prev_port_status, vhci_hcd->port_status,
|
||||
sizeof(prev_port_status));
|
||||
if (!invalid_rhport)
|
||||
memcpy(prev_port_status, vhci_hcd->port_status,
|
||||
sizeof(prev_port_status));
|
||||
}
|
||||
|
||||
switch (typeReq) {
|
||||
|
@ -354,8 +366,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
usbip_dbg_vhci_rh(" ClearHubFeature\n");
|
||||
break;
|
||||
case ClearPortFeature:
|
||||
if (rhport < 0)
|
||||
if (invalid_rhport) {
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
goto error;
|
||||
}
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
|
@ -415,9 +429,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
break;
|
||||
case GetPortStatus:
|
||||
usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
|
||||
if (wIndex < 1) {
|
||||
if (invalid_rhport) {
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
retval = -EPIPE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* we do not care about resume. */
|
||||
|
@ -513,16 +528,20 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (rhport < 0)
|
||||
if (invalid_rhport) {
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
goto error;
|
||||
}
|
||||
|
||||
vhci_hcd->port_status[rhport] |= USB_PORT_STAT_SUSPEND;
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
usbip_dbg_vhci_rh(
|
||||
" SetPortFeature: USB_PORT_FEAT_POWER\n");
|
||||
if (rhport < 0)
|
||||
if (invalid_rhport) {
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
goto error;
|
||||
}
|
||||
if (hcd->speed == HCD_USB3)
|
||||
vhci_hcd->port_status[rhport] |= USB_SS_PORT_STAT_POWER;
|
||||
else
|
||||
|
@ -531,8 +550,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
case USB_PORT_FEAT_BH_PORT_RESET:
|
||||
usbip_dbg_vhci_rh(
|
||||
" SetPortFeature: USB_PORT_FEAT_BH_PORT_RESET\n");
|
||||
if (rhport < 0)
|
||||
if (invalid_rhport) {
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
goto error;
|
||||
}
|
||||
/* Applicable only for USB3.0 hub */
|
||||
if (hcd->speed != HCD_USB3) {
|
||||
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,
|
|||
case USB_PORT_FEAT_RESET:
|
||||
usbip_dbg_vhci_rh(
|
||||
" SetPortFeature: USB_PORT_FEAT_RESET\n");
|
||||
if (rhport < 0)
|
||||
if (invalid_rhport) {
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
goto error;
|
||||
}
|
||||
/* if it's already enabled, disable */
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
vhci_hcd->port_status[rhport] = 0;
|
||||
|
@ -565,8 +588,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
default:
|
||||
usbip_dbg_vhci_rh(" SetPortFeature: default %d\n",
|
||||
wValue);
|
||||
if (rhport < 0)
|
||||
if (invalid_rhport) {
|
||||
pr_err("invalid port number %d\n", wIndex);
|
||||
goto error;
|
||||
}
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
if ((vhci_hcd->port_status[rhport] &
|
||||
USB_SS_PORT_STAT_POWER) != 0) {
|
||||
|
@ -608,7 +633,7 @@ error:
|
|||
if (usbip_dbg_flag_vhci_rh) {
|
||||
pr_debug("port %d\n", rhport);
|
||||
/* Only dump valid port status */
|
||||
if (rhport >= 0) {
|
||||
if (!invalid_rhport) {
|
||||
dump_port_status_diff(prev_port_status[rhport],
|
||||
vhci_hcd->port_status[rhport],
|
||||
hcd->speed == HCD_USB3);
|
||||
|
@ -618,8 +643,10 @@ error:
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -141,6 +141,10 @@ echo "Import devices from localhost - should work"
|
|||
src/usbip attach -r localhost -b $busid;
|
||||
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";
|
||||
src/usbip port;
|
||||
echo "=============================================================="
|
||||
|
|
Loading…
Reference in New Issue