Date: Wed, 17 Feb 2010 11:29:46 +0100 From: Marcus Meissner <meissner@...e.de> To: OSS Security List <oss-security@...ts.openwall.com> Subject: CVE request: kernel information leak via userspace USB interface Hi, While programming a USB device using libusb I found that a usb read from the device returned data it should not. Looking into the code showed that in USB commands that fail during device communication (with e.g. USB timeouts) return the transfer buffer unmodified back to userspace. This transfer buffer is allocated with kmalloc before and not initialized, so userspace gets to see recently freed data of the kernel. Greg, Linus and Alan produced a fix that was commited to mainline tonight: commit d4a4683ca054ed9917dfc9e3ff0f7ecf74ad90d6 (full commit attached to the mail) The issue seems to have been in the kernel for the whole 2.6 series (oldest kernel I looked at was 2.6.5, I tested down to 2.6.25). Access to USB userspace devices either requires root access or desktop user access via udev/hal ACLs on non-mass-storage Digital Cameras or Media Players. (So the desktop user needs to plugin such a ACL getting device before being able to read the memory). Ciao, Marcus commit d4a4683ca054ed9917dfc9e3ff0f7ecf74ad90d6 Author: Greg KH <greg@...ah.com> Date: Mon Feb 15 09:37:46 2010 -0800 USB: usbfs: only copy the actual data received We need to only copy the data received by the device to userspace, not the whole kernel buffer, which can contain "stale" data. Thanks to Marcus Meissner for pointing this out and testing the fix. Reported-by: Marcus Meissner <meissner@...e.de> Tested-by: Marcus Meissner <meissner@...e.de> Cc: Alan Stern <stern@...land.harvard.edu> Cc: Linus Torvalds <torvalds@...ux-foundation.org> Cc: stable <stable@...nel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de> diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6e8bcdf..ca948bb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1312,9 +1312,9 @@ static int processcompl(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) + if (as->userbuffer && urb->actual_length) if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + urb->actual_length)) goto err_out; if (put_user(as->status, &userurb->status)) goto err_out; @@ -1475,9 +1475,9 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) + if (as->userbuffer && urb->actual_length) if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + urb->actual_length)) return -EFAULT; if (put_user(as->status, &userurb->status)) return -EFAULT;
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Powered by Openwall GNU/*/Linux - Powered by OpenVZ