]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.27.46/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.27.46 / usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch
1 From ddeee0b2eec2a51b0712b04de4b39e7bec892a53 Mon Sep 17 00:00:00 2001
2 From: Linus Torvalds <torvalds@linux-foundation.org>
3 Date: Tue, 16 Feb 2010 12:35:07 -0800
4 Subject: USB: usbfs: properly clean up the as structure on error paths
5
6 From: Linus Torvalds <torvalds@linux-foundation.org>
7
8 commit ddeee0b2eec2a51b0712b04de4b39e7bec892a53 upstream.
9
10 I notice that the processcompl_compat() function seems to be leaking the
11 'struct async *as' in the error paths.
12
13 I think that the calling convention is fundamentally buggered. The
14 caller is the one that did the "reap_as()" to get the as thing, the
15 caller should be the one to free it too.
16
17 Freeing it in the caller also means that it very clearly always gets
18 freed, and avoids the need for any "free in the error case too".
19
20 From: Linus Torvalds <torvalds@linux-foundation.org>
21 Cc: Alan Stern <stern@rowland.harvard.edu>
22 Cc: Marcus Meissner <meissner@suse.de>
23 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
24
25 ---
26 drivers/usb/core/devio.c | 40 ++++++++++++++++++++++++++--------------
27 1 file changed, 26 insertions(+), 14 deletions(-)
28
29 --- a/drivers/usb/core/devio.c
30 +++ b/drivers/usb/core/devio.c
31 @@ -1246,14 +1246,11 @@ static int processcompl(struct async *as
32 }
33 }
34
35 - free_async(as);
36 -
37 if (put_user(addr, (void __user * __user *)arg))
38 return -EFAULT;
39 return 0;
40
41 err_out:
42 - free_async(as);
43 return -EFAULT;
44 }
45
46 @@ -1283,8 +1280,11 @@ static struct async *reap_as(struct dev_
47 static int proc_reapurb(struct dev_state *ps, void __user *arg)
48 {
49 struct async *as = reap_as(ps);
50 - if (as)
51 - return processcompl(as, (void __user * __user *)arg);
52 + if (as) {
53 + int retval = processcompl(as, (void __user * __user *)arg);
54 + free_async(as);
55 + return retval;
56 + }
57 if (signal_pending(current))
58 return -EINTR;
59 return -EIO;
60 @@ -1292,11 +1292,16 @@ static int proc_reapurb(struct dev_state
61
62 static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
63 {
64 + int retval;
65 struct async *as;
66
67 - if (!(as = async_getcompleted(ps)))
68 - return -EAGAIN;
69 - return processcompl(as, (void __user * __user *)arg);
70 + as = async_getcompleted(ps);
71 + retval = -EAGAIN;
72 + if (as) {
73 + retval = processcompl(as, (void __user * __user *)arg);
74 + free_async(as);
75 + }
76 + return retval;
77 }
78
79 #ifdef CONFIG_COMPAT
80 @@ -1369,7 +1374,6 @@ static int processcompl_compat(struct as
81 }
82 }
83
84 - free_async(as);
85 if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
86 return -EFAULT;
87 return 0;
88 @@ -1378,8 +1382,11 @@ static int processcompl_compat(struct as
89 static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
90 {
91 struct async *as = reap_as(ps);
92 - if (as)
93 - return processcompl_compat(as, (void __user * __user *)arg);
94 + if (as) {
95 + int retval = processcompl_compat(as, (void __user * __user *)arg);
96 + free_async(as);
97 + return retval;
98 + }
99 if (signal_pending(current))
100 return -EINTR;
101 return -EIO;
102 @@ -1387,11 +1394,16 @@ static int proc_reapurb_compat(struct de
103
104 static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
105 {
106 + int retval;
107 struct async *as;
108
109 - if (!(as = async_getcompleted(ps)))
110 - return -EAGAIN;
111 - return processcompl_compat(as, (void __user * __user *)arg);
112 + retval = -EAGAIN;
113 + as = async_getcompleted(ps);
114 + if (as) {
115 + retval = processcompl_compat(as, (void __user * __user *)arg);
116 + free_async(as);
117 + }
118 + return retval;
119 }
120
121 #endif