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>
This commit is contained in:
		
							parent
							
								
									aeec26d348
								
							
						
					
					
						commit
						c4c0e236be
					
				
							
								
								
									
										12
									
								
								usb-linux.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								usb-linux.c
									
									
									
									
									
								
							@ -115,7 +115,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 {
 | 
			
		||||
@ -552,6 +552,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.
 | 
			
		||||
@ -580,6 +581,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();
 | 
			
		||||
    aurb->hdev   = s;
 | 
			
		||||
    aurb->packet = p;
 | 
			
		||||
@ -596,7 +604,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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user