From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40EF212BF03; Sun, 28 Jan 2024 16:15:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706458532; cv=none; b=IWAfZM/xnbLnV4ivkhUYY3rDxinXIeXMuBeFydLd2miPm6mF2QNE2DfOOjQLDqc19J6WTXjZOaSg3oAvDeztJ9fWaRd0EndghZ6nKoHoGreXDudgDbVYQZ3QuWXNbX6Fga/je2Dcxmtxhk3gwhP7tbVYD6izr5t6Ur08/KXDg3k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706458532; c=relaxed/simple; bh=o4xzHRBMA12JJMcNnt3IiYQvBBwbOUYyVDvqcLYgOUc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GXwwNSoqB+dj+k3TUr/byU8YnPvk+Zkz2P98z+zbQZ/JHi9PtqtEBLgEBX5py+6AaYU7E5Y2UTKpP9FtRZBJ7HDN3Yt4afyKYHzR/02kK7aoalKj7JjkFo8XKRWqNC/oSpHQivn1x2QyCEBZTmu/c4kxR76QaGRc65X4TJYIwjs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=W0OQR/mO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="W0OQR/mO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E217AC43390; Sun, 28 Jan 2024 16:15:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1706458531; bh=o4xzHRBMA12JJMcNnt3IiYQvBBwbOUYyVDvqcLYgOUc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W0OQR/mO9KfpYIXImhNNiS5e7bu/em4GkAYOPYkiK9aha5lxdF3tf6+Bbak3iKHXm pqmFPKw4LcaaJamuRncDQN0gV4hDYXqmxbHBigRJ3Gq72nJLFmiftknWEZXStmnI4+ pRHHrVsanQmjW4HozFthB2poAxQBjsLkp5HlL8i84jge/kBNWHkJ7PJh157GFVhZrv k1sM3iidLDK8GZp+oxGnZbndO28TNIBJ28bez5m/3lPdsyAHEHWlZxIOFmuYa1aJWe nRulqTHpZhvv8/i2pFPNGbIwBSGm0UkXfx1JiRbqB46tyj4l1OP/EBzO0rP/ZUygcz OLLWGA/pmcsLA== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Mathias Nyman , Kuen-Han Tsai , Greg Kroah-Hartman , Sasha Levin , mathias.nyman@intel.com, linux-usb@vger.kernel.org Subject: [PATCH AUTOSEL 5.15 04/19] xhci: fix possible null pointer deref during xhci urb enqueue Date: Sun, 28 Jan 2024 11:15:01 -0500 Message-ID: <20240128161524.204182-4-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240128161524.204182-1-sashal@kernel.org> References: <20240128161524.204182-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 5.15.148 Content-Transfer-Encoding: 8bit From: Mathias Nyman [ Upstream commit e2e2aacf042f52854c92775b7800ba668e0bdfe4 ] There is a short gap between urb being submitted and actually added to the endpoint queue (linked). If the device is disconnected during this time then usb core is not yet aware of the pending urb, and device may be freed just before xhci_urq_enqueue() continues, dereferencing the freed device. Freeing the device is protected by the xhci spinlock, so make sure we take and keep the lock while checking that device exists, dereference it, and add the urb to the queue. Remove the unnecessary URB check, usb core checks it before calling xhci_urb_enqueue() Suggested-by: Kuen-Han Tsai Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20231201150647.1307406-20-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/host/xhci.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5c9d3be136d2..6c8c9cbcd05d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1644,24 +1644,7 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag struct urb_priv *urb_priv; int num_tds; - if (!urb) - return -EINVAL; - ret = xhci_check_args(hcd, urb->dev, urb->ep, - true, true, __func__); - if (ret <= 0) - return ret ? ret : -EINVAL; - - slot_id = urb->dev->slot_id; ep_index = xhci_get_endpoint_index(&urb->ep->desc); - ep_state = &xhci->devs[slot_id]->eps[ep_index].ep_state; - - if (!HCD_HW_ACCESSIBLE(hcd)) - return -ESHUTDOWN; - - if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) { - xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n"); - return -ENODEV; - } if (usb_endpoint_xfer_isoc(&urb->ep->desc)) num_tds = urb->number_of_packets; @@ -1700,12 +1683,35 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag spin_lock_irqsave(&xhci->lock, flags); + ret = xhci_check_args(hcd, urb->dev, urb->ep, + true, true, __func__); + if (ret <= 0) { + ret = ret ? ret : -EINVAL; + goto free_priv; + } + + slot_id = urb->dev->slot_id; + + if (!HCD_HW_ACCESSIBLE(hcd)) { + ret = -ESHUTDOWN; + goto free_priv; + } + + if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) { + xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n"); + ret = -ENODEV; + goto free_priv; + } + if (xhci->xhc_state & XHCI_STATE_DYING) { xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for non-responsive xHCI host.\n", urb->ep->desc.bEndpointAddress, urb); ret = -ESHUTDOWN; goto free_priv; } + + ep_state = &xhci->devs[slot_id]->eps[ep_index].ep_state; + if (*ep_state & (EP_GETTING_STREAMS | EP_GETTING_NO_STREAMS)) { xhci_warn(xhci, "WARN: Can't enqueue URB, ep in streams transition state %x\n", *ep_state); -- 2.43.0