From ee741cdd6bc6f3b69dbde7950cb577f812ac0eba Mon Sep 17 00:00:00 2001 From: Eduardo Habkost <ehabkost@redhat.com> Date: Thu, 4 Feb 2010 12:41:47 -0200 Subject: [PATCH] CVE-2010-0297: usb-linux.c: fix buffer overflow RH-Author: Eduardo Habkost <ehabkost@redhat.com> Message-id: <20100204124147.GY22381@blackpad.lan.raisama.net> Patchwork-id: 6917 O-Subject: [PATCH KVM 5.5 5.4.z] CVE-2010-0297: usb-linux.c: fix buffer overflow Bugzilla: 560770 RH-Acked-by: Juan Quintela <quintela@redhat.com> RH-Acked-by: Gleb Natapov <gleb@redhat.com> RH-Acked-by: Don Dutile <ddutile@redhat.com> CVE: CVE-2010-0297 Bugzilla (5.5): https://bugzilla.redhat.com/show_bug.cgi?id=560770 Bugzilla (5.4.z): https://bugzilla.redhat.com/show_bug.cgi?id=560769 Backport of upstream commit: commit c4c0e236beabb9de5ff472f77aeb811ec5484615 Author: Jim Paris <jim@jtan.com> Date: Mon Aug 24 14:56:12 2009 -0400 usb-linux.c: fix buffer overflow In usb-linux.c:usb_host_handle_control, we pass a 1024-byte buffer and length to the kernel. However, the length was provided by the caller of dev->handle_packet, and is not checked, so the kernel might provide too much data and overflow our buffer. For example, hw/usb-uhci.c could set the length to 2047. hw/usb-ohci.c looks like it might go up to 4096 or 8192. This causes a qemu crash, as reported here: http://www.mail-archive.com/kvm@vger.kernel.org/msg18447.html This patch increases the usb-linux.c buffer size to 2048 to fix the specific device reported, and adds a check to avoid the overflow in any case. Signed-off-by: Jim Paris <jim@jtan.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Please ACK. --- qemu/usb-linux.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- qemu/usb-linux.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/qemu/usb-linux.c b/qemu/usb-linux.c index bc7da67..7b0e729 100644 --- a/qemu/usb-linux.c +++ b/qemu/usb-linux.c @@ -119,7 +119,7 @@ struct ctrl_struct { uint16_t offset; uint8_t state; struct usb_ctrlrequest req; - uint8_t buffer[1024]; + uint8_t buffer[2048]; }; typedef struct USBHostDevice { @@ -560,6 +560,7 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p) struct usbdevfs_urb *urb; AsyncURB *aurb; int ret, value, index; + int buffer_len; /* * Process certain standard device requests. @@ -588,6 +589,13 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p) /* The rest are asynchronous */ + buffer_len = 8 + s->ctrl.len; + if (buffer_len > sizeof(s->ctrl.buffer)) { + fprintf(stderr, "husb: ctrl buffer too small (%u > %lu)\n", + buffer_len, sizeof(s->ctrl.buffer)); + return USB_RET_STALL; + } + aurb = async_alloc(); if (!aurb) { dprintf("husb: async malloc failed\n"); @@ -608,7 +616,7 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p) urb->endpoint = p->devep; urb->buffer = &s->ctrl.req; - urb->buffer_length = 8 + s->ctrl.len; + urb->buffer_length = buffer_len; urb->usercontext = s; -- 1.6.3.rc4.29.g8146