diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-02-16 14:31:30 -0800 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-02-16 14:31:30 -0800 |
| commit | 8ddf33958e750354317a0cc6ad396a017fb7ce51 (patch) | |
| tree | 8c046df611aeb8e7927e0577578d6c1e0db1116a | |
| parent | 4aec9b12892864b7cc35454d02b7f0f5b552c966 (diff) | |
| download | patches-8ddf33958e750354317a0cc6ad396a017fb7ce51.tar.gz | |
another usbfs patch
| -rw-r--r-- | series | 1 | ||||
| -rw-r--r-- | usb.current/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch | 123 |
2 files changed, 124 insertions, 0 deletions
@@ -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; + } + + |
