From patchwork Mon Apr 2 11:50:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Stezenbach X-Patchwork-Id: 150197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 901C4B6FAA for ; Tue, 3 Apr 2012 04:19:47 +1000 (EST) Received: from localhost ([::1]:54712 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SElqz-0000Yb-5O for incoming@patchwork.ozlabs.org; Mon, 02 Apr 2012 14:19:45 -0400 Received: from eggs.gnu.org ([208.118.235.92]:58520) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SEfmc-0004b0-3D for qemu-devel@nongnu.org; Mon, 02 Apr 2012 07:50:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SEfmV-0008Nm-M9 for qemu-devel@nongnu.org; Mon, 02 Apr 2012 07:50:49 -0400 Received: from bar.sig21.net ([80.81.252.164]:60163) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SEfmV-0008Nc-Di for qemu-devel@nongnu.org; Mon, 02 Apr 2012 07:50:43 -0400 Received: from p5099b351.dip0.t-ipconnect.de ([80.153.179.81] helo=zzz.local) by bar.sig21.net with esmtpsa (TLS1.0:RSA_ARCFOUR_SHA1:16) (Exim 4.69) (envelope-from ) id 1SEfmN-0007Sz-NH; Mon, 02 Apr 2012 13:50:39 +0200 Received: from js by zzz.local with local (Exim 4.77) (envelope-from ) id 1SEfmN-0005xh-2r; Mon, 02 Apr 2012 13:50:35 +0200 Date: Mon, 2 Apr 2012 13:50:35 +0200 From: Johannes Stezenbach To: Gerd Hoffmann Message-ID: <20120402115034.GB22763@sig21.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 1) X-Received-From: 80.81.252.164 X-Mailman-Approved-At: Mon, 02 Apr 2012 14:19:35 -0400 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH] usb-host: fix handling of zero-length packets X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Zero-length packets are valid but currently cause qemu to crash: Program terminated with signal 11, Segmentation fault. #0 0xf7589f26 in usb_host_handle_data (dev=0xf8fd4820, p=0xf91606b0) at qemu/hw/usb/host-linux.c:886 886 prem = p->iov.iov[v].iov_len; (gdb) bt #0 0xf7589f26 in usb_host_handle_data (dev=0xf8fd4820, p=0xf91606b0) at qemu/hw/usb/host-linux.c:886 #1 0xf757ecf8 in usb_device_handle_data (dev=0xf8fd4820, p=0xf91606b0) at qemu/hw/usb/bus.c:135 #2 0xf75805cc in usb_process_one (p=0xf91606b0) at qemu/hw/usb/core.c:365 #3 0xf7580c9f in usb_handle_packet (dev=0xf8fd4820, p=0xf91606b0) at qemu/hw/usb/core.c:385 #4 0xf74f9a0b in ehci_execute (q=0xf9160640) at qemu/hw/usb/hcd-ehci.c:1393 ... (gdb) p p->iov $3 = {iov = 0x0, niov = 0, nalloc = 0, size = 0} (gdb) f 4 #4 0xf74f9a0b in ehci_execute (q=0xf9160640) at /home/js/src/other/qemu/hw/usb/hcd-ehci.c:1393 1393 ret = usb_handle_packet(dev, &q->packet); (gdb) p q->sgl $4 = {sg = 0xf9160410, nsg = 0, nalloc = 5, size = 0} Signed-off-by: Johannes Stezenbach --- Note that I didn't do sufficient testing. I have a proprietary firmware update tool which does one large bulk transfer with a size which is a multiple of 512. With qemu and kvm from Debian sid (qemu-1.0.1+dfsg-1, kvm-1.0+dfsg-9) the zero-length packet at the end causes timeout. qemu from git master or kraxel/usb.45 crashes. With this patch my firmware update worked. hw/usb/host-linux.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index a382f0a..35106cd 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -883,16 +883,15 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) } v = 0; - prem = p->iov.iov[v].iov_len; - pbuf = p->iov.iov[v].iov_base; + prem = 0; + pbuf = 0; rem = p->iov.size; - while (rem) { - if (prem == 0) { - v++; + for (;;) { + if (prem == 0 && rem > 0) { assert(v < p->iov.niov); prem = p->iov.iov[v].iov_len; pbuf = p->iov.iov[v].iov_base; - assert(prem <= rem); + v++; } aurb = async_alloc(s); aurb->packet = p; @@ -937,6 +936,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) return USB_RET_STALL; } } + if (rem == 0) + break; } return USB_RET_ASYNC;