aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-02-16 14:31:30 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2010-02-16 14:31:30 -0800
commit8ddf33958e750354317a0cc6ad396a017fb7ce51 (patch)
tree8c046df611aeb8e7927e0577578d6c1e0db1116a
parent4aec9b12892864b7cc35454d02b7f0f5b552c966 (diff)
downloadpatches-8ddf33958e750354317a0cc6ad396a017fb7ce51.tar.gz
another usbfs patch
-rw-r--r--series1
-rw-r--r--usb.current/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch123
2 files changed, 124 insertions, 0 deletions
diff --git a/series b/series
index 7e2e68134eea11..926814a113a40c 100644
--- a/series
+++ b/series
@@ -21,6 +21,7 @@ tty.current/serial-8250-add-serial-transmitter-fully-empty-test.patch
# USB patches for 2.6.33
#################################
usb.current/usb-usbfs-only-copy-the-actual-data-received.patch
+usb.current/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch
usb.current/usb-ftdi_sio-new-device-id-for-papouch-ad4usb.patch
usb.current/usb-storage-remove-unneeded-sc-pr-from-unusual_devs.h.patch
usb.current/usb-ftdi_sio-add-device-ids-several-elv-one-mindstorms-nxt.patch
diff --git a/usb.current/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch b/usb.current/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch
new file mode 100644
index 00000000000000..9795c76c7171b1
--- /dev/null
+++ b/usb.current/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch
@@ -0,0 +1,123 @@
+From torvalds@linux-foundation.org Tue Feb 16 12:35:42 2010
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Tue, 16 Feb 2010 12:35:07 -0800 (PST)
+Subject: USB: usbfs: properly clean up the as structure on error paths
+To: gregkh@suse.de
+Cc: greg@kroah.com, meissner@suse.de, stable@kernel.org, stern@rowland.harvard.edu
+Message-ID: <alpine.LFD.2.00.1002161225170.4141@localhost.localdomain>
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+I notice that the processcompl_compat() function seems to be leaking the
+'struct async *as' in the error paths.
+
+I think that the calling convention is fundamentally buggered. The
+caller is the one that did the "reap_as()" to get the as thing, the
+caller should be the one to free it too.
+
+Freeing it in the caller also means that it very clearly always gets
+freed, and avoids the need for any "free in the error case too".
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Marcus Meissner <meissner@suse.de>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/devio.c | 40 ++++++++++++++++++++++++++--------------
+ 1 file changed, 26 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1334,14 +1334,11 @@ static int processcompl(struct async *as
+ }
+ }
+
+- free_async(as);
+-
+ if (put_user(addr, (void __user * __user *)arg))
+ return -EFAULT;
+ return 0;
+
+ err_out:
+- free_async(as);
+ return -EFAULT;
+ }
+
+@@ -1371,8 +1368,11 @@ static struct async *reap_as(struct dev_
+ static int proc_reapurb(struct dev_state *ps, void __user *arg)
+ {
+ struct async *as = reap_as(ps);
+- if (as)
+- return processcompl(as, (void __user * __user *)arg);
++ if (as) {
++ int retval = processcompl(as, (void __user * __user *)arg);
++ free_async(as);
++ return retval;
++ }
+ if (signal_pending(current))
+ return -EINTR;
+ return -EIO;
+@@ -1380,11 +1380,16 @@ static int proc_reapurb(struct dev_state
+
+ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
+ {
++ int retval;
+ struct async *as;
+
+- if (!(as = async_getcompleted(ps)))
+- return -EAGAIN;
+- return processcompl(as, (void __user * __user *)arg);
++ as = async_getcompleted(ps);
++ retval = -EAGAIN;
++ if (as) {
++ retval = processcompl(as, (void __user * __user *)arg);
++ free_async(as);
++ }
++ return retval;
+ }
+
+ #ifdef CONFIG_COMPAT
+@@ -1497,7 +1502,6 @@ static int processcompl_compat(struct as
+ }
+ }
+
+- free_async(as);
+ if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
+ return -EFAULT;
+ return 0;
+@@ -1506,8 +1510,11 @@ static int processcompl_compat(struct as
+ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
+ {
+ struct async *as = reap_as(ps);
+- if (as)
+- return processcompl_compat(as, (void __user * __user *)arg);
++ if (as) {
++ int retval = processcompl_compat(as, (void __user * __user *)arg);
++ free_async(as);
++ return retval;
++ }
+ if (signal_pending(current))
+ return -EINTR;
+ return -EIO;
+@@ -1515,11 +1522,16 @@ static int proc_reapurb_compat(struct de
+
+ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
+ {
++ int retval;
+ struct async *as;
+
+- if (!(as = async_getcompleted(ps)))
+- return -EAGAIN;
+- return processcompl_compat(as, (void __user * __user *)arg);
++ retval = -EAGAIN;
++ as = async_getcompleted(ps);
++ if (as) {
++ retval = processcompl_compat(as, (void __user * __user *)arg);
++ free_async(as);
++ }
++ return retval;
+ }
+
+