Message ID | 4BB0ADFE.6010403@canonical.com |
---|---|
State | Accepted |
Headers | show |
On Mon, Mar 29, 2010 at 03:41:18PM +0200, Stefan Bader wrote: > As this patch is upstream and has been cc'ed to stable too, I would ACK to > cherry-pick the upstream patch (attached for simplicity) > > Stefan I concur: Acked-by: Andy Whitcroft <apw@canonical.com> > From 7152b592593b9d48b33f8997b1dfd6df9143f7ec Mon Sep 17 00:00:00 2001 > From: Alan Stern <stern@rowland.harvard.edu> > Date: Sat, 6 Mar 2010 15:04:03 -0500 > Subject: [PATCH] USB: fix usbfs regression > > This patch (as1352) fixes a bug in the way isochronous input data is > returned to userspace for usbfs transfers. The entire buffer must be > copied, not just the first actual_length bytes, because the individual > packets will be discontiguous if any of them are short. > > Reported-by: Markus Rechberger <mrechberger@gmail.com> > Signed-off-by: Alan Stern <stern@rowland.harvard.edu> > CC: stable <stable@kernel.org> > Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> > --- > drivers/usb/core/devio.c | 17 ++++++++++++++--- > 1 files changed, 14 insertions(+), 3 deletions(-) > > diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c > index e909ff7..3466fdc 100644 > --- a/drivers/usb/core/devio.c > +++ b/drivers/usb/core/devio.c > @@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, > free_async(as); > return -ENOMEM; > } > + /* Isochronous input data may end up being discontiguous > + * if some of the packets are short. Clear the buffer so > + * that the gaps don't leak kernel data to userspace. > + */ > + if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO) > + memset(as->urb->transfer_buffer, 0, > + uurb->buffer_length); > } > as->urb->dev = ps->dev; > as->urb->pipe = (uurb->type << 30) | > @@ -1345,10 +1352,14 @@ static int processcompl(struct async *as, void __user * __user *arg) > void __user *addr = as->userurb; > unsigned int i; > > - if (as->userbuffer && urb->actual_length) > - if (copy_to_user(as->userbuffer, urb->transfer_buffer, > - urb->actual_length)) > + if (as->userbuffer && urb->actual_length) { > + if (urb->number_of_packets > 0) /* Isochronous */ > + i = urb->transfer_buffer_length; > + else /* Non-Isoc */ > + i = urb->actual_length; > + if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) > goto err_out; > + } > if (put_user(as->status, &userurb->status)) > goto err_out; > if (put_user(urb->actual_length, &userurb->actual_length)) -apw
Applied to Lucid. -apw
On Tue, Mar 30, 2010 at 6:55 PM, Andy Whitcroft <apw@canonical.com> wrote: > Applied to Lucid. > great thanks Markus
From 7152b592593b9d48b33f8997b1dfd6df9143f7ec Mon Sep 17 00:00:00 2001 From: Alan Stern <stern@rowland.harvard.edu> Date: Sat, 6 Mar 2010 15:04:03 -0500 Subject: [PATCH] USB: fix usbfs regression This patch (as1352) fixes a bug in the way isochronous input data is returned to userspace for usbfs transfers. The entire buffer must be copied, not just the first actual_length bytes, because the individual packets will be discontiguous if any of them are short. Reported-by: Markus Rechberger <mrechberger@gmail.com> Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/usb/core/devio.c | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e909ff7..3466fdc 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, free_async(as); return -ENOMEM; } + /* Isochronous input data may end up being discontiguous + * if some of the packets are short. Clear the buffer so + * that the gaps don't leak kernel data to userspace. + */ + if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO) + memset(as->urb->transfer_buffer, 0, + uurb->buffer_length); } as->urb->dev = ps->dev; as->urb->pipe = (uurb->type << 30) | @@ -1345,10 +1352,14 @@ static int processcompl(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer && urb->actual_length) - if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->actual_length)) + if (as->userbuffer && urb->actual_length) { + if (urb->number_of_packets > 0) /* Isochronous */ + i = urb->transfer_buffer_length; + else /* Non-Isoc */ + i = urb->actual_length; + if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) goto err_out; + } if (put_user(as->status, &userurb->status)) goto err_out; if (put_user(urb->actual_length, &userurb->actual_length)) -- 1.6.3.3