Skip to content

Commit 887c8ba

Browse files
committed
Merge tag 'usb-4.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/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 ...
2 parents 27b3b16 + 80c82ff commit 887c8ba

33 files changed

+277
-145
lines changed

drivers/usb/class/cdc-wdm.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,10 @@ static void wdm_in_callback(struct urb *urb)
190190
/*
191191
* only set a new error if there is no previous error.
192192
* Errors are only cleared during read/open
193+
* Avoid propagating -EPIPE (stall) to userspace since it is
194+
* better handled as an empty read
193195
*/
194-
if (desc->rerr == 0)
196+
if (desc->rerr == 0 && status != -EPIPE)
195197
desc->rerr = status;
196198

197199
if (length + desc->length > desc->wMaxCommand) {

drivers/usb/core/config.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -643,15 +643,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
643643

644644
} else if (header->bDescriptorType ==
645645
USB_DT_INTERFACE_ASSOCIATION) {
646+
struct usb_interface_assoc_descriptor *d;
647+
648+
d = (struct usb_interface_assoc_descriptor *)header;
649+
if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) {
650+
dev_warn(ddev,
651+
"config %d has an invalid interface association descriptor of length %d, skipping\n",
652+
cfgno, d->bLength);
653+
continue;
654+
}
655+
646656
if (iad_num == USB_MAXIADS) {
647657
dev_warn(ddev, "found more Interface "
648658
"Association Descriptors "
649659
"than allocated for in "
650660
"configuration %d\n", cfgno);
651661
} else {
652-
config->intf_assoc[iad_num] =
653-
(struct usb_interface_assoc_descriptor
654-
*)header;
662+
config->intf_assoc[iad_num] = d;
655663
iad_num++;
656664
}
657665

@@ -852,7 +860,7 @@ int usb_get_configuration(struct usb_device *dev)
852860
}
853861

854862
if (dev->quirks & USB_QUIRK_DELAY_INIT)
855-
msleep(100);
863+
msleep(200);
856864

857865
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
858866
bigbuffer, length);

drivers/usb/core/devio.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ module_param(usbfs_memory_mb, uint, 0644);
140140
MODULE_PARM_DESC(usbfs_memory_mb,
141141
"maximum MB allowed for usbfs buffers (0 = no limit)");
142142

143+
/* Hard limit, necessary to avoid arithmetic overflow */
144+
#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
145+
143146
static atomic64_t usbfs_memory_usage; /* Total memory currently allocated */
144147

145148
/* Check whether it's okay to allocate more memory for a transfer */
@@ -1460,6 +1463,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
14601463
USBDEVFS_URB_ZERO_PACKET |
14611464
USBDEVFS_URB_NO_INTERRUPT))
14621465
return -EINVAL;
1466+
if ((unsigned int)uurb->buffer_length >= USBFS_XFER_MAX)
1467+
return -EINVAL;
14631468
if (uurb->buffer_length > 0 && !uurb->buffer)
14641469
return -EINVAL;
14651470
if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
@@ -1571,7 +1576,11 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
15711576
totlen += isopkt[u].length;
15721577
}
15731578
u *= sizeof(struct usb_iso_packet_descriptor);
1574-
uurb->buffer_length = totlen;
1579+
if (totlen <= uurb->buffer_length)
1580+
uurb->buffer_length = totlen;
1581+
else
1582+
WARN_ONCE(1, "uurb->buffer_length is too short %d vs %d",
1583+
totlen, uurb->buffer_length);
15751584
break;
15761585

15771586
default:

drivers/usb/core/hub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4838,7 +4838,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
48384838
goto loop;
48394839

48404840
if (udev->quirks & USB_QUIRK_DELAY_INIT)
4841-
msleep(1000);
4841+
msleep(2000);
48424842

