]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.27.46/usb-fix-usbfs-regression.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.27.46 / usb-fix-usbfs-regression.patch
CommitLineData
bbc77fb3
GKH
1From 7152b592593b9d48b33f8997b1dfd6df9143f7ec Mon Sep 17 00:00:00 2001
2From: Alan Stern <stern@rowland.harvard.edu>
3Date: Sat, 6 Mar 2010 15:04:03 -0500
4Subject: USB: fix usbfs regression
5
6From: Alan Stern <stern@rowland.harvard.edu>
7
8commit 7152b592593b9d48b33f8997b1dfd6df9143f7ec upstream.
9
10This patch (as1352) fixes a bug in the way isochronous input data is
11returned to userspace for usbfs transfers. The entire buffer must be
12copied, not just the first actual_length bytes, because the individual
13packets will be discontiguous if any of them are short.
14
15Reported-by: Markus Rechberger <mrechberger@gmail.com>
16Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
17Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
18
19---
20 drivers/usb/core/devio.c | 17 ++++++++++++++---
21 1 file changed, 14 insertions(+), 3 deletions(-)
22
23--- a/drivers/usb/core/devio.c
24+++ b/drivers/usb/core/devio.c
25@@ -1123,6 +1123,13 @@ static int proc_do_submiturb(struct dev_
26 free_async(as);
27 return -ENOMEM;
28 }
29+ /* Isochronous input data may end up being discontiguous
30+ * if some of the packets are short. Clear the buffer so
31+ * that the gaps don't leak kernel data to userspace.
32+ */
33+ if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
34+ memset(as->urb->transfer_buffer, 0,
35+ uurb->buffer_length);
36 }
37 as->urb->dev = ps->dev;
38 as->urb->pipe = (uurb->type << 30) |
39@@ -1224,10 +1231,14 @@ static int processcompl(struct async *as
40 void __user *addr = as->userurb;
41 unsigned int i;
42
43- if (as->userbuffer && urb->actual_length)
44- if (copy_to_user(as->userbuffer, urb->transfer_buffer,
45- urb->actual_length))
46+ if (as->userbuffer && urb->actual_length) {
47+ if (urb->number_of_packets > 0) /* Isochronous */
48+ i = urb->transfer_buffer_length;
49+ else /* Non-Isoc */
50+ i = urb->actual_length;
51+ if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
52 goto err_out;
53+ }
54 if (put_user(as->status, &userurb->status))
55 goto err_out;
56 if (put_user(urb->actual_length, &userurb->actual_length))