]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.33.2/usb-fix-usbfs-regression.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.33.2 / usb-fix-usbfs-regression.patch
1 From 7152b592593b9d48b33f8997b1dfd6df9143f7ec Mon Sep 17 00:00:00 2001
2 From: Alan Stern <stern@rowland.harvard.edu>
3 Date: Sat, 6 Mar 2010 15:04:03 -0500
4 Subject: USB: fix usbfs regression
5
6 From: Alan Stern <stern@rowland.harvard.edu>
7
8 commit 7152b592593b9d48b33f8997b1dfd6df9143f7ec upstream.
9
10 This patch (as1352) fixes a bug in the way isochronous input data is
11 returned to userspace for usbfs transfers. The entire buffer must be
12 copied, not just the first actual_length bytes, because the individual
13 packets will be discontiguous if any of them are short.
14
15 Reported-by: Markus Rechberger <mrechberger@gmail.com>
16 Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
17 Signed-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 @@ -1176,6 +1176,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 @@ -1312,10 +1319,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))