Skip to content

Commit

Permalink
Merge tag 'usb-4.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a number of USB fixes for 4.14-rc4 to resolved reported
  issues.

  There's a bunch of stuff in here based on the great work Andrey
  Konovalov is doing in fuzzing the USB stack. Lots of bug fixes when
  dealing with corrupted USB descriptors that we've never seen in
  "normal" operation, but is now ensuring the stack is much more
  hardened overall.

  There's also the usual XHCI and gadget driver fixes as well, and a
  build error fix, and a few other minor things, full details in the
  shortlog.

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

* tag 'usb-4.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (38 commits)
  usb: dwc3: of-simple: Add compatible for Spreadtrum SC9860 platform
  usb: gadget: udc: atmel: set vbus irqflags explicitly
  usb: gadget: ffs: handle I/O completion in-order
  usb: renesas_usbhs: fix usbhsf_fifo_clear() for RX direction
  usb: renesas_usbhs: fix the BCLR setting condition for non-DCP pipe
  usb: gadget: udc: renesas_usb3: Fix return value of usb3_write_pipe()
  usb: gadget: udc: renesas_usb3: fix Pn_RAMMAP.Pn_MPKT value
  usb: gadget: udc: renesas_usb3: fix for no-data control transfer
  USB: dummy-hcd: Fix erroneous synchronization change
  USB: dummy-hcd: fix infinite-loop resubmission bug
  USB: dummy-hcd: fix connection failures (wrong speed)
  USB: cdc-wdm: ignore -EPIPE from GetEncapsulatedResponse
  USB: devio: Don't corrupt user memory
  USB: devio: Prevent integer overflow in proc_do_submiturb()
  USB: g_mass_storage: Fix deadlock when driver is unbound
  USB: gadgetfs: Fix crash caused by inadequate synchronization
  USB: gadgetfs: fix copy_to_user while holding spinlock
  USB: uas: fix bug in handling of alternate settings
  usb-storage: unusual_devs entry to fix write-access regression for Seagate external drives
  usb-storage: fix bogus hardware error messages for ATA pass-thru devices
  ...
  • Loading branch information
Linus Torvalds committed Oct 3, 2017
2 parents 27b3b16 + 80c82ff commit 887c8ba
Show file tree
Hide file tree
Showing 33 changed files with 277 additions and 145 deletions.
4 changes: 3 additions & 1 deletion drivers/usb/class/cdc-wdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,10 @@ static void wdm_in_callback(struct urb *urb)
/*
* only set a new error if there is no previous error.
* Errors are only cleared during read/open
* Avoid propagating -EPIPE (stall) to userspace since it is
* better handled as an empty read
*/
if (desc->rerr == 0)
if (desc->rerr == 0 && status != -EPIPE)
desc->rerr = status;

if (length + desc->length > desc->wMaxCommand) {
Expand Down
16 changes: 12 additions & 4 deletions drivers/usb/core/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -643,15 +643,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,

} else if (header->bDescriptorType ==
USB_DT_INTERFACE_ASSOCIATION) {
struct usb_interface_assoc_descriptor *d;

d = (struct usb_interface_assoc_descriptor *)header;
if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) {
dev_warn(ddev,
"config %d has an invalid interface association descriptor of length %d, skipping\n",
cfgno, d->bLength);
continue;
}

if (iad_num == USB_MAXIADS) {
dev_warn(ddev, "found more Interface "
"Association Descriptors "
"than allocated for in "
"configuration %d\n", cfgno);
} else {
config->intf_assoc[iad_num] =
(struct usb_interface_assoc_descriptor
*)header;
config->intf_assoc[iad_num] = d;
iad_num++;
}

Expand Down Expand Up @@ -852,7 +860,7 @@ int usb_get_configuration(struct usb_device *dev)
}

if (dev->quirks & USB_QUIRK_DELAY_INIT)
msleep(100);
msleep(200);

result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
bigbuffer, length);
Expand Down
11 changes: 10 additions & 1 deletion drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ module_param(usbfs_memory_mb, uint, 0644);
MODULE_PARM_DESC(usbfs_memory_mb,
"maximum MB allowed for usbfs buffers (0 = no limit)");