48434843
/* consecutive bus-powered hubs aren't reliable; they can
48444844
* violate the voltage drop budget. if the new child has

drivers/usb/core/message.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,10 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
20692069
elength = 1;
20702070
goto next_desc;
20712071
}
2072+
if ((buflen < elength) || (elength < 3)) {
2073+
dev_err(&intf->dev, "invalid descriptor buffer length\n");
2074+
break;
2075+
}
20722076
if (buffer[1] != USB_DT_CS_INTERFACE) {
20732077
dev_err(&intf->dev, "skipping garbage\n");
20742078
goto next_desc;

drivers/usb/dwc3/dwc3-of-simple.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = {
177177
{ .compatible = "rockchip,rk3399-dwc3" },
178178
{ .compatible = "xlnx,zynqmp-dwc3" },
179179
{ .compatible = "cavium,octeon-7130-usb-uctl" },
180+
{ .compatible = "sprd,sc9860-dwc3" },
180181
{ /* Sentinel */ }
181182
};
182183
MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);

drivers/usb/dwc3/ep0.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
990990
DWC3_TRBCTL_CONTROL_DATA,
991991
true);
992992

993+
req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];
994+
993995
/* Now prepare one extra TRB to align transfer size */
994996
dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
995997
maxpacket - rem,
@@ -1015,6 +1017,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
10151017
DWC3_TRBCTL_CONTROL_DATA,
10161018
true);
10171019

1020+
req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];
1021+
10181022
/* Now prepare one extra TRB to align transfer size */
10191023
dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
10201024
0, DWC3_TRBCTL_CONTROL_DATA,
@@ -1029,6 +1033,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
10291033
dwc3_ep0_prepare_one_trb(dep, req->request.dma,
10301034
req->request.length, DWC3_TRBCTL_CONTROL_DATA,
10311035
false);
1036+
1037+
req->trb = &dwc->ep0_trb[dep->trb_enqueue];
1038+
10321039
ret = dwc3_ep0_start_trans(dep);
10331040
}
10341041

drivers/usb/gadget/function/f_fs.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
static void ffs_data_get(struct ffs_data *ffs);
4747
static void ffs_data_put(struct ffs_data *ffs);
4848
/* Creates new ffs_data object. */
49-
static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc));
49+
static struct ffs_data *__must_check ffs_data_new(const char *dev_name)
50+
__attribute__((malloc));
5051

5152
/* Opened counter handling. */
5253
static void ffs_data_opened(struct ffs_data *ffs);
@@ -780,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
780781
struct usb_request *req)
781782
{
782783
struct ffs_io_data *io_data = req->context;
784+
struct ffs_data *ffs = io_data->ffs;
783785

784786
ENTER();
785787

786788
INIT_WORK(&io_data->work, ffs_user_copy_worker);
787-
schedule_work(&io_data->work);
789+
queue_work(ffs->io_completion_wq, &io_data->work);
788790
}
789791

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

1503-
ffs = ffs_data_new();
1505+
ffs = ffs_data_new(dev_name);
15041506
if (unlikely(!ffs))
15051507
return ERR_PTR(-ENOMEM);
15061508
ffs->file_perms = data.perms;
@@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs)
16101612
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
16111613
waitqueue_active(&ffs->ep0req_completion.wait) ||
16121614
waitqueue_active(&ffs->wait));
1615+
destroy_workqueue(ffs->io_completion_wq);
16131616
kfree(ffs->dev_name);
16141617
kfree(ffs);
16151618
}
@@ -1642,14 +1645,20 @@ static void ffs_data_closed(struct ffs_data *ffs)
16421645
ffs_data_put(ffs);
16431646
}
16441647

1645-
static struct ffs_data *ffs_data_new(void)
1648+
static struct ffs_data *ffs_data_new(const char *dev_name)
16461649
{
16471650
struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
16481651
if (unlikely(!ffs))
16491652
return NULL;
16501653

16511654
ENTER();
16521655

1656+
ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name);
1657+
if (!ffs->io_completion_wq) {
1658+
kfree(ffs);
1659+
return NULL;
1660+
}
1661+
16531662
refcount_set(&ffs->ref, 1);
16541663
atomic_set(&ffs->opened, 0);
16551664
ffs->state = FFS_READ_DESCRIPTORS;

