Commit c36c7a7c authored by Linus Torvalds's avatar Linus Torvalds

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

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

  There is the usual handful gadget/dwc2/dwc3 fixes as always, for
  reported issues. But the most important things in here is the core fix
  from Alan Stern to resolve a nasty security bug (my first attempt is
  reverted, Alan's was much cleaner), as well as a number of usbip fixes
  from Shuah Khan to resolve those reported security issues.

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

* tag 'usb-4.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: core: prevent malicious bNumInterfaces overflow
  Revert "USB: core: only clean up what we allocated"
  USB: core: only clean up what we allocated
  Revert "usb: gadget: allow to enable legacy drivers without USB_ETH"
  usb: gadget: webcam: fix V4L2 Kconfig dependency
  usb: dwc2: Fix TxFIFOn sizes and total TxFIFO size issues
  usb: dwc3: gadget: Fix PCM1 for ISOC EP with ep->mult less than 3
  usb: dwc3: of-simple: set dev_pm_ops
  usb: dwc3: of-simple: fix missing clk_disable_unprepare
  usb: dwc3: gadget: Wait longer for controller to end command processing
  usb: xhci: fix TDS for MTK xHCI1.1
  xhci: Don't add a virt_dev to the devs array before it's fully allocated
  usbip: fix stub_send_ret_submit() vulnerability to null transfer_buffer
  usbip: prevent vhci_hcd driver from leaking a socket pointer address
  usbip: fix stub_rx: harden CMD_SUBMIT path to handle malicious input
  usbip: fix stub_rx: get_pipe() to validate endpoint number
  tools/usbip: fixes potential (minor) "buffer overflow" (detected on recent gcc with -Werror)
  USB: uas and storage: Add US_FL_BROKEN_FUA for another JMicron JMS567 ID
  usb: musb: da8xx: fix babble condition handling
parents a84ec723 48a4ff1c
...@@ -555,6 +555,9 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, ...@@ -555,6 +555,9 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
unsigned iad_num = 0; unsigned iad_num = 0;
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
nintf = nintf_orig = config->desc.bNumInterfaces;
config->desc.bNumInterfaces = 0; // Adjusted later
if (config->desc.bDescriptorType != USB_DT_CONFIG || if (config->desc.bDescriptorType != USB_DT_CONFIG ||
config->desc.bLength < USB_DT_CONFIG_SIZE || config->desc.bLength < USB_DT_CONFIG_SIZE ||
config->desc.bLength > size) { config->desc.bLength > size) {
...@@ -568,7 +571,6 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, ...@@ -568,7 +571,6 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
buffer += config->desc.bLength; buffer += config->desc.bLength;
size -= config->desc.bLength; size -= config->desc.bLength;
nintf = nintf_orig = config->desc.bNumInterfaces;
if (nintf > USB_MAXINTERFACES) { if (nintf > USB_MAXINTERFACES) {
dev_warn(ddev, "config %d has too many interfaces: %d, " dev_warn(ddev, "config %d has too many interfaces: %d, "
"using maximum allowed: %d\n", "using maximum allowed: %d\n",
......
...@@ -537,6 +537,7 @@ struct dwc2_core_params { ...@@ -537,6 +537,7 @@ struct dwc2_core_params {
* 2 - Internal DMA * 2 - Internal DMA
* @power_optimized Are power optimizations enabled? * @power_optimized Are power optimizations enabled?
* @num_dev_ep Number of device endpoints available * @num_dev_ep Number of device endpoints available
* @num_dev_in_eps Number of device IN endpoints available
* @num_dev_perio_in_ep Number of device periodic IN endpoints * @num_dev_perio_in_ep Number of device periodic IN endpoints
* available * available
* @dev_token_q_depth Device Mode IN Token Sequence Learning Queue * @dev_token_q_depth Device Mode IN Token Sequence Learning Queue
...@@ -565,6 +566,7 @@ struct dwc2_core_params { ...@@ -565,6 +566,7 @@ struct dwc2_core_params {
* 2 - 8 or 16 bits * 2 - 8 or 16 bits
* @snpsid: Value from SNPSID register * @snpsid: Value from SNPSID register
* @dev_ep_dirs: Direction of device endpoints (GHWCFG1) * @dev_ep_dirs: Direction of device endpoints (GHWCFG1)
* @g_tx_fifo_size[] Power-on values of TxFIFO sizes
*/ */
struct dwc2_hw_params { struct dwc2_hw_params {
unsigned op_mode:3; unsigned op_mode:3;
...@@ -586,12 +588,14 @@ struct dwc2_hw_params { ...@@ -586,12 +588,14 @@ struct dwc2_hw_params {
unsigned fs_phy_type:2; unsigned fs_phy_type:2;
unsigned i2c_enable:1; unsigned i2c_enable:1;
unsigned num_dev_ep:4; unsigned num_dev_ep:4;
unsigned num_dev_in_eps : 4;
unsigned num_dev_perio_in_ep:4; unsigned num_dev_perio_in_ep:4;
unsigned total_fifo_size:16; unsigned total_fifo_size:16;
unsigned power_optimized:1; unsigned power_optimized:1;
unsigned utmi_phy_data_width:2; unsigned utmi_phy_data_width:2;
u32 snpsid; u32 snpsid;
u32 dev_ep_dirs; u32 dev_ep_dirs;
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
}; };
/* Size of control and EP0 buffers */ /* Size of control and EP0 buffers */
......
...@@ -195,55 +195,18 @@ int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) ...@@ -195,55 +195,18 @@ int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
{ {
if (hsotg->hw_params.en_multiple_tx_fifo) if (hsotg->hw_params.en_multiple_tx_fifo)
/* In dedicated FIFO mode we need count of IN EPs */ /* In dedicated FIFO mode we need count of IN EPs */
return (dwc2_readl(hsotg->regs + GHWCFG4) & return hsotg->hw_params.num_dev_in_eps;
GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT;
else else
/* In shared FIFO mode we need count of Periodic IN EPs */ /* In shared FIFO mode we need count of Periodic IN EPs */
return hsotg->hw_params.num_dev_perio_in_ep; return hsotg->hw_params.num_dev_perio_in_ep;
} }
/**
* dwc2_hsotg_ep_info_size - return Endpoint Info Control block size in DWORDs
*/
static int dwc2_hsotg_ep_info_size(struct dwc2_hsotg *hsotg)
{
int val = 0;
int i;
u32 ep_dirs;
/*
* Don't need additional space for ep info control registers in
* slave mode.
*/
if (!using_dma(hsotg)) {
dev_dbg(hsotg->dev, "Buffer DMA ep info size 0\n");
return 0;
}
/*
* Buffer DMA mode - 1 location per endpoit
* Descriptor DMA mode - 4 locations per endpoint
*/
ep_dirs = hsotg->hw_params.dev_ep_dirs;
for (i = 0; i <= hsotg->hw_params.num_dev_ep; i++) {
val += ep_dirs & 3 ? 1 : 2;
ep_dirs >>= 2;
}
if (using_desc_dma(hsotg))
val = val * 4;
return val;
}
/** /**
* dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for * dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for
* device mode TX FIFOs * device mode TX FIFOs
*/ */
int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
{ {
int ep_info_size;
int addr; int addr;
int tx_addr_max; int tx_addr_max;
u32 np_tx_fifo_size; u32 np_tx_fifo_size;
...@@ -252,8 +215,7 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) ...@@ -252,8 +215,7 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
hsotg->params.g_np_tx_fifo_size); hsotg->params.g_np_tx_fifo_size);
/* Get Endpoint Info Control block size in DWORDs. */ /* Get Endpoint Info Control block size in DWORDs. */
ep_info_size = dwc2_hsotg_ep_info_size(hsotg); tx_addr_max = hsotg->hw_params.total_fifo_size;
tx_addr_max = hsotg->hw_params.total_fifo_size - ep_info_size;
addr = hsotg->params.g_rx_fifo_size + np_tx_fifo_size; addr = hsotg->params.g_rx_fifo_size + np_tx_fifo_size;
if (tx_addr_max <= addr) if (tx_addr_max <= addr)
......
...@@ -484,8 +484,7 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) ...@@ -484,8 +484,7 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
} }
for (fifo = 1; fifo <= fifo_count; fifo++) { for (fifo = 1; fifo <= fifo_count; fifo++) {
dptxfszn = (dwc2_readl(hsotg->regs + DPTXFSIZN(fifo)) & dptxfszn = hsotg->hw_params.g_tx_fifo_size[fifo];
FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT;
if (hsotg->params.g_tx_fifo_size[fifo] < min || if (hsotg->params.g_tx_fifo_size[fifo] < min ||
hsotg->params.g_tx_fifo_size[fifo] > dptxfszn) { hsotg->params.g_tx_fifo_size[fifo] > dptxfszn) {
...@@ -609,6 +608,7 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) ...@@ -609,6 +608,7 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
struct dwc2_hw_params *hw = &hsotg->hw_params; struct dwc2_hw_params *hw = &hsotg->hw_params;
bool forced; bool forced;
u32 gnptxfsiz; u32 gnptxfsiz;
int fifo, fifo_count;
if (hsotg->dr_mode == USB_DR_MODE_HOST) if (hsotg->dr_mode == USB_DR_MODE_HOST)
return; return;
...@@ -617,6 +617,14 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) ...@@ -617,6 +617,14 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
fifo_count = dwc2_hsotg_tx_fifo_count(hsotg);
for (fifo = 1; fifo <= fifo_count; fifo++) {
hw->g_tx_fifo_size[fifo] =
(dwc2_readl(hsotg->regs + DPTXFSIZN(fifo)) &
FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT;
}
if (forced) if (forced)
dwc2_clear_force_mode(hsotg); dwc2_clear_force_mode(hsotg);
...@@ -661,14 +669,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) ...@@ -661,14 +669,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4); hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ); grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
/*
* Host specific hardware parameters. Reading these parameters
* requires the controller to be in host mode. The mode will
* be forced, if necessary, to read these values.
*/
dwc2_get_host_hwparams(hsotg);
dwc2_get_dev_hwparams(hsotg);
/* hwcfg1 */ /* hwcfg1 */
hw->dev_ep_dirs = hwcfg1; hw->dev_ep_dirs = hwcfg1;
...@@ -711,6 +711,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) ...@@ -711,6 +711,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN); hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >> hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >>
GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT; GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT;
hw->num_dev_in_eps = (hwcfg4 & GHWCFG4_NUM_IN_EPS_MASK) >>
GHWCFG4_NUM_IN_EPS_SHIFT;
hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA); hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA);
hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ); hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >> hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >>
...@@ -719,6 +721,13 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) ...@@ -719,6 +721,13 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
/* fifo sizes */ /* fifo sizes */
hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
GRXFSIZ_DEPTH_SHIFT; GRXFSIZ_DEPTH_SHIFT;
/*
* Host specific hardware parameters. Reading these parameters
* requires the controller to be in host mode. The mode will
* be forced, if necessary, to read these values.
*/
dwc2_get_host_hwparams(hsotg);
dwc2_get_dev_hwparams(hsotg);
return 0; return 0;
} }
......
...@@ -51,8 +51,10 @@ static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count) ...@@ -51,8 +51,10 @@ static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
clk = of_clk_get(np, i); clk = of_clk_get(np, i);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
while (--i >= 0) while (--i >= 0) {
clk_disable_unprepare(simple->clks[i]);
clk_put(simple->clks[i]); clk_put(simple->clks[i]);
}
return PTR_ERR(clk); return PTR_ERR(clk);
} }
...@@ -203,6 +205,7 @@ static struct platform_driver dwc3_of_simple_driver = { ...@@ -203,6 +205,7 @@ static struct platform_driver dwc3_of_simple_driver = {
.driver = { .driver = {
.name = "dwc3-of-simple", .name = "dwc3-of-simple",
.of_match_table = of_dwc3_simple_match, .of_match_table = of_dwc3_simple_match,
.pm = &dwc3_of_simple_dev_pm_ops,
}, },
}; };
......
...@@ -259,7 +259,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, ...@@ -259,7 +259,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
{ {
const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; const struct usb_endpoint_descriptor *desc = dep->endpoint.desc;
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
u32 timeout = 500; u32 timeout = 1000;
u32 reg; u32 reg;
int cmd_status = 0; int cmd_status = 0;
...@@ -912,7 +912,7 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, ...@@ -912,7 +912,7 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
*/ */
if (speed == USB_SPEED_HIGH) { if (speed == USB_SPEED_HIGH) {
struct usb_ep *ep = &dep->endpoint; struct usb_ep *ep = &dep->endpoint;
unsigned int mult = ep->mult - 1; unsigned int mult = 2;
unsigned int maxp = usb_endpoint_maxp(ep->desc); unsigned int maxp = usb_endpoint_maxp(ep->desc);
if (length <= (2 * maxp)) if (length <= (2 * maxp))
......
...@@ -508,8 +508,8 @@ choice ...@@ -508,8 +508,8 @@ choice
controller, and the relevant drivers for each function declared controller, and the relevant drivers for each function declared
by the device. by the device.
endchoice
source "drivers/usb/gadget/legacy/Kconfig" source "drivers/usb/gadget/legacy/Kconfig"
endchoice
endif # USB_GADGET endif # USB_GADGET
...@@ -13,14 +13,6 @@ ...@@ -13,14 +13,6 @@
# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG). # both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
# #
menuconfig USB_GADGET_LEGACY
bool "Legacy USB Gadget Support"
help
Legacy USB gadgets are USB gadgets that do not use the USB gadget
configfs interface.
if USB_GADGET_LEGACY
config USB_ZERO config USB_ZERO
tristate "Gadget Zero (DEVELOPMENT)" tristate "Gadget Zero (DEVELOPMENT)"
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
...@@ -487,7 +479,7 @@ endif ...@@ -487,7 +479,7 @@ endif
# or video class gadget drivers), or specific hardware, here. # or video class gadget drivers), or specific hardware, here.
config USB_G_WEBCAM config USB_G_WEBCAM
tristate "USB Webcam Gadget" tristate "USB Webcam Gadget"
depends on VIDEO_DEV depends on VIDEO_V4L2
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
select VIDEOBUF2_VMALLOC select VIDEOBUF2_VMALLOC
select USB_F_UVC select USB_F_UVC
...@@ -498,5 +490,3 @@ config USB_G_WEBCAM ...@@ -498,5 +490,3 @@ config USB_G_WEBCAM
Say "y" to link the driver statically, or "m" to build a Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_webcam". dynamically linked module called "g_webcam".
endif
...@@ -971,10 +971,9 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, ...@@ -971,10 +971,9 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
return 0; return 0;
} }
xhci->devs[slot_id] = kzalloc(sizeof(*xhci->devs[slot_id]), flags); dev = kzalloc(sizeof(*dev), flags);
if (!xhci->devs[slot_id]) if (!dev)
return 0; return 0;
dev = xhci->devs[slot_id];
/* Allocate the (output) device context that will be used in the HC. */ /* Allocate the (output) device context that will be used in the HC. */
dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags); dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags);
...@@ -1015,9 +1014,17 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, ...@@ -1015,9 +1014,17 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
trace_xhci_alloc_virt_device(dev); trace_xhci_alloc_virt_device(dev);
xhci->devs[slot_id] = dev;
return 1; return 1;
fail: fail:
xhci_free_virt_device(xhci, slot_id);
if (dev->in_ctx)
xhci_free_container_ctx(xhci, dev->in_ctx);
if (dev->out_ctx)
xhci_free_container_ctx(xhci, dev->out_ctx);
kfree(dev);
return 0; return 0;
} }
......
...@@ -3112,7 +3112,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, ...@@ -3112,7 +3112,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
{ {
u32 maxp, total_packet_count; u32 maxp, total_packet_count;
/* MTK xHCI is mostly 0.97 but contains some features from 1.0 */ /* MTK xHCI 0.96 contains some features from 1.0 */
if (xhci->hci_version < 0x100 && !(xhci->quirks & XHCI_MTK_HOST)) if (xhci->hci_version < 0x100 && !(xhci->quirks & XHCI_MTK_HOST))
return ((td_total_len - transferred) >> 10); return ((td_total_len - transferred) >> 10);
...@@ -3121,8 +3121,8 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, ...@@ -3121,8 +3121,8 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
trb_buff_len == td_total_len) trb_buff_len == td_total_len)
return 0; return 0;
/* for MTK xHCI, TD size doesn't include this TRB */ /* for MTK xHCI 0.96, TD size include this TRB, but not in 1.x */
if (xhci->quirks & XHCI_MTK_HOST) if ((xhci->quirks & XHCI_MTK_HOST) && (xhci->hci_version < 0x100))
trb_buff_len = 0; trb_buff_len = 0;
maxp = usb_endpoint_maxp(&urb->ep->desc); maxp = usb_endpoint_maxp(&urb->ep->desc);
......
...@@ -284,7 +284,15 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) ...@@ -284,7 +284,15 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
portstate(musb->port1_status |= USB_PORT_STAT_POWER); portstate(musb->port1_status |= USB_PORT_STAT_POWER);
del_timer(&musb->dev_timer); del_timer(&musb->dev_timer);
} else { } else if (!(musb->int_usb & MUSB_INTR_BABBLE)) {
/*
* When babble condition happens, drvvbus interrupt
* is also generated. Ignore this drvvbus interrupt
* and let babble interrupt handler recovers the
* controller; otherwise, the host-mode flag is lost
* due to the MUSB_DEV_MODE() call below and babble
* recovery logic will not be called.
*/
musb->is_active = 0; musb->is_active = 0;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
otg->default_a = 0; otg->default_a = 0;
......
...@@ -2100,6 +2100,13 @@ UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0116, ...@@ -2100,6 +2100,13 @@ UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0116,
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BROKEN_FUA ), US_FL_BROKEN_FUA ),
/* Reported by David Kozub <zub@linux.fjfi.cvut.cz> */
UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999,
"JMicron",
"JMS567",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BROKEN_FUA),
/* /*
* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br> * Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
* JMicron responds to USN and several other SCSI ioctls with a * JMicron responds to USN and several other SCSI ioctls with a
......
...@@ -129,6 +129,13 @@ UNUSUAL_DEV(0x152d, 0x0567, 0x0000, 0x9999, ...@@ -129,6 +129,13 @@ UNUSUAL_DEV(0x152d, 0x0567, 0x0000, 0x9999,
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BROKEN_FUA | US_FL_NO_REPORT_OPCODES), US_FL_BROKEN_FUA | US_FL_NO_REPORT_OPCODES),
/* Reported-by: David Kozub <zub@linux.fjfi.cvut.cz> */
UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999,
"JMicron",
"JMS567",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BROKEN_FUA),
/* Reported-by: Hans de Goede <hdegoede@redhat.com> */ /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999, UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999,
"VIA", "VIA",
......
...@@ -322,23 +322,34 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, ...@@ -322,23 +322,34 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
return priv; return priv;
} }
static int get_pipe(struct stub_device *sdev, int epnum, int dir) static int get_pipe(struct stub_device *sdev, struct usbip_header *pdu)
{ {
struct usb_device *udev = sdev->udev; struct usb_device *udev = sdev->udev;
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep;
struct usb_endpoint_descriptor *epd = NULL; struct usb_endpoint_descriptor *epd = NULL;
int epnum = pdu->base.ep;
int dir = pdu->base.direction;
if (epnum < 0 || epnum > 15)
goto err_ret;
if (dir == USBIP_DIR_IN) if (dir == USBIP_DIR_IN)
ep = udev->ep_in[epnum & 0x7f]; ep = udev->ep_in[epnum & 0x7f];
else else
ep = udev->ep_out[epnum & 0x7f]; ep = udev->ep_out[epnum & 0x7f];
if (!ep) { if (!ep)
dev_err(&sdev->udev->dev, "no such endpoint?, %d\n", goto err_ret;
epnum);
BUG();
}
epd = &ep->desc; epd = &ep->desc;
/* validate transfer_buffer_length */
if (pdu->u.cmd_submit.transfer_buffer_length > INT_MAX) {
dev_err(&sdev->udev->dev,
"CMD_SUBMIT: -EMSGSIZE transfer_buffer_length %d\n",
pdu->u.cmd_submit.transfer_buffer_length);
return -1;
}
if (usb_endpoint_xfer_control(epd)) { if (usb_endpoint_xfer_control(epd)) {
if (dir == USBIP_DIR_OUT) if (dir == USBIP_DIR_OUT)
return usb_sndctrlpipe(udev, epnum); return usb_sndctrlpipe(udev, epnum);
...@@ -361,15 +372,31 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) ...@@ -361,15 +372,31 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir)
} }
if (usb_endpoint_xfer_isoc(epd)) { if (usb_endpoint_xfer_isoc(epd)) {
/* validate packet size and number of packets */
unsigned int maxp, packets, bytes;
maxp = usb_endpoint_maxp(epd);
maxp *= usb_endpoint_maxp_mult(epd);
bytes = pdu->u.cmd_submit.transfer_buffer_length;
packets = DIV_ROUND_UP(bytes, maxp);
if (pdu->u.cmd_submit.number_of_packets < 0 ||
pdu->u.cmd_submit.number_of_packets > packets) {
dev_err(&sdev->udev->dev,
"CMD_SUBMIT: isoc invalid num packets %d\n",
pdu->u.cmd_submit.number_of_packets);
return -1;
}
if (dir == USBIP_DIR_OUT) if (dir == USBIP_DIR_OUT)
return usb_sndisocpipe(udev, epnum); return usb_sndisocpipe(udev, epnum);
else else
return usb_rcvisocpipe(udev, epnum); return usb_rcvisocpipe(udev, epnum);
} }
err_ret:
/* NOT REACHED */ /* NOT REACHED */
dev_err(&sdev->udev->dev, "get pipe, epnum %d\n", epnum); dev_err(&sdev->udev->dev, "CMD_SUBMIT: invalid epnum %d\n", epnum);
return 0; return -1;
} }
static void masking_bogus_flags(struct urb *urb) static void masking_bogus_flags(struct urb *urb)
...@@ -433,7 +460,10 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, ...@@ -433,7 +460,10 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
struct stub_priv *priv; struct stub_priv *priv;
struct usbip_device *ud = &sdev->ud; struct usbip_device *ud = &sdev->ud;
struct usb_device *udev = sdev->udev; struct usb_device *udev = sdev->udev;
int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); int pipe = get_pipe(sdev, pdu);
if (pipe == -1)
return;
priv = stub_priv_alloc(sdev, pdu); priv = stub_priv_alloc(sdev, pdu);
if (!priv) if (!priv)
...@@ -452,7 +482,8 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, ...@@ -452,7 +482,8 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
} }
/* allocate urb transfer buffer, if needed */ /* allocate urb transfer buffer, if needed */
if (pdu->u.cmd_submit.transfer_buffer_length > 0) { if (pdu->u.cmd_submit.transfer_buffer_length > 0 &&
pdu->u.cmd_submit.transfer_buffer_length <= INT_MAX) {
priv->urb->transfer_buffer = priv->urb->transfer_buffer =
kzalloc(pdu->u.cmd_submit.transfer_buffer_length, kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
GFP_KERNEL); GFP_KERNEL);
......
...@@ -167,6 +167,13 @@ static int stub_send_ret_submit(struct stub_device *sdev) ...@@ -167,6 +167,13 @@ static int stub_send_ret_submit(struct stub_device *sdev)
memset(&pdu_header, 0, sizeof(pdu_header)); memset(&pdu_header, 0, sizeof(pdu_header));
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
if (urb->actual_length > 0 && !urb->transfer_buffer) {
dev_err(&sdev->udev->dev,
"urb: actual_length %d transfer_buffer null\n",
urb->actual_length);
return -1;
}
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
iovnum = 2 + urb->number_of_packets; iovnum = 2 + urb->number_of_packets;
else else
......
...@@ -256,6 +256,7 @@ struct usbip_device { ...@@ -256,6 +256,7 @@ struct usbip_device {
/* lock for status */ /* lock for status */
spinlock_t lock; spinlock_t lock;
int sockfd;
struct socket *tcp_socket; struct socket *tcp_socket;
struct task_struct *tcp_rx; struct task_struct *tcp_rx;
......
...@@ -17,15 +17,20 @@ ...@@ -17,15 +17,20 @@
/* /*
* output example: * output example:
* hub port sta spd dev socket local_busid * hub port sta spd dev sockfd local_busid
* hs 0000 004 000 00000000 c5a7bb80 1-2.3 * hs 0000 004 000 00000000 3 1-2.3
* ................................................ * ................................................
* ss 0008 004 000 00000000 d8cee980 2-3.4 * ss 0008 004 000 00000000 4 2-3.4
* ................................................ * ................................................
* *
* IP address can be retrieved from a socket pointer address by looking * Output includes socket fd instead of socket pointer address to avoid
* up /proc/net/{tcp,tcp6}. Also, a userland program may remember a * leaking kernel memory address in:
* port number and its peer IP address. * /sys/devices/platform/vhci_hcd.0/status and in debug output.
* The socket pointer address is not used at the moment and it was made
* visible as a convenient way to find IP address from socket pointer
* address by looking up /proc/net/{tcp,tcp6}. As this opens a security
* hole, the change is made to use sockfd instead.
*
*/ */
static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vdev) static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vdev)
{ {
...@@ -39,8 +44,8 @@ static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vd ...@@ -39,8 +44,8 @@ static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vd
if (vdev->ud.status == VDEV_ST_USED) { if (vdev->ud.status == VDEV_ST_USED) {
*out += sprintf(*out, "%03u %08x ", *out += sprintf(*out, "%03u %08x ",
vdev->speed, vdev->devid); vdev->speed, vdev->devid);
*out += sprintf(*out, "%16p %s", *out += sprintf(*out, "%u %s",
vdev->ud.tcp_socket, vdev->ud.sockfd,
dev_name(&vdev->udev->dev)); dev_name(&vdev->udev->dev));
} else { } else {
...@@ -160,7 +165,8 @@ static ssize_t nports_show(struct device *dev, struct device_attribute *attr, ...@@ -160,7 +165,8 @@ static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
char *s = out; char *s = out;
/* /*
* Half the ports are for SPEED_HIGH and half for SPEED_SUPER, thus the * 2. * Half the ports are for SPEED_HIGH and half for SPEED_SUPER,
* thus the * 2.
*/ */
out += sprintf(out, "%d\n", VHCI_PORTS * vhci_num_controllers); out += sprintf(out, "%d\n", VHCI_PORTS * vhci_num_controllers);
return out - s; return out - s;
...@@ -366,6 +372,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, ...@@ -366,6 +372,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
vdev->devid = devid; vdev->devid = devid;
vdev->speed = speed; vdev->speed = speed;
vdev->ud.sockfd = sockfd;
vdev->ud.tcp_socket = socket; vdev->ud.tcp_socket = socket;
vdev->ud.status = VDEV_ST_NOTASSIGNED; vdev->ud.status = VDEV_ST_NOTASSIGNED;
......
...@@ -50,14 +50,14 @@ static int parse_status(const char *value) ...@@ -50,14 +50,14 @@ static int parse_status(const char *value)
while (*c != '\0') { while (*c != '\0') {
int port, status, speed, devid; int port, status, speed, devid;
unsigned long socket; int sockfd;
char lbusid[SYSFS_BUS_ID_SIZE]; char lbusid[SYSFS_BUS_ID_SIZE];
struct usbip_imported_device *idev; struct usbip_imported_device *idev;
char hub[3]; char hub[3];
ret = sscanf(c, "%2s %d %d %d %x %lx %31s\n", ret = sscanf(c, "%2s %d %d %d %x %u %31s\n",
hub, &port, &status, &speed, hub, &port, &status, &speed,
&devid, &socket, lbusid); &devid, &sockfd, lbusid);
if (ret < 5) { if (ret < 5) {
dbg("sscanf failed: %d", ret); dbg("sscanf failed: %d", ret);
...@@ -66,7 +66,7 @@ static int parse_status(const char *value) ...@@ -66,7 +66,7 @@ static int parse_status(const char *value)
dbg("hub %s port %d status %d speed %d devid %x", dbg("hub %s port %d status %d speed %d devid %x",
hub, port, status, speed, devid); hub, port, status, speed, devid);
dbg("socket %lx lbusid %s", socket, lbusid); dbg("sockfd %u lbusid %s", sockfd, lbusid);
/* if a device is connected, look at it */ /* if a device is connected, look at it */
idev = &vhci_driver->idev[port]; idev = &vhci_driver->idev[port];
...@@ -106,7 +106,7 @@ static int parse_status(const char *value) ...@@ -106,7 +106,7 @@ static int parse_status(const char *value)
return 0; return 0;
} }
#define MAX_STATUS_NAME 16 #define MAX_STATUS_NAME 18
static int refresh_imported_device_list(void) static int refresh_imported_device_list(void)
{ {
......
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