From patchwork Sun Feb 26 16:09:21 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alon Levy X-Patchwork-Id: 143099 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2DF39B6FA2 for ; Mon, 27 Feb 2012 03:27:43 +1100 (EST) Received: from localhost ([::1]:41713 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S1gfP-0001C5-Uf for incoming@patchwork.ozlabs.org; Sun, 26 Feb 2012 11:09:43 -0500 Received: from eggs.gnu.org ([208.118.235.92]:59388) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S1gfD-0001BE-0Z for qemu-devel@nongnu.org; Sun, 26 Feb 2012 11:09:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S1gfB-0000Ea-MV for qemu-devel@nongnu.org; Sun, 26 Feb 2012 11:09:30 -0500 Received: from mx1.redhat.com ([209.132.183.28]:13466) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S1gfB-0000EQ-ET for qemu-devel@nongnu.org; Sun, 26 Feb 2012 11:09:29 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1QG9RUO027288 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 26 Feb 2012 11:09:27 -0500 Received: from garlic.tlv.redhat.com (spice-ovirt.tlv.redhat.com [10.35.4.71]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q1QG9PeM018331; Sun, 26 Feb 2012 11:09:26 -0500 From: Alon Levy To: qemu-devel@nongnu.org Date: Sun, 26 Feb 2012 17:09:21 +0100 Message-Id: <1330272564-21692-1-git-send-email-alevy@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: kraxel@redhat.com Subject: [Qemu-devel] [PATCH 1/4] usb-desc: fix user trigerrable segfaults (!config) 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 Check for dev->config being NULL in two places: USB_REQ_GET_CONFIGURATION and USB_REQ_GET_STATUS. The behavior of USB_REQ_GET_STATUS is unspecified in the Default state, that corresponds to dev->config being NULL (it defaults to NULL and is reset whenever a SET_CONFIGURATION with value 0, or attachment). I implemented it to correspond with the state before ed5a83ddd8c1d8ec7b1015315530cf29949e7c48, the commit moving SET_STATUS to usb-desc; if dev->config is not set we return whatever is in the first configuration. The behavior of USB_REQ_GET_CONFIGURATION is also undefined before any SET_CONFIGURATION, but here we just return 0 (same as specified for the Address state). A win7 guest failed to initialize the device before this patch, segfaulting when GET_STATUS was called with dev->config == NULL. With this patch the passthrough device still doesn't work but the failure is unrelated. Signed-off-by: Alon Levy --- hw/usb-desc.c | 20 +++++++++++++++++--- 1 files changed, 17 insertions(+), 3 deletions(-) diff --git a/hw/usb-desc.c b/hw/usb-desc.c index 3c3ed6a..ccf85ad 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -536,7 +536,11 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: - data[0] = dev->config->bConfigurationValue; + /* + * 9.4.2: 0 should be returned if the device is unconfigured, otherwise + * the non zero value of bConfigurationValue. + */ + data[0] = dev->config ? dev->config->bConfigurationValue : 0; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: @@ -544,9 +548,18 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, trace_usb_set_config(dev->addr, value, ret); break; - case DeviceRequest | USB_REQ_GET_STATUS: + case DeviceRequest | USB_REQ_GET_STATUS: { + const USBDescConfig *config = dev->config ? + dev->config : &dev->device->confs[0]; + data[0] = 0; - if (dev->config->bmAttributes & 0x40) { + /* + * Default state: Device behavior when this request is received while + * the device is in the Default state is not specified. + * We return the same value that a configured device would return if + * it used the first configuration. + */ + if (config->bmAttributes & 0x40) { data[0] |= 1 << USB_DEVICE_SELF_POWERED; } if (dev->remote_wakeup) { @@ -555,6 +568,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, data[1] = 0x00; ret = 2; break; + } case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 0;