From 70f7ca9a0262784d0b80727860a63d64ab228e7b Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 15 Jun 2016 15:56:11 +0200 Subject: usb: devio, do not warn when allocation fails usbdev_mmap allocates a buffer. The size of the buffer is determined by a user. So with this code (no need to be root): int fd = open("/dev/bus/usb/001/001", O_RDONLY); mmap(NULL, 0x800000, PROT_READ, MAP_SHARED, fd, 0); we can see a warning: WARNING: CPU: 0 PID: 21771 at ../mm/page_alloc.c:3563 __alloc_pages_slowpath+0x1036/0x16e0() ... Call Trace: [] ? warn_slowpath_null+0x2e/0x40 [] ? __alloc_pages_slowpath+0x1036/0x16e0 [] ? warn_alloc_failed+0x250/0x250 [] ? get_page_from_freelist+0x75b/0x28b0 [] ? __alloc_pages_nodemask+0x583/0x6b0 [] ? __alloc_pages_slowpath+0x16e0/0x16e0 [] ? dma_generic_alloc_coherent+0x104/0x220 [] ? hcd_buffer_alloc+0x1d6/0x3e0 [usbcore] [] ? hcd_buffer_destroy+0xa0/0xa0 [usbcore] [] ? usb_alloc_coherent+0x65/0x90 [usbcore] [] ? usbdev_mmap+0x1a5/0x770 [usbcore] ... Allocations like this one should be marked as __GFP_NOWARN. So do so. The size could be also clipped by something like: if (size >= (1 << (MAX_ORDER + PAGE_SHIFT - 1))) return -ENOMEM; But I think the overall limit of 16M (by usbfs_increase_memory_usage) is enough, so that we only silence the warning here. Signed-off-by: Jiri Slaby Cc: Greg Kroah-Hartman Cc: Alan Stern Cc: Steinar H. Gunderson Cc: Markus Rechberger Fixes: f7d34b445a (USB: Add support for usbfs zerocopy.) Cc: 4.6+ Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/core/devio.c') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e9f5043a2167..472cbcdf7456 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -241,7 +241,8 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma) goto error_decrease_mem; } - mem = usb_alloc_coherent(ps->dev, size, GFP_USER, &dma_handle); + mem = usb_alloc_coherent(ps->dev, size, GFP_USER | __GFP_NOWARN, + &dma_handle); if (!mem) { ret = -ENOMEM; goto error_free_usbm; -- cgit v1.2.3-70-g09d2 From 5cce438298a0d2a7a857a4a3c3e26aeb8f77b941 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 10 Jun 2016 14:42:55 -0400 Subject: USB: remove race condition in usbfs/libusb when using reap-after-disconnect Hans de Goede has reported a difficulty in the Linux port of libusb. When a device is removed, the poll() system call in usbfs starts returning POLLERR as soon as udev->state is set to USB_STATE_NOTATTACHED, but the outstanding URBs are not available for reaping until some time later (after usbdev_remove() has been called). This is awkward for libusb or other usbfs clients, although not an insuperable problem. At any rate, it's easy to change usbfs so that it returns POLLHUP as soon as the state becomes USB_STATE_NOTATTACHED but it doesn't return POLLERR until after the outstanding URBs have completed. That's what this patch does; it uses the fact that ps->list is always on the dev->filelist list until usbdev_remove() takes it off, which happens after all the outstanding URBs have been cancelled. Signed-off-by: Alan Stern Reported-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/usb/core/devio.c') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 472cbcdf7456..e6a6d67c8705 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2583,7 +2583,9 @@ static unsigned int usbdev_poll(struct file *file, if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) mask |= POLLOUT | POLLWRNORM; if (!connected(ps)) - mask |= POLLERR | POLLHUP; + mask |= POLLHUP; + if (list_empty(&ps->list)) + mask |= POLLERR; return mask; } -- cgit v1.2.3-70-g09d2 From 53e5f36fbd2453ad69a3369a1db62dc06c30a4aa Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 23 Aug 2016 15:32:51 -0400 Subject: USB: avoid left shift by -1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UBSAN complains about a left shift by -1 in proc_do_submiturb(). This can occur when an URB is submitted for a bulk or control endpoint on a high-speed device, since the code doesn't bother to check the endpoint type; normally only interrupt or isochronous endpoints have a nonzero bInterval value. Aside from the fact that the operation is illegal, it shouldn't matter because the result isn't used. Still, in theory it could cause a hardware exception or other problem, so we should work around it. This patch avoids doing the left shift unless the shift amount is >= 0. The same piece of code has another problem. When checking the device speed (the exponential encoding for interrupt endpoints is used only by high-speed or faster devices), we need to look for speed >= USB_SPEED_SUPER as well as speed == USB_SPEED HIGH. The patch adds this check. Signed-off-by: Alan Stern Reported-by: Vittorio Zecca Tested-by: Vittorio Zecca Suggested-by: Bjørn Mork CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/usb/core/devio.c') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e6a6d67c8705..09c8d9ca61ae 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1709,11 +1709,17 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb as->urb->start_frame = uurb->start_frame; as->urb->number_of_packets = number_of_packets; as->urb->stream_id = stream_id; - if (uurb->type == USBDEVFS_URB_TYPE_ISO || - ps->dev->speed == USB_SPEED_HIGH) - as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); - else - as->urb->interval = ep->desc.bInterval; + + if (ep->desc.bInterval) { + if (uurb->type == USBDEVFS_URB_TYPE_ISO || + ps->dev->speed == USB_SPEED_HIGH || + ps->dev->speed >= USB_SPEED_SUPER) + as->urb->interval = 1 << + min(15, ep->desc.bInterval - 1); + else + as->urb->interval = ep->desc.bInterval; + } + as->urb->context = as; as->urb->complete = async_completed; for (totlen = u = 0; u < number_of_packets; u++) { -- cgit v1.2.3-70-g09d2