mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-10 16:23:42 +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;
|
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,
|
||||||
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 {
|
||||||
* 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 {
|
||||||
* 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 {
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
/* 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)
|
||||||
|
|
||||||
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 = {
|
||||||
.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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
*/
|
*/
|
||||||
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
|
||||||
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 @@
|
||||||
# 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
|
||||||
# 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
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
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 {
|
||||||
/* 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 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue