From: Greg Kroah-Hartman Date: Thu, 7 Dec 2017 12:20:31 +0000 (+0100) Subject: 3.18-stable patches X-Git-Tag: v3.18.87~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ab85ccd839a9df870bcfd14154cd142c9499d6c7;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: usb-devio-prevent-integer-overflow-in-proc_do_submiturb.patch usb-host-fix-incorrect-updating-of-offset.patch usb-hub-cycle-hub-power-when-initialization-fails.patch usb-increase-usbfs-transfer-limit.patch usb-usbfs-filter-flags-passed-in-from-user-space.patch --- diff --git a/queue-3.18/series b/queue-3.18/series index 0d75f9c061c..a51bf0f9e00 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -19,3 +19,8 @@ ima-fix-hash-algorithm-initialization.patch uas-always-apply-us_fl_no_ata_1x-quirk-to-seagate-devices.patch usb-quirks-add-no-lpm-quirk-for-ky-688-usb-3.1-type-c-hub.patch serial-8250_pci-add-amazon-pci-serial-device-id.patch +usb-hub-cycle-hub-power-when-initialization-fails.patch +usb-increase-usbfs-transfer-limit.patch +usb-devio-prevent-integer-overflow-in-proc_do_submiturb.patch +usb-usbfs-filter-flags-passed-in-from-user-space.patch +usb-host-fix-incorrect-updating-of-offset.patch diff --git a/queue-3.18/usb-devio-prevent-integer-overflow-in-proc_do_submiturb.patch b/queue-3.18/usb-devio-prevent-integer-overflow-in-proc_do_submiturb.patch new file mode 100644 index 00000000000..533ef26067e --- /dev/null +++ b/queue-3.18/usb-devio-prevent-integer-overflow-in-proc_do_submiturb.patch @@ -0,0 +1,52 @@ +From 57999d1107c1e60c2ca7088f2ac0f819e2f554b3 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 22 Sep 2017 23:43:25 +0300 +Subject: USB: devio: Prevent integer overflow in proc_do_submiturb() + +From: Dan Carpenter + +commit 57999d1107c1e60c2ca7088f2ac0f819e2f554b3 upstream. + +There used to be an integer overflow check in proc_do_submiturb() but +we removed it. It turns out that it's still required. The +uurb->buffer_length variable is a signed integer and it's controlled by +the user. It can lead to an integer overflow when we do: + + num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE); + +If we strip away the macro then that line looks like this: + + num_sgs = (uurb->buffer_length + USB_SG_SIZE - 1) / USB_SG_SIZE; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +It's the first addition which can overflow. + +Fixes: 1129d270cbfb ("USB: Increase usbfs transfer limit") +Signed-off-by: Dan Carpenter +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/devio.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -118,6 +118,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 */ +@@ -1295,6 +1298,8 @@ static int proc_do_submiturb(struct usb_ + 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 && diff --git a/queue-3.18/usb-host-fix-incorrect-updating-of-offset.patch b/queue-3.18/usb-host-fix-incorrect-updating-of-offset.patch new file mode 100644 index 00000000000..abf1b87e374 --- /dev/null +++ b/queue-3.18/usb-host-fix-incorrect-updating-of-offset.patch @@ -0,0 +1,37 @@ +From 1d5a31582ef046d3b233f0da1a68ae26519b2f0a Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Tue, 7 Nov 2017 16:45:04 +0000 +Subject: usb: host: fix incorrect updating of offset + +From: Colin Ian King + +commit 1d5a31582ef046d3b233f0da1a68ae26519b2f0a upstream. + +The variable temp is incorrectly being updated, instead it should +be offset otherwise the loop just reads the same capability value +and loops forever. Thanks to Alan Stern for pointing out the +correct fix to my original fix. Fix also cleans up clang warning: + +drivers/usb/host/ehci-dbg.c:840:4: warning: Value stored to 'temp' +is never read + +Fixes: d49d43174400 ("USB: misc ehci updates") +Signed-off-by: Colin Ian King +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-dbg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/host/ehci-dbg.c ++++ b/drivers/usb/host/ehci-dbg.c +@@ -850,7 +850,7 @@ static ssize_t fill_registers_buffer(str + default: /* unknown */ + break; + } +- temp = (cap >> 8) & 0xff; ++ offset = (cap >> 8) & 0xff; + } + } + #endif diff --git a/queue-3.18/usb-hub-cycle-hub-power-when-initialization-fails.patch b/queue-3.18/usb-hub-cycle-hub-power-when-initialization-fails.patch new file mode 100644 index 00000000000..f9db665afb3 --- /dev/null +++ b/queue-3.18/usb-hub-cycle-hub-power-when-initialization-fails.patch @@ -0,0 +1,57 @@ +From 973593a960ddac0f14f0d8877d2d0abe0afda795 Mon Sep 17 00:00:00 2001 +From: Mike Looijmans +Date: Thu, 9 Nov 2017 13:16:46 +0100 +Subject: usb: hub: Cycle HUB power when initialization fails + +From: Mike Looijmans + +commit 973593a960ddac0f14f0d8877d2d0abe0afda795 upstream. + +Sometimes the USB device gets confused about the state of the initialization and +the connection fails. In particular, the device thinks that it's already set up +and running while the host thinks the device still needs to be configured. To +work around this issue, power-cycle the hub's output to issue a sort of "reset" +to the device. This makes the device restart its state machine and then the +initialization succeeds. + +This fixes problems where the kernel reports a list of errors like this: + +usb 1-1.3: device not accepting address 19, error -71 + +The end result is a non-functioning device. After this patch, the sequence +becomes like this: + +usb 1-1.3: new high-speed USB device number 18 using ci_hdrc +usb 1-1.3: device not accepting address 18, error -71 +usb 1-1.3: new high-speed USB device number 19 using ci_hdrc +usb 1-1.3: device not accepting address 19, error -71 +usb 1-1-port3: attempt power cycle +usb 1-1.3: new high-speed USB device number 21 using ci_hdrc +usb-storage 1-1.3:1.2: USB Mass Storage device detected + +Signed-off-by: Mike Looijmans +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -4816,6 +4816,15 @@ loop: + usb_put_dev(udev); + if ((status == -ENOTCONN) || (status == -ENOTSUPP)) + break; ++ ++ /* When halfway through our retry count, power-cycle the port */ ++ if (i == (SET_CONFIG_TRIES / 2) - 1) { ++ dev_info(&port_dev->dev, "attempt power cycle\n"); ++ usb_hub_set_port_power(hdev, hub, port1, false); ++ msleep(2 * hub_power_on_good_delay(hub)); ++ usb_hub_set_port_power(hdev, hub, port1, true); ++ msleep(hub_power_on_good_delay(hub)); ++ } + } + if (hub->hdev->parent || + !hcd->driver->port_handed_over || diff --git a/queue-3.18/usb-increase-usbfs-transfer-limit.patch b/queue-3.18/usb-increase-usbfs-transfer-limit.patch new file mode 100644 index 00000000000..2bebe82d203 --- /dev/null +++ b/queue-3.18/usb-increase-usbfs-transfer-limit.patch @@ -0,0 +1,100 @@ +From 1129d270cbfbb7e2b1ec3dede4a13930bdd10e41 Mon Sep 17 00:00:00 2001 +From: Mateusz Berezecki +Date: Wed, 21 Dec 2016 09:19:14 -0800 +Subject: USB: Increase usbfs transfer limit + +From: Mateusz Berezecki + +commit 1129d270cbfbb7e2b1ec3dede4a13930bdd10e41 upstream. + +Promote a variable keeping track of USB transfer memory usage to a +wider data type and allow for higher bandwidth transfers from a large +number of USB devices connected to a single host. + +Signed-off-by: Mateusz Berezecki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/devio.c | 43 ++++++++++++++++--------------------------- + 1 file changed, 16 insertions(+), 27 deletions(-) + +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -113,42 +113,35 @@ enum snoop_when { + #define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0) + + /* Limit on the total amount of memory we can allocate for transfers */ +-static unsigned usbfs_memory_mb = 16; ++static u32 usbfs_memory_mb = 16; + 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 atomic_t usbfs_memory_usage; /* Total memory currently allocated */ ++static atomic64_t usbfs_memory_usage; /* Total memory currently allocated */ + + /* Check whether it's okay to allocate more memory for a transfer */ +-static int usbfs_increase_memory_usage(unsigned amount) ++static int usbfs_increase_memory_usage(u64 amount) + { +- unsigned lim; ++ u64 lim; + +- /* +- * Convert usbfs_memory_mb to bytes, avoiding overflows. +- * 0 means use the hard limit (effectively unlimited). +- */ + lim = ACCESS_ONCE(usbfs_memory_mb); +- if (lim == 0 || lim > (USBFS_XFER_MAX >> 20)) +- lim = USBFS_XFER_MAX; +- else +- lim <<= 20; ++ lim <<= 20; + +- atomic_add(amount, &usbfs_memory_usage); +- if (atomic_read(&usbfs_memory_usage) <= lim) +- return 0; +- atomic_sub(amount, &usbfs_memory_usage); +- return -ENOMEM; ++ atomic64_add(amount, &usbfs_memory_usage); ++ ++ if (lim > 0 && atomic64_read(&usbfs_memory_usage) > lim) { ++ atomic64_sub(amount, &usbfs_memory_usage); ++ return -ENOMEM; ++ } ++ ++ return 0; + } + + /* Memory for a transfer is being deallocated */ +-static void usbfs_decrease_memory_usage(unsigned amount) ++static void usbfs_decrease_memory_usage(u64 amount) + { +- atomic_sub(amount, &usbfs_memory_usage); ++ atomic64_sub(amount, &usbfs_memory_usage); + } + + static int connected(struct usb_dev_state *ps) +@@ -1077,7 +1070,7 @@ static int proc_bulk(struct usb_dev_stat + if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) + return -EINVAL; + len1 = bulk.len; +- if (len1 >= USBFS_XFER_MAX) ++ if (len1 >= (INT_MAX - sizeof(struct urb))) + return -EINVAL; + ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); + if (ret) +@@ -1420,10 +1413,6 @@ static int proc_do_submiturb(struct usb_ + return -EINVAL; + } + +- if (uurb->buffer_length >= USBFS_XFER_MAX) { +- ret = -EINVAL; +- goto error; +- } + if (uurb->buffer_length > 0 && + !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, + uurb->buffer, uurb->buffer_length)) { diff --git a/queue-3.18/usb-usbfs-filter-flags-passed-in-from-user-space.patch b/queue-3.18/usb-usbfs-filter-flags-passed-in-from-user-space.patch new file mode 100644 index 00000000000..9d2d1327eea --- /dev/null +++ b/queue-3.18/usb-usbfs-filter-flags-passed-in-from-user-space.patch @@ -0,0 +1,47 @@ +From 446f666da9f019ce2ffd03800995487e79a91462 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 23 Nov 2017 16:39:52 +0100 +Subject: USB: usbfs: Filter flags passed in from user space + +From: Oliver Neukum + +commit 446f666da9f019ce2ffd03800995487e79a91462 upstream. + +USBDEVFS_URB_ISO_ASAP must be accepted only for ISO endpoints. +Improve sanity checking. + +Reported-by: Andrey Konovalov +Signed-off-by: Oliver Neukum +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/devio.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -1290,14 +1290,18 @@ static int proc_do_submiturb(struct usb_ + int number_of_packets = 0; + unsigned int stream_id = 0; + void *buf; +- +- if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | +- USBDEVFS_URB_SHORT_NOT_OK | ++ unsigned long mask = USBDEVFS_URB_SHORT_NOT_OK | + USBDEVFS_URB_BULK_CONTINUATION | + USBDEVFS_URB_NO_FSBR | + USBDEVFS_URB_ZERO_PACKET | +- USBDEVFS_URB_NO_INTERRUPT)) +- return -EINVAL; ++ USBDEVFS_URB_NO_INTERRUPT; ++ /* USBDEVFS_URB_ISO_ASAP is a special case */ ++ if (uurb->type == USBDEVFS_URB_TYPE_ISO) ++ mask |= USBDEVFS_URB_ISO_ASAP; ++ ++ if (uurb->flags & ~mask) ++ return -EINVAL; ++ + if ((unsigned int)uurb->buffer_length >= USBFS_XFER_MAX) + return -EINVAL; + if (uurb->buffer_length > 0 && !uurb->buffer)