mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
USB fixes for 4.15-rc4
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWjQaXQ8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylt5ACdERNVQBbVoMadU97CUw/btE0FFtAAnjWr0xVn hzlFdbbueTSIJqsp+G4H =fjyL -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
c36c7a7c40
18 changed files with 144 additions and 99 deletions
|
@ -555,6 +555,9 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
|
|||
unsigned iad_num = 0;
|
||||
|
||||
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 ||
|
||||
config->desc.bLength < USB_DT_CONFIG_SIZE ||
|
||||
config->desc.bLength > size) {
|
||||
|
@ -568,7 +571,6 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
|
|||
buffer += config->desc.bLength;
|
||||
size -= config->desc.bLength;
|
||||
|
||||
nintf = nintf_orig = config->desc.bNumInterfaces;
|
||||
if (nintf > USB_MAXINTERFACES) {
|
||||
dev_warn(ddev, "config %d has too many interfaces: %d, "
|
||||
"using maximum allowed: %d\n",
|
||||
|
|
|
@ -537,6 +537,7 @@ struct dwc2_core_params {
|
|||
* 2 - Internal DMA
|
||||
* @power_optimized Are power optimizations enabled?
|
||||
* @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
|
||||
* available
|
||||
* @dev_token_q_depth Device Mode IN Token Sequence Learning Queue
|
||||
|
@ -565,6 +566,7 @@ struct dwc2_core_params {
|
|||
* 2 - 8 or 16 bits
|
||||
* @snpsid: Value from SNPSID register
|
||||
* @dev_ep_dirs: Direction of device endpoints (GHWCFG1)
|
||||
* @g_tx_fifo_size[] Power-on values of TxFIFO sizes
|
||||
*/
|
||||
struct dwc2_hw_params {
|
||||
unsigned op_mode:3;
|
||||
|
@ -586,12 +588,14 @@ struct dwc2_hw_params {
|
|||
unsigned fs_phy_type:2;
|
||||
unsigned i2c_enable:1;
|
||||
unsigned num_dev_ep:4;
|
||||
unsigned num_dev_in_eps : 4;
|
||||
unsigned num_dev_perio_in_ep:4;
|
||||
unsigned total_fifo_size:16;
|
||||
unsigned power_optimized:1;
|
||||
unsigned utmi_phy_data_width:2;
|
||||
u32 snpsid;
|
||||
u32 dev_ep_dirs;
|
||||
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
|
||||
};
|
||||
|
||||
/* Size of control and EP0 buffers */
|
||||
|
|
|
@ -195,55 +195,18 @@ int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
|
|||
{
|
||||
if (hsotg->hw_params.en_multiple_tx_fifo)
|
||||
/* In dedicated FIFO mode we need count of IN EPs */
|
||||
return (dwc2_readl(hsotg->regs + GHWCFG4) &
|
||||
GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT;
|
||||
return hsotg->hw_params.num_dev_in_eps;
|
||||
else
|
||||
/* In shared FIFO mode we need count of Periodic IN EPs */
|
||||
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
|
||||
* device mode TX FIFOs
|
||||
*/
|
||||
int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int ep_info_size;
|
||||
int addr;
|
||||
int tx_addr_max;
|
||||
u32 np_tx_fifo_size;
|
||||
|
@ -252,8 +215,7 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
|||
hsotg->params.g_np_tx_fifo_size);
|
||||
|
||||
/* 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 - ep_info_size;
|
||||
tx_addr_max = hsotg->hw_params.total_fifo_size;
|
||||
|
||||
addr = hsotg->params.g_rx_fifo_size + np_tx_fifo_size;
|
||||
if (tx_addr_max <= addr)
|
||||
|
|
|
@ -484,8 +484,7 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
|
|||
}
|
||||
|
||||
for (fifo = 1; fifo <= fifo_count; fifo++) {
|
||||
dptxfszn = (dwc2_readl(hsotg->regs + DPTXFSIZN(fifo)) &
|
||||
FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT;
|
||||
dptxfszn = hsotg->hw_params.g_tx_fifo_size[fifo];
|
||||
|
||||
if (hsotg->params.g_tx_fifo_size[fifo] < min ||
|
||||
hsotg->params.g_tx_fifo_size[fifo] > dptxfszn) {
|
||||
|
@ -609,6 +608,7 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
|
|||
struct dwc2_hw_params *hw = &hsotg->hw_params;
|
||||
bool forced;
|
||||
u32 gnptxfsiz;
|
||||
int fifo, fifo_count;
|
||||
|
||||
if (hsotg->dr_mode == USB_DR_MODE_HOST)
|
||||
return;
|
||||
|
@ -617,6 +617,14 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
|
|||
|
||||
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)
|
||||
dwc2_clear_force_mode(hsotg);
|
||||
|
||||
|
@ -661,14 +669,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
|||
hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
|
||||
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 */
|
||||
hw->dev_ep_dirs = hwcfg1;
|
||||
|
||||
|
@ -711,6 +711,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
|||
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
|
||||
hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >>
|
||||
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->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
|
||||
hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >>
|
||||
|
@ -719,6 +721,13 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
|||
/* fifo sizes */
|
||||
hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -51,8 +51,10 @@ static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
|
|||
|
||||
clk = of_clk_get(np, i);
|
||||
if (IS_ERR(clk)) {
|
||||
while (--i >= 0)
|
||||
while (--i >= 0) {
|
||||
clk_disable_unprepare(simple->clks[i]);
|
||||
clk_put(simple->clks[i]);
|
||||
}
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
|
@ -203,6 +205,7 @@ static struct platform_driver dwc3_of_simple_driver = {
|
|||
.driver = {
|
||||
.name = "dwc3-of-simple",
|
||||
.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,
|
|||
{
|
||||
const struct usb_endpoint_descriptor *desc = dep->endpoint.desc;
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
u32 timeout = 500;
|
||||
u32 timeout = 1000;
|
||||
u32 reg;
|
||||
|
||||
int cmd_status = 0;
|
||||
|
@ -912,7 +912,7 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
|
|||
*/
|
||||
if (speed == USB_SPEED_HIGH) {
|
||||
struct usb_ep *ep = &dep->endpoint;
|
||||
unsigned int mult = ep->mult - 1;
|
||||
unsigned int mult = 2;
|
||||
unsigned int maxp = usb_endpoint_maxp(ep->desc);
|
||||
|
||||
if (length <= (2 * maxp))
|
||||
|
|
|
@ -508,8 +508,8 @@ choice
|
|||
controller, and the relevant drivers for each function declared
|
||||
by the device.
|
||||
|
||||
endchoice
|
||||
|
||||
source "drivers/usb/gadget/legacy/Kconfig"
|
||||
|
||||
endchoice
|
||||
|
||||
endif # USB_GADGET
|
||||
|
|
|
@ -13,14 +13,6 @@
|
|||
# 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
|
||||
tristate "Gadget Zero (DEVELOPMENT)"
|
||||
select USB_LIBCOMPOSITE
|
||||
|
@ -487,7 +479,7 @@ endif
|
|||
# or video class gadget drivers), or specific hardware, here.
|
||||
config USB_G_WEBCAM
|
||||
tristate "USB Webcam Gadget"
|
||||
depends on VIDEO_DEV
|
||||
depends on VIDEO_V4L2
|
||||
select USB_LIBCOMPOSITE
|
||||
select VIDEOBUF2_VMALLOC
|
||||
select USB_F_UVC
|
||||
|
@ -498,5 +490,3 @@ config USB_G_WEBCAM
|
|||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_webcam".
|
||||
|
||||
endif
|
||||
|
|
|
@ -971,10 +971,9 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
xhci->devs[slot_id] = kzalloc(sizeof(*xhci->devs[slot_id]), flags);
|
||||
if (!xhci->devs[slot_id])
|
||||
dev = kzalloc(sizeof(*dev), flags);
|
||||
if (!dev)
|
||||
return 0;
|
||||
dev = xhci->devs[slot_id];
|
||||
|
||||
/* 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);
|
||||
|
@ -1015,9 +1014,17 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
|||
|
||||
trace_xhci_alloc_virt_device(dev);
|
||||
|
||||
xhci->devs[slot_id] = dev;
|
||||
|
||||
return 1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -3112,7 +3112,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
|
|||
{
|
||||
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))
|
||||
return ((td_total_len - transferred) >> 10);
|
||||
|
||||
|
@ -3121,8 +3121,8 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
|
|||
trb_buff_len == td_total_len)
|
||||
return 0;
|
||||
|
||||
/* for MTK xHCI, TD size doesn't include this TRB */
|
||||
if (xhci->quirks & XHCI_MTK_HOST)
|
||||
/* for MTK xHCI 0.96, TD size include this TRB, but not in 1.x */
|
||||
if ((xhci->quirks & XHCI_MTK_HOST) && (xhci->hci_version < 0x100))
|
||||
trb_buff_len = 0;
|
||||
|
||||
maxp = usb_endpoint_maxp(&urb->ep->desc);
|
||||
|
|
|
@ -284,7 +284,15 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
|
|||
musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
|
||||
portstate(musb->port1_status |= USB_PORT_STAT_POWER);
|
||||
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_DEV_MODE(musb);
|
||||
otg->default_a = 0;
|
||||
|
|
|
@ -2100,6 +2100,13 @@ UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0116,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
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>
|
||||
* JMicron responds to USN and several other SCSI ioctls with a
|
||||
|
|
|
@ -129,6 +129,13 @@ UNUSUAL_DEV(0x152d, 0x0567, 0x0000, 0x9999,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
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> */
|
||||
UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999,
|
||||
"VIA",
|
||||
|
|
|
@ -322,23 +322,34 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
|
|||
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_host_endpoint *ep;
|
||||
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)
|
||||
ep = udev->ep_in[epnum & 0x7f];
|
||||
else
|
||||
ep = udev->ep_out[epnum & 0x7f];
|
||||
if (!ep) {
|
||||
dev_err(&sdev->udev->dev, "no such endpoint?, %d\n",
|
||||
epnum);
|
||||
BUG();
|
||||
}
|
||||
if (!ep)
|
||||
goto err_ret;
|
||||
|
||||
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 (dir == USBIP_DIR_OUT)
|
||||
return usb_sndctrlpipe(udev, epnum);
|
||||
|
@ -361,15 +372,31 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir)
|
|||
}
|
||||
|
||||
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)
|
||||
return usb_sndisocpipe(udev, epnum);
|
||||
else
|
||||
return usb_rcvisocpipe(udev, epnum);
|
||||
}
|
||||
|
||||
err_ret:
|
||||
/* NOT REACHED */
|
||||
dev_err(&sdev->udev->dev, "get pipe, epnum %d\n", epnum);
|
||||
return 0;
|
||||
dev_err(&sdev->udev->dev, "CMD_SUBMIT: invalid epnum %d\n", epnum);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void masking_bogus_flags(struct urb *urb)
|
||||
|
@ -433,7 +460,10 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
|
|||
struct stub_priv *priv;
|
||||
struct usbip_device *ud = &sdev->ud;
|
||||
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);
|
||||
if (!priv)
|
||||
|
@ -452,7 +482,8 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
|
|||
}
|
||||
|
||||
/* 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 =
|
||||
kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
|
||||
GFP_KERNEL);
|
||||
|
|
|
@ -167,6 +167,13 @@ static int stub_send_ret_submit(struct stub_device *sdev)
|
|||
memset(&pdu_header, 0, sizeof(pdu_header));
|
||||
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)
|
||||
iovnum = 2 + urb->number_of_packets;
|
||||
else
|
||||
|
|
|
@ -256,6 +256,7 @@ struct usbip_device {
|
|||
/* lock for status */
|
||||
spinlock_t lock;
|
||||
|
||||
int sockfd;
|
||||
struct socket *tcp_socket;
|
||||
|
||||
struct task_struct *tcp_rx;
|
||||
|
|
|
@ -17,15 +17,20 @@
|
|||
|
||||
/*
|
||||
* output example:
|
||||
* hub port sta spd dev socket local_busid
|
||||
* hs 0000 004 000 00000000 c5a7bb80 1-2.3
|
||||
* hub port sta spd dev sockfd local_busid
|
||||
* 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
|
||||
* up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
|
||||
* port number and its peer IP address.
|
||||
* Output includes socket fd instead of socket pointer address to avoid
|
||||
* leaking kernel memory address in:
|
||||
* /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)
|
||||
{
|
||||
|
@ -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) {
|
||||
*out += sprintf(*out, "%03u %08x ",
|
||||
vdev->speed, vdev->devid);
|
||||
*out += sprintf(*out, "%16p %s",
|
||||
vdev->ud.tcp_socket,
|
||||
*out += sprintf(*out, "%u %s",
|
||||
vdev->ud.sockfd,
|
||||
dev_name(&vdev->udev->dev));
|
||||
|
||||
} else {
|
||||
|
@ -160,7 +165,8 @@ static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
|
|||
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);
|
||||
return out - s;
|
||||
|
@ -366,6 +372,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
vdev->devid = devid;
|
||||
vdev->speed = speed;
|
||||
vdev->ud.sockfd = sockfd;
|
||||
vdev->ud.tcp_socket = socket;
|
||||
vdev->ud.status = VDEV_ST_NOTASSIGNED;
|
||||
|
||||
|
|
|
@ -50,14 +50,14 @@ static int parse_status(const char *value)
|
|||
|
||||
while (*c != '\0') {
|
||||
int port, status, speed, devid;
|
||||
unsigned long socket;
|
||||
int sockfd;
|
||||
char lbusid[SYSFS_BUS_ID_SIZE];
|
||||
struct usbip_imported_device *idev;
|
||||
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,
|
||||
&devid, &socket, lbusid);
|
||||
&devid, &sockfd, lbusid);
|
||||
|
||||
if (ret < 5) {
|
||||
dbg("sscanf failed: %d", ret);
|
||||
|
@ -66,7 +66,7 @@ static int parse_status(const char *value)
|
|||
|
||||
dbg("hub %s port %d status %d speed %d devid %x",
|
||||
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 */
|
||||
idev = &vhci_driver->idev[port];
|
||||
|
@ -106,7 +106,7 @@ static int parse_status(const char *value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_STATUS_NAME 16
|
||||
#define MAX_STATUS_NAME 18
|
||||
|
||||
static int refresh_imported_device_list(void)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue