From patchwork Tue Nov 28 14:01:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 170795 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp3939085vqx; Tue, 28 Nov 2023 06:01:19 -0800 (PST) X-Google-Smtp-Source: AGHT+IEZJKv2Hr1B+pQjVv5FeDsyOF1JERTHhdJw/ANNIeG7z5i1oXbZLeU5gZJVfq+MtnNE5zM4 X-Received: by 2002:a17:902:ecc7:b0:1cf:b298:3a54 with SMTP id a7-20020a170902ecc700b001cfb2983a54mr12060273plh.58.1701180079535; Tue, 28 Nov 2023 06:01:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701180079; cv=none; d=google.com; s=arc-20160816; b=lDFO+jkFf+7AkN1WFnhv5q5NX+OhzPw8IzUuu7FAAinUdqb4TAdD/9C3V+0Effof0k pZ0kcE0Uxy/A8I0Ht3CHn9VIBUnd0sEuBdQvnuKXLQR8ImbB4HvP2byvR9+Zx0hZPl0e mpuOemQ7+wCW4oXDkNwZzs6u+Y7ybwG0mGY/9V4NTOKOGfPx+WsAiP0q0D88eEd7rPpH FzCX14Wqw5BXTprLcJ7Z6ypsoqSePMU/nYJmeBqLm1OqFSl+g98c1tBG+qbddb7eRFfp jyCh54KOxrKEsM7Qi7N3Qn/rJeUB4vppAybr6Jh0EJe00ECqrq7xMUBE+f/L+22YeO8R d+PQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=QvOcpg9zYRLYO6oNybpo1xRa1HcorufcElWSa3qaxUg=; fh=3F54v6jmjA4Ey2JVCnJkeTLJJd6nUM30m8dRjeh6Z1M=; b=qMb1e4MJ05h8JtdpwiAbhAwFRRXXEsyVDRR8fIcsijV/z8iO+wJIjhRqlwvD8u9vcQ y7Oe+NzLU0CLHlcWl/rRYoXG5SHggSTwdIepu/Ju28Hv7yPo2mSEvSIrn5ZHlk5s75cH RKlRNhNVuDn3u9pH6Mz0iAh0pmkyaYDpSUQUBuf5KdR0ss8sJLf8Gfp+dLT1/Rgm0aPA mlSjEJxGjMOWdkd8pg234kxKwJae+QqtjUs7muiyCDdd6lqoIGm9R+rl3c2tGYY8PoRr GrASMTEa6Ro7XRwGGjiqoZi9s5mn7maGmQ/ificS5axKVP2zSICtjt+Ut3IAEZYlZfs6 zI+g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=YR76t52J; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from agentk.vger.email (agentk.vger.email. [23.128.96.32]) by mx.google.com with ESMTPS id k7-20020a170902c40700b001cf5c99f2adsi193464plk.261.2023.11.28.06.01.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Nov 2023 06:01:19 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) client-ip=23.128.96.32; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=YR76t52J; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by agentk.vger.email (Postfix) with ESMTP id 053788054B7D; Tue, 28 Nov 2023 06:01:09 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at agentk.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345291AbjK1OAv (ORCPT + 99 others); Tue, 28 Nov 2023 09:00:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344802AbjK1OAr (ORCPT ); Tue, 28 Nov 2023 09:00:47 -0500 Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D24FAB5; Tue, 28 Nov 2023 06:00:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701180053; x=1732716053; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MNlQHIbeic/N5OcXLHIcXCVWnYu4P3iJBAyhPL8NeKQ=; b=YR76t52JeirAoil/rjLqIBq7CFupf56PCvqUvH/zRxBYaz8h+v9AQtU3 T2M5YFro+nUeN11orlyiQQnhIPoSpQFDrpxQTqujexP/fRkzOrcoaCC26 lKH/APIZM/6NHVk284OW+VdPqHGjmryjc0g1JdqY5Abne0L6xJFqR53FZ ak3QtPw8mx1mg1h47XyvlekcEeNT32NQy/2Hgz15vmXtYcoucZDAIa1Gb P34oNVfhpslkni2udgn+Iut7DltBCGfekpFHRunEKiWs+b4o4+zdCve12 1jHJ+Op5e44d3t9yR/+URL2XDpITuIdhgY8UQ05kr3LVOBMywbUWl44xG g==; X-IronPort-AV: E=McAfee;i="6600,9927,10907"; a="383312970" X-IronPort-AV: E=Sophos;i="6.04,234,1695711600"; d="scan'208";a="383312970" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Nov 2023 06:00:30 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10907"; a="892080410" X-IronPort-AV: E=Sophos;i="6.04,234,1695711600"; d="scan'208";a="892080410" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by orsmga004.jf.intel.com with ESMTP; 28 Nov 2023 06:00:28 -0800 From: Mathias Nyman To: khtsai@google.com Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stern@rowland.harvard.edu, Mathias Nyman Subject: [RFT PATCH 1/2] xhci: Reconfigure endpoint 0 max packet size only during endpoint reset Date: Tue, 28 Nov 2023 16:01:40 +0200 Message-Id: <20231128140141.1161490-1-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <51b8fc3d-25ef-1ab3-d744-8d851a133828@linux.intel.com> References: <51b8fc3d-25ef-1ab3-d744-8d851a133828@linux.intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on agentk.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (agentk.vger.email [0.0.0.0]); Tue, 28 Nov 2023 06:01:09 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783816602698778848 X-GMAIL-MSGID: 1783816602698778848 The max packet size for full speed control endpoint 0 may vary. It is defined in the device descriptor, which is read using the same endpoint. Usb core sets a temporary max packet size value until the real value is read. xhci driver needs to reconfigure the endpoint context seen by the controller if the max packet size changes. It makes more sense to do this reconfiguration in xhci_endpoint_reset() instead of urb enqueue as usb core will call endpoint reset during enumeration if the max packet values differ. Max packet size adjustment for endpoinr 0 can only happen once per device enumeration. Previously the max packet size was checked during every urb enqueue. This is an additional check for every enqueued urb, and also turned out to have locking issues as urbs may be queued in any context while xhci max packet size reconfiguration requires memory allocation, locking, and sleeping. Tested with a full speed device using both old and new scheme enumeration and a intentionally incorrect preliminary max packet size value. Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci.c | 85 ++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 884b0898d9c9..df31d44498d6 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1438,10 +1438,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, * descriptor. If the usb_device's max packet size changes after that point, * we need to issue an evaluate context command and wait on it. */ -static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, - unsigned int ep_index, struct urb *urb, gfp_t mem_flags) +static int xhci_check_ep0_maxpacket(struct xhci_hcd *xhci, struct xhci_virt_device *vdev) { - struct xhci_container_ctx *out_ctx; struct xhci_input_control_ctx *ctrl_ctx; struct xhci_ep_ctx *ep_ctx; struct xhci_command *command; @@ -1449,11 +1447,15 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, int hw_max_packet_size; int ret = 0; - out_ctx = xhci->devs[slot_id]->out_ctx; - ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); + ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, 0); hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); - max_packet_size = usb_endpoint_maxp(&urb->dev->ep0.desc); - if (hw_max_packet_size != max_packet_size) { + max_packet_size = usb_endpoint_maxp(&vdev->udev->ep0.desc); + + if (hw_max_packet_size == max_packet_size) + return 0; + + switch (max_packet_size) { + case 8: case 16: case 32: case 64: case 9: xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, "Max Packet Size for ep 0 changed."); xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, @@ -1465,28 +1467,22 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, "Issuing evaluate context command."); - /* Set up the input context flags for the command */ - /* FIXME: This won't work if a non-default control endpoint - * changes max packet sizes. - */ - - command = xhci_alloc_command(xhci, true, mem_flags); + command = xhci_alloc_command(xhci, true, GFP_KERNEL); if (!command) return -ENOMEM; - command->in_ctx = xhci->devs[slot_id]->in_ctx; + command->in_ctx = vdev->in_ctx; ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx); if (!ctrl_ctx) { xhci_warn(xhci, "%s: Could not get input context, bad type.\n", __func__); ret = -ENOMEM; - goto command_cleanup; + break; } /* Set up the modified control endpoint 0 */ - xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, - xhci->devs[slot_id]->out_ctx, ep_index); + xhci_endpoint_copy(xhci, vdev->in_ctx, vdev->out_ctx, 0); - ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index); + ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, 0); ep_ctx->ep_info &= cpu_to_le32(~EP_STATE_MASK);/* must clear */ ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); @@ -1494,17 +1490,20 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); ctrl_ctx->drop_flags = 0; - ret = xhci_configure_endpoint(xhci, urb->dev, command, - true, false); - - /* Clean up the input context for later use by bandwidth - * functions. - */ + ret = xhci_configure_endpoint(xhci, vdev->udev, command, + true, false); + /* Clean up the input context for later use by bandwidth functions */ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); -command_cleanup: - kfree(command->completion); - kfree(command); + break; + default: + dev_dbg(&vdev->udev->dev, "incorrect max packet size %d for ep0\n", + max_packet_size); + return -EINVAL; } + + kfree(command->completion); + kfree(command); + return ret; } @@ -1561,21 +1560,6 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag trace_xhci_urb_enqueue(urb); - if (usb_endpoint_xfer_control(&urb->ep->desc)) { - /* Check to see if the max packet size for the default control - * endpoint changed during FS device enumeration - */ - if (urb->dev->speed == USB_SPEED_FULL) { - ret = xhci_check_maxpacket(xhci, slot_id, - ep_index, urb, mem_flags); - if (ret < 0) { - xhci_urb_free_priv(urb_priv); - urb->hcpriv = NULL; - return ret; - } - } - } - spin_lock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) { @@ -3104,6 +3088,21 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, int err; xhci = hcd_to_xhci(hcd); + ep_index = xhci_get_endpoint_index(&host_ep->desc); + + /* + * Usb core assumes a max packet value for ep0 on FS devices until the + * real value is read from the descriptor. Core resets Ep0 if values + * mismatch. Reconfigure the xhci ep0 endpoint context here in that case + */ + if (usb_endpoint_xfer_control(&host_ep->desc) && ep_index == 0) { + udev = container_of(host_ep, struct usb_device, ep0); + if (udev->speed == USB_SPEED_FULL) + xhci_check_ep0_maxpacket(xhci, xhci->devs[udev->slot_id]); + /* Nothing else should be done here for ep0 during ep reset */ + return; + } + if (!host_ep->hcpriv) return; udev = (struct usb_device *) host_ep->hcpriv; @@ -3116,7 +3115,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, */ if (!udev->slot_id || !vdev) return; - ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = &vdev->eps[ep_index]; /* Bail out if toggle is already being cleared by a endpoint reset */ From patchwork Tue Nov 28 14:01:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 170794 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp3939159vqx; Tue, 28 Nov 2023 06:01:23 -0800 (PST) X-Google-Smtp-Source: AGHT+IGlGJRbB8wk0dJe7/85fRDmT6JopA88gdCCBmY7ylQ1xxU742Qgj8Jem4DksnRUHhIa7/nt X-Received: by 2002:a05:6808:168d:b0:3b8:41d1:7310 with SMTP id bb13-20020a056808168d00b003b841d17310mr19195400oib.5.1701180083367; Tue, 28 Nov 2023 06:01:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701180083; cv=none; d=google.com; s=arc-20160816; b=cBRVWu00DOAhU68xmvpe6Notib5NwggbYRAEPIHNh7VVF3qagifbJDg0dBEw696gqG nV1RAVtg4PqTxjyP/QTfidTIEqHbh28Xbn/o3C/kiqvAJKT5QcCoaUjpZ3GN78MuXE5n oNZQVu+kL6a3jpJiuolxjLb5HBAiC968HawhE4MzIohd/9gOU/h9WWNYBwU37Dvu4ABV qalL3LbQnory7M/03J5WKEe/+fYeo9zqXZH+AezndJv/JfxpJ2PM3Qd/0ZYPSTUwwtUL 6F6l+xrQceM2wJWlm3J0uyMPY+VytKqjtXEaHwF4s/7psji6BHs1icCVKE8Nu0ZXbMM3 kwyA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=gDeyDevgPSVHyhItuIxiJ5f232ZPZJroRvVWCk5dyvo=; fh=3F54v6jmjA4Ey2JVCnJkeTLJJd6nUM30m8dRjeh6Z1M=; b=WsM8MwD0hSL8MhHyxXom24373MuCJcgcLM+JTb9E67Bmlg7ez29Nk3bFz6SfKFPc19 edeZIqZr5cH+jdpDRnrtXjACekMQEy0uX3v1LKgou1b35ryhqk8prJzaEgsd9XntNVwN 9T9R+bSgbQwl9NfpRS8lHLc9cE/Y3u2mcyYp56TNsc8GQ3W/lHaAgKzA69cDbz6C5C13 GPDni2aivM60yRKCCEaqPwV5/AmPuH8YwJK6S8CwnrmC8hbPzVRcG3M7I5rgCXflVzhH 0THCtwzOPMa+Lh8dUgf5C2zaaLKD169Sw3qqjcviljm2zsFQKSldNulkoTjFWUxLKg/6 KBKQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=akNl+mrk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id bm6-20020a656e86000000b00584e65212d4si12050387pgb.609.2023.11.28.06.01.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Nov 2023 06:01:23 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=akNl+mrk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id 493D680AC8F2; Tue, 28 Nov 2023 06:01:16 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345314AbjK1OAy (ORCPT + 99 others); Tue, 28 Nov 2023 09:00:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60306 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344807AbjK1OAu (ORCPT ); Tue, 28 Nov 2023 09:00:50 -0500 Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 759E1CC; Tue, 28 Nov 2023 06:00:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701180056; x=1732716056; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bzQwSFKdK4wUAzVYUBTKHo5DJAY0+XMLzAA1r8JOvRk=; b=akNl+mrkzVGbOgi9G6bPuuFqoZ9AUadOhOuOJLZMYF7U0foCLZiosDqQ 5bhxNEMnmLNc+tNVYwvJjgY7lr+sxMnLHIi789goO5PKjGklWAvNsNywk kZAqmA0Tujj31A1N0EObTCbi9M0sHDpvFjczteuZQpjiq9jVUAgGldO+7 EnQg9aHfKFc/gEeRtkBWs1NWIDooM1Uzi+vPLgNz3BoGqt/kWv7X0ua3U zNi9hHDr0iCs+vkRjOGAWNrISTvqnTDQO0cgAb1h6w7riG011ZhBODHE/ PHAHlzBPHjA9fLC0Cy26vpYSsoRNjmFFBP7txQHSCJGZvNWd06AsdP1h9 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10907"; a="383312979" X-IronPort-AV: E=Sophos;i="6.04,234,1695711600"; d="scan'208";a="383312979" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Nov 2023 06:00:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10907"; a="892080417" X-IronPort-AV: E=Sophos;i="6.04,234,1695711600"; d="scan'208";a="892080417" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by orsmga004.jf.intel.com with ESMTP; 28 Nov 2023 06:00:31 -0800 From: Mathias Nyman To: khtsai@google.com Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stern@rowland.harvard.edu, Mathias Nyman Subject: [RFT PATCH 2/2] xhci: fix possible null pointer deref during xhci urb enqueue Date: Tue, 28 Nov 2023 16:01:41 +0200 Message-Id: <20231128140141.1161490-2-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231128140141.1161490-1-mathias.nyman@linux.intel.com> References: <51b8fc3d-25ef-1ab3-d744-8d851a133828@linux.intel.com> <20231128140141.1161490-1-mathias.nyman@linux.intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (lipwig.vger.email [0.0.0.0]); Tue, 28 Nov 2023 06:01:16 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783816606922940201 X-GMAIL-MSGID: 1783816606922940201 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, dereferening 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 --- 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 df31d44498d6..4929c4396e9e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1521,24 +1521,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; @@ -1562,12 +1545,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);