/* Hard limit, necessary to avoid arithmetic overflow */
#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)

static atomic64_t usbfs_memory_usage; /* Total memory currently allocated */

/* Check whether it's okay to allocate more memory for a transfer */
Expand Down Expand Up @@ -1460,6 +1463,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
USBDEVFS_URB_ZERO_PACKET |
USBDEVFS_URB_NO_INTERRUPT))
return -EINVAL;
if ((unsigned int)uurb->buffer_length >= USBFS_XFER_MAX)
return -EINVAL;
if (uurb->buffer_length > 0 && !uurb->buffer)
return -EINVAL;
if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
Expand Down Expand Up @@ -1571,7 +1576,11 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
totlen += isopkt[u].length;
}
u *= sizeof(struct usb_iso_packet_descriptor);
uurb->buffer_length = totlen;
if (totlen <= uurb->buffer_length)
uurb->buffer_length = totlen;
else
WARN_ONCE(1, "uurb->buffer_length is too short %d vs %d",
totlen, uurb->buffer_length);
break;

default:
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -4838,7 +4838,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
goto loop;

if (udev->quirks & USB_QUIRK_DELAY_INIT)
msleep(1000);
msleep(2000);

/* consecutive bus-powered hubs aren't reliable; they can
* violate the voltage drop budget. if the new child has
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/core/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -2069,6 +2069,10 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
elength = 1;
goto next_desc;
}
if ((buflen < elength) || (elength < 3)) {
dev_err(&intf->dev, "invalid descriptor buffer length\n");
break;
}
if (buffer[1] != USB_DT_CS_INTERFACE) {
dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/dwc3/dwc3-of-simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = {
{ .compatible = "rockchip,rk3399-dwc3" },
{ .compatible = "xlnx,zynqmp-dwc3" },
{ .compatible = "cavium,octeon-7130-usb-uctl" },
{ .compatible = "sprd,sc9860-dwc3" },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
Expand Down
7 changes: 7 additions & 0 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
DWC3_TRBCTL_CONTROL_DATA,
true);

req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];

/* Now prepare one extra TRB to align transfer size */
dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
maxpacket - rem,
Expand All @@ -1015,6 +1017,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
DWC3_TRBCTL_CONTROL_DATA,
true);

req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];

/* Now prepare one extra TRB to align transfer size */
dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
0, DWC3_TRBCTL_CONTROL_DATA,
Expand All @@ -1029,6 +1033,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
dwc3_ep0_prepare_one_trb(dep, req->request.dma,
req->request.length, DWC3_TRBCTL_CONTROL_DATA,
false);

req->trb = &dwc->ep0_trb[dep->trb_enqueue];

ret = dwc3_ep0_start_trans(dep);
}

Expand Down
17 changes: 13 additions & 4 deletions drivers/usb/gadget/function/f_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
static void ffs_data_get(struct ffs_data *ffs);
static void ffs_data_put(struct ffs_data *ffs);
/* Creates new ffs_data object. */
static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc));
static struct ffs_data *__must_check ffs_data_new(const char *dev_name)
__attribute__((malloc));

/* Opened counter handling. */
static void ffs_data_opened(struct ffs_data *ffs);
Expand Down Expand Up @@ -780,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
struct usb_request *req)
{
struct ffs_io_data *io_data = req->context;
struct ffs_data *ffs = io_data->ffs;

ENTER();

INIT_WORK(&io_data->work, ffs_user_copy_worker);
schedule_work(&io_data->work);
queue_work(ffs->io_completion_wq, &io_data->work);
}

static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile)
Expand Down Expand Up @@ -1500,7 +1502,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
if (unlikely(ret < 0))
return ERR_PTR(ret);

ffs = ffs_data_new();
ffs = ffs_data_new(dev_name);
if (unlikely(!ffs))
return ERR_PTR(-ENOMEM);
ffs->file_perms = data.perms;
Expand Down Expand Up @@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs)
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
waitqueue_active(&ffs->ep0req_completion.wait) ||
waitqueue_active(&ffs->wait));
destroy_workqueue(ffs->io_completion_wq);
kfree(ffs->dev_name);
kfree(ffs);
}
Expand Down Expand Up @@ -1642,14 +1645,20 @@ static void ffs_data_closed(struct ffs_data *ffs)
ffs_data_put(ffs);
}

static struct ffs_data *ffs_data_new(void)
static struct ffs_data *ffs_data_new(const char *dev_name)
{
struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
if (unlikely(!ffs))
return NULL;

ENTER();

ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name);
if (!ffs->io_completion_wq) {
kfree(ffs);
return NULL;
}

refcount_set(&ffs->ref, 1);
atomic_set(&ffs->opened, 0);
ffs->state = FFS_READ_DESCRIPTORS;
Expand Down
27 changes: 7 additions & 20 deletions drivers/usb/gadget/function/f_mass_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,6 @@ struct fsg_common {
struct completion thread_notifier;
struct task_struct *thread_task;

/* Callback functions. */
const struct fsg_operations *ops;
/* Gadget's private data. */
void *private_data;

Expand Down Expand Up @@ -2438,6 +2436,7 @@ static void handle_exception(struct fsg_common *common)
static int fsg_main_thread(void *common_)
{
struct fsg_common *common = common_;
int i;

/*
* Allow the thread to be killed by a signal, but set the signal mask
Expand Down Expand Up @@ -2476,21 +2475,16 @@ static int fsg_main_thread(void *common_)
common->thread_task = NULL;
spin_unlock_irq(&common->lock);

if (!common->ops || !common->ops->thread_exits
|| common->ops->thread_exits(common) < 0) {
int i;
/* Eject media from all LUNs */

down_write(&common->filesem);
for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
struct fsg_lun *curlun = common->luns[i];
if (!curlun || !fsg_lun_is_open(curlun))
continue;
down_write(&common->filesem);
for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
struct fsg_lun *curlun = common->luns[i];

if (curlun && fsg_lun_is_open(curlun))
fsg_lun_close(curlun);
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
}
up_write(&common->filesem);
}
up_write(&common->filesem);

/* Let fsg_unbind() know the thread has exited */
complete_and_exit(&common->thread_notifier, 0);
Expand Down Expand Up @@ -2681,13 +2675,6 @@ void fsg_common_remove_luns(struct fsg_common *common)
}
EXPORT_SYMBOL_GPL(fsg_common_remove_luns);

void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops)
{
common->ops = ops;
}
EXPORT_SYMBOL_GPL(fsg_common_set_ops);

void fsg_common_free_buffers(struct fsg_common *common)
{
_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
Expand Down
14 changes: 0 additions & 14 deletions drivers/usb/gadget/function/f_mass_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,6 @@ struct fsg_module_parameters {
struct fsg_common;

/* FSF callback functions */
struct fsg_operations {
/*
* Callback function to call when thread exits. If no
* callback is set or it returns value lower then zero MSF
* will force eject all LUNs it operates on (including those
* marked as non-removable or with prevent_medium_removal flag
* set).
*/
int (*thread_exits)(struct fsg_common *common);
};

struct fsg_lun_opts {
struct config_group group;
struct fsg_lun *lun;
Expand Down Expand Up @@ -142,9 +131,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun);

void fsg_common_remove_luns(struct fsg_common *common);

void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops);

int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
unsigned int id, const char *name,
const char **name_pfx);
Expand Down
7 changes: 6 additions & 1 deletion drivers/usb/gadget/function/f_printer.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
size_t size; /* Amount of data in a TX request. */
size_t bytes_copied = 0;
struct usb_request *req;
int value;

DBG(dev, "printer_write trying to send %d bytes\n", (int)len);

Expand Down Expand Up @@ -634,7 +635,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
return -EAGAIN;
}

if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
/* here, we unlock, and only unlock, to avoid deadlock. */
spin_unlock(&dev->lock);
value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
spin_lock(&dev->lock);
if (value) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
mutex_unlock(&dev->lock_printer_io);
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/gadget/function/u_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ struct ffs_data {
} file_perms;

struct eventfd_ctx *ffs_eventfd;
struct workqueue_struct *io_completion_wq;
bool no_disconnect;
struct work_struct reset_work;

Expand Down
Loading

0 comments on commit 887c8ba

Please sign in to comment.