drivers/usb/gadget/function/f_mass_storage.c

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,6 @@ struct fsg_common {
307307
struct completion thread_notifier;
308308
struct task_struct *thread_task;
309309

310-
/* Callback functions. */
311-
const struct fsg_operations *ops;
312310
/* Gadget's private data. */
313311
void *private_data;
314312

@@ -2438,6 +2436,7 @@ static void handle_exception(struct fsg_common *common)
24382436
static int fsg_main_thread(void *common_)
24392437
{
24402438
struct fsg_common *common = common_;
2439+
int i;
24412440

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

2479-
if (!common->ops || !common->ops->thread_exits
2480-
|| common->ops->thread_exits(common) < 0) {
2481-
int i;
2478+
/* Eject media from all LUNs */
24822479

2483-
down_write(&common->filesem);
2484-
for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
2485-
struct fsg_lun *curlun = common->luns[i];
2486-
if (!curlun || !fsg_lun_is_open(curlun))
2487-
continue;
2480+
down_write(&common->filesem);
2481+
for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
2482+
struct fsg_lun *curlun = common->luns[i];
24882483

2484+
if (curlun && fsg_lun_is_open(curlun))
24892485
fsg_lun_close(curlun);
2490-
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
2491-
}
2492-
up_write(&common->filesem);
24932486
}
2487+
up_write(&common->filesem);
24942488

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

2684-
void fsg_common_set_ops(struct fsg_common *common,
2685-
const struct fsg_operations *ops)
2686-
{
2687-
common->ops = ops;
2688-
}
2689-
EXPORT_SYMBOL_GPL(fsg_common_set_ops);
2690-
26912678
void fsg_common_free_buffers(struct fsg_common *common)
26922679
{
26932680
_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);

drivers/usb/gadget/function/f_mass_storage.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,6 @@ struct fsg_module_parameters {
6060
struct fsg_common;
6161

6262
/* FSF callback functions */
63-
struct fsg_operations {
64-
/*
65-
* Callback function to call when thread exits. If no
66-
* callback is set or it returns value lower then zero MSF
67-
* will force eject all LUNs it operates on (including those
68-
* marked as non-removable or with prevent_medium_removal flag
69-
* set).
70-
*/
71-
int (*thread_exits)(struct fsg_common *common);
72-
};
73-
7463
struct fsg_lun_opts {
7564
struct config_group group;
7665
struct fsg_lun *lun;
@@ -142,9 +131,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun);
142131

143132
void fsg_common_remove_luns(struct fsg_common *common);
144133

145-
void fsg_common_set_ops(struct fsg_common *common,
146-
const struct fsg_operations *ops);
147-
148134
int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
149135
unsigned int id, const char *name,
150136
const char **name_pfx);

drivers/usb/gadget/function/f_printer.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
555555
size_t size; /* Amount of data in a TX request. */
556556
size_t bytes_copied = 0;
557557
struct usb_request *req;
558+
int value;
558559

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

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

637-
if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
638+
/* here, we unlock, and only unlock, to avoid deadlock. */
639+
spin_unlock(&dev->lock);
640+
value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
641+
spin_lock(&dev->lock);
642+
if (value) {
638643
list_add(&req->list, &dev->tx_reqs);
639644
spin_unlock_irqrestore(&dev->lock, flags);
640645
mutex_unlock(&dev->lock_printer_io);

drivers/usb/gadget/function/u_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ struct ffs_data {
279279
} file_perms;
280280

281281
struct eventfd_ctx *ffs_eventfd;
282+
struct workqueue_struct *io_completion_wq;
282283
bool no_disconnect;
283284
struct work_struct reset_work;
284285

0 commit comments

Comments
 (0)