From patchwork Mon Mar 1 16:11:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kroah-Hartman X-Patchwork-Id: 390075 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 19983C433E9 for ; Mon, 1 Mar 2021 17:06:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E37436515B for ; Mon, 1 Mar 2021 17:06:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236793AbhCARFn (ORCPT ); Mon, 1 Mar 2021 12:05:43 -0500 Received: from mail.kernel.org ([198.145.29.99]:55952 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234898AbhCAQ6n (ORCPT ); Mon, 1 Mar 2021 11:58:43 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 747D064FE0; Mon, 1 Mar 2021 16:37:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1614616632; bh=MrbIWZbNZwdaxrIrI0E4s1Fwq8D53RoLHd37QujM1hU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eq/TxpDrR/Zd75m9Am8TUXxORBy8Qk4YuKu+V8wVZQpTpTzygJnOIIHJuYTcNMVIH ybEyZVR/KHl3YtH7GYC459msUSYrnvONgv7rxDgCBsw8K0Y8jUBptuy46XXUgqugNC wv55FBZtEBzJV7+ch4B8Ljs0i2Tn4yNc8rD9bsG4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Felipe Balbi , Jack Pham , Jerome Brunet , Sasha Levin , Ferry Toth , Peter Chen Subject: [PATCH 4.19 042/247] usb: gadget: u_audio: Free requests only after callback Date: Mon, 1 Mar 2021 17:11:02 +0100 Message-Id: <20210301161033.730046010@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210301161031.684018251@linuxfoundation.org> References: <20210301161031.684018251@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Jack Pham [ Upstream commit 7de8681be2cde9f6953d3be1fa6ce05f9fe6e637 ] As per the kernel doc for usb_ep_dequeue(), it states that "this routine is asynchronous, that is, it may return before the completion routine runs". And indeed since v5.0 the dwc3 gadget driver updated its behavior to place dequeued requests on to a cancelled list to be given back later after the endpoint is stopped. The free_ep() was incorrectly assuming that a request was ready to be freed after calling dequeue which results in a use-after-free in dwc3 when it traverses its cancelled list. Fix this by moving the usb_ep_free_request() call to the callback itself in case the ep is disabled. Fixes: eb9fecb9e69b0 ("usb: gadget: f_uac2: split out audio core") Reported-and-tested-by: Ferry Toth Reviewed-and-tested-by: Peter Chen Acked-by: Felipe Balbi Signed-off-by: Jack Pham Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210118084642.322510-2-jbrunet@baylibre.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/gadget/function/u_audio.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index fb5ed97572e5f..0cb0c638fd131 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -89,7 +89,12 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) struct snd_uac_chip *uac = prm->uac; /* i/f shutting down */ - if (!prm->ep_enabled || req->status == -ESHUTDOWN) + if (!prm->ep_enabled) { + usb_ep_free_request(ep, req); + return; + } + + if (req->status == -ESHUTDOWN) return; /* @@ -351,8 +356,14 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep) for (i = 0; i < params->req_number; i++) { if (prm->ureq[i].req) { - usb_ep_dequeue(ep, prm->ureq[i].req); - usb_ep_free_request(ep, prm->ureq[i].req); + if (usb_ep_dequeue(ep, prm->ureq[i].req)) + usb_ep_free_request(ep, prm->ureq[i].req); + /* + * If usb_ep_dequeue() cannot successfully dequeue the + * request, the request will be freed by the completion + * callback. + */ + prm->ureq[i].req = NULL; } }