Received: by 2002:a25:31c3:0:0:0:0:0 with SMTP id x186csp4482468ybx; Mon, 4 Nov 2019 14:10:04 -0800 (PST) X-Google-Smtp-Source: APXvYqxURmTgsNAXKC0z7lwwDA9uKw+KCEXYKmp6K2uiFbiqCGg9osa576AoqFDnNCiQdGg+WuuK X-Received: by 2002:a17:906:7e10:: with SMTP id e16mr26373696ejr.84.1572905404778; Mon, 04 Nov 2019 14:10:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1572905404; cv=none; d=google.com; s=arc-20160816; b=HPNWh5gnVCXB4CulliAeOZVVZInS+nrADj7ecKyH/Lne38CabvrJmg3xQtQttZBRh2 TKEvFNNqa+R+/vfKUjk6Bzv3CxAzgQ0alj0y0YdkStUCuZNKGfw7stBbJzvsNgF0jiuf fAAjtASP6A7Ywk8JtsORW+XDD56Wp1NgNJwvewLtk2MDksnnaVSrRT0lpY46mOpniRqs +iwZ/j59XRiPaEK+HdCHMxfI2lnb4x0//UbYVSL1hWx6V51kgd1gDONaQ8A1lDcX9k9s 0T6kcUaeOhPiL/L3JGKYk2PDFBukN/8AkRno0IgklUaTJ7BB/DWiLnQOnJNC0qjpk2LX 0E7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=SWTk1FmE9SsOlNqF6dcvXAZTltlshWvwD4imYGs5Jds=; b=BlDUNMQLwkR42Q4olWl0oWZf4gRQDr5xgc64BXpZga5e/O8P6//lhdBjF9BB8iyg7i KaaNtf8TzwzVmDQtO0ouR8pao/TXqLoimseEnBCE2wnoCaQ3awe7UjInSuu1mGbIppy6 sUlBI+s9fcRbsptPc8+eE1fewnitNR0VW2pLkFtfzIk/ji+zF3HCNv2+OLmDaWVvSOF7 9QYO6PPwsL+H7pikQjjSVw5tYJbwIpl+x28k01p+kF8r5Zd3fKdBRJaWo/lY0RjbqpKG wPJw6S0vA4CQRug7030VGE/A04pk+nm89xUdms0qZzCVdIfpZ54rEgtJnnr0ha0d/xZs XqsA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=CLMiHNNd; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y51si8417534edb.29.2019.11.04.14.09.41; Mon, 04 Nov 2019 14:10:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=CLMiHNNd; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389947AbfKDWJE (ORCPT + 99 others); Mon, 4 Nov 2019 17:09:04 -0500 Received: from mail.kernel.org ([198.145.29.99]:42036 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390334AbfKDWJC (ORCPT ); Mon, 4 Nov 2019 17:09:02 -0500 Received: from localhost (6.204-14-84.ripe.coltfrance.com [84.14.204.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 18B40214D8; Mon, 4 Nov 2019 22:09:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1572905341; bh=pFFbdePxjjhPoguf/Ha0ult80u4T1XctSKWMf6QgOfQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CLMiHNNdsOuIJtDrNVs+mHqfUiH9rO00j/+zWPXKeXf1r4QrSDvUZoguKos2u1fPa rSmqYyqfxmcRA96/VFSGfzde5xu9K6BcueBEuTUuzaNmk6LGkJjhDfPKmDei5S3FgP UuXZverWcmU8YaSzZT18tR+C0HRssKrxQDhlYgj8= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Johan Hovold , Mathias Nyman Subject: [PATCH 5.3 112/163] xhci: Fix use-after-free regression in xhci clear hub TT implementation Date: Mon, 4 Nov 2019 22:45:02 +0100 Message-Id: <20191104212148.359193024@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191104212140.046021995@linuxfoundation.org> References: <20191104212140.046021995@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mathias Nyman commit 18b74067ac78a2dea65783314c13df98a53d071c upstream. commit ef513be0a905 ("usb: xhci: Add Clear_TT_Buffer") schedules work to clear TT buffer, but causes a use-after-free regression at the same time Make sure hub_tt_work finishes before endpoint is disabled, otherwise the work will dereference already freed endpoint and device related pointers. This was triggered when usb core failed to read the configuration descriptor of a FS/LS device during enumeration. xhci driver queued clear_tt_work while usb core freed and reallocated a new device for the next enumeration attempt. EHCI driver implents ehci_endpoint_disable() that makes sure clear_tt_work has finished before it returns, but xhci lacks this support. usb core will call hcd->driver->endpoint_disable() callback before disabling endpoints, so we want this in xhci as well. The added xhci_endpoint_disable() is based on ehci_endpoint_disable() Fixes: ef513be0a905 ("usb: xhci: Add Clear_TT_Buffer") Cc: # v5.3 Reported-by: Johan Hovold Suggested-by: Johan Hovold Reviewed-by: Johan Hovold Tested-by: Johan Hovold Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/1572013829-14044-2-git-send-email-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 54 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3071,6 +3071,48 @@ void xhci_cleanup_stalled_ring(struct xh } } +static void xhci_endpoint_disable(struct usb_hcd *hcd, + struct usb_host_endpoint *host_ep) +{ + struct xhci_hcd *xhci; + struct xhci_virt_device *vdev; + struct xhci_virt_ep *ep; + struct usb_device *udev; + unsigned long flags; + unsigned int ep_index; + + xhci = hcd_to_xhci(hcd); +rescan: + spin_lock_irqsave(&xhci->lock, flags); + + udev = (struct usb_device *)host_ep->hcpriv; + if (!udev || !udev->slot_id) + goto done; + + vdev = xhci->devs[udev->slot_id]; + if (!vdev) + goto done; + + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = &vdev->eps[ep_index]; + if (!ep) + goto done; + + /* wait for hub_tt_work to finish clearing hub TT */ + if (ep->ep_state & EP_CLEARING_TT) { + spin_unlock_irqrestore(&xhci->lock, flags); + schedule_timeout_uninterruptible(1); + goto rescan; + } + + if (ep->ep_state) + xhci_dbg(xhci, "endpoint disable with ep_state 0x%x\n", + ep->ep_state); +done: + host_ep->hcpriv = NULL; + spin_unlock_irqrestore(&xhci->lock, flags); +} + /* * Called after usb core issues a clear halt control message. * The host side of the halt should already be cleared by a reset endpoint @@ -5237,20 +5279,13 @@ static void xhci_clear_tt_buffer_complet unsigned int ep_index; unsigned long flags; - /* - * udev might be NULL if tt buffer is cleared during a failed device - * enumeration due to a halted control endpoint. Usb core might - * have allocated a new udev for the next enumeration attempt. - */ - xhci = hcd_to_xhci(hcd); + + spin_lock_irqsave(&xhci->lock, flags); udev = (struct usb_device *)ep->hcpriv; - if (!udev) - return; slot_id = udev->slot_id; ep_index = xhci_get_endpoint_index(&ep->desc); - spin_lock_irqsave(&xhci->lock, flags); xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_CLEARING_TT; xhci_ring_doorbell_for_active_rings(xhci, slot_id, ep_index); spin_unlock_irqrestore(&xhci->lock, flags); @@ -5287,6 +5322,7 @@ static const struct hc_driver xhci_hc_dr .free_streams = xhci_free_streams, .add_endpoint = xhci_add_endpoint, .drop_endpoint = xhci_drop_endpoint, + .endpoint_disable = xhci_endpoint_disable, .endpoint_reset = xhci_endpoint_reset, .check_bandwidth = xhci_check_bandwidth, .reset_bandwidth = xhci_reset_bandwidth,