Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp1823791imm; Mon, 3 Sep 2018 10:22:12 -0700 (PDT) X-Google-Smtp-Source: ANB0Vdameoy+3f2D1w7AxvC+e4HBEoIYHnJBNmJuf1/Nsp9B+3ZdSm0MCJW1wzEoay5cjob7skf9 X-Received: by 2002:a62:7590:: with SMTP id q138-v6mr23040198pfc.148.1535995332037; Mon, 03 Sep 2018 10:22:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535995332; cv=none; d=google.com; s=arc-20160816; b=X7dPZf1Yzfx0h6eq5FqKn5Je2lqwCBlBZAKvPln+sxXhd0IAujVsXYMFj1qHrDflOi SkLgjH/hvOov0DWKDg7YsWSE+vkYRXSrjAtgDa5gjPolk3n2WOd+ZCMIte0T/Pz15bDd VbeqXwLAjf1Hp0ab3PFEeHtS+BY1gIzxvksJiEfEmmshkDxKeFtJJHmRjNdwf1qKBaG1 PhE3poWk8N+eICLhEya1SqZtbWzeQfyp1QoV3F51iAG+OputXwc4KzGOUZy2ZjlF2pxW /anGBXey/GZ4HLAUqFp3g6rRhL930YJmDdamB/0k91noAHT7n9VFnvfWLPcJcHt7iQ97 ryKQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=QImeS5Xwx4YWtgtxhbr9PJrE6+zflmROXZBFbjW+Od8=; b=qpA/8JYgAMLrONkCvClxTi565vR2gFvs1v3SAwI9hZkkNFIKGMQv51Cn19479i++kc /tVwzNI9jc+lyZ5CQ6kgipziwf+YHV2d0SJGJVUBHnZ9KPtCLXN1LtK+JHWupnYinoLF bHhkXDCH9o/Oo7ks3MVQa2ysfWCQGVLyZrHGeg3SZH5kZbBof6Md1TwC8cxxLMW8cW2n z/dQskvfvDcH+mcgG7qZ5iyZoCpAJUkg7EGzNX2VJC20wIczLkqQbP081sfa9DFJW7WR vOSNy96Ef4r70JdDdZo64KFGkbiTutMGJs8dH8QNdcUO0p85Lht6Q7oKVRqD0nKYIz9I cntw== ARC-Authentication-Results: i=1; mx.google.com; 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 n10-v6si20311676pfb.316.2018.09.03.10.21.57; Mon, 03 Sep 2018 10:22:12 -0700 (PDT) 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; 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 S1730307AbeICVjS (ORCPT + 99 others); Mon, 3 Sep 2018 17:39:18 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:43000 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728837AbeICVjR (ORCPT ); Mon, 3 Sep 2018 17:39:17 -0400 Received: from localhost (ip-213-127-74-90.ip.prioritytelecom.net [213.127.74.90]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 51D1AD12; Mon, 3 Sep 2018 17:18:12 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Vladimir Zapolskiy , Eugeniu Rosca , Felipe Balbi , Sasha Levin Subject: [PATCH 4.14 023/165] [PATCH 23/82] usb: gadget: u_audio: protect stream runtime fields with stream spinlock Date: Mon, 3 Sep 2018 18:55:09 +0200 Message-Id: <20180903165656.194828702@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180903165655.003605184@linuxfoundation.org> References: <20180903165655.003605184@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ [ Upstream commit 56bc61587daadef67712068f251c4ef2e3932d94 ] The change protects almost the whole body of u_audio_iso_complete() function by PCM stream lock, this is mainly sufficient to avoid a race between USB request completion and stream termination, the change prevents a possibility of invalid memory access in interrupt context by memcpy(): Unable to handle kernel paging request at virtual address 00004e80 pgd = c0004000 [00004e80] *pgd=00000000 Internal error: Oops: 817 [#1] PREEMPT SMP ARM CPU: 0 PID: 3 Comm: ksoftirqd/0 Tainted: G C 3.14.54+ #117 task: da180b80 ti: da192000 task.ti: da192000 PC is at memcpy+0x50/0x330 LR is at 0xcdd92b0e pc : [] lr : [] psr: 20000193 sp : da193ce4 ip : dd86ae26 fp : 0000b180 r10: daf81680 r9 : 00000000 r8 : d58a01ea r7 : 2c0b43e4 r6 : acdfb08b r5 : 01a271cf r4 : 87389377 r3 : 69469782 r2 : 00000020 r1 : daf82fe0 r0 : 00004e80 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5387d Table: 2b70804a DAC: 00000015 Process ksoftirqd/0 (pid: 3, stack limit = 0xda192238) Also added a check for potential !runtime condition, commonly it is done by PCM_RUNTIME_CHECK(substream) in the beginning, however this does not completely prevent from oopses in u_audio_iso_complete(), because the proper protection scheme must be implemented in PCM library functions. An example of *not fixed* oops due to substream->runtime->* dereference by snd_pcm_running(substream) from snd_pcm_period_elapsed(), where substream->runtime is gone while waiting the substream lock: Unable to handle kernel paging request at virtual address 6b6b6b6b pgd = db7e4000 [6b6b6b6b] *pgd=00000000 CPU: 0 PID: 193 Comm: klogd Tainted: G C 3.14.54+ #118 task: db5ac500 ti: db60c000 task.ti: db60c000 PC is at snd_pcm_period_elapsed+0x48/0xd8 [snd_pcm] LR is at snd_pcm_period_elapsed+0x40/0xd8 [snd_pcm] pc : [<>] lr : [<>] psr: 60000193 Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 2b7e404a DAC: 00000015 Process klogd (pid: 193, stack limit = 0xdb60c238) [<>] (snd_pcm_period_elapsed [snd_pcm]) from [<>] (udc_irq+0x500/0xbbc) [<>] (udc_irq) from [<>] (ci_irq+0x280/0x304) [<>] (ci_irq) from [<>] (handle_irq_event_percpu+0xa4/0x40c) [<>] (handle_irq_event_percpu) from [<>] (handle_irq_event+0x3c/0x5c) [<>] (handle_irq_event) from [<>] (handle_fasteoi_irq+0xc4/0x110) [<>] (handle_fasteoi_irq) from [<>] (generic_handle_irq+0x20/0x30) [<>] (generic_handle_irq) from [<>] (handle_IRQ+0x80/0xc0) [<>] (handle_IRQ) from [<>] (gic_handle_irq+0x3c/0x60) [<>] (gic_handle_irq) from [<>] (__irq_svc+0x44/0x78) Signed-off-by: Vladimir Zapolskiy [erosca: W/o this patch, with minimal instrumentation [1], I can consistently reproduce BUG: KASAN: use-after-free [2]] [1] Instrumentation to reproduce issue [2]: # diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c # index a72295c953bb..bd0b308024fe 100644 # --- a/drivers/usb/gadget/function/u_audio.c # +++ b/drivers/usb/gadget/function/u_audio.c # @@ -16,6 +16,7 @@ # #include # #include # #include # +#include # # #include "u_audio.h" # # @@ -147,6 +148,8 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) # # spin_unlock_irqrestore(&prm->lock, flags); # # + udelay(500); //delay here to increase probability of parallel activities # + # /* Pack USB load in ALSA ring buffer */ # pending = prm->dma_bytes - hw_ptr; [2] After applying [1], below BUG occurs on Rcar-H3-Salvator-X board: ================================================================== BUG: KASAN: use-after-free in u_audio_iso_complete+0x24c/0x520 [u_audio] Read of size 8 at addr ffff8006cafcc248 by task swapper/0/0 CPU: 0 PID: 0 Comm: swapper/0 Tainted: G WC 4.14.47+ #160 Hardware name: Renesas Salvator-X board based on r8a7795 ES2.0+ (DT) Call trace: [] dump_backtrace+0x0/0x364 [] show_stack+0x14/0x1c [] dump_stack+0x108/0x174 [] print_address_description+0x7c/0x32c [] kasan_report+0x324/0x354 [] __asan_load8+0x24/0x94 [] u_audio_iso_complete+0x24c/0x520 [u_audio] [] usb_gadget_giveback_request+0x480/0x4d0 [udc_core] [] usbhsg_queue_done+0x100/0x130 [renesas_usbhs] [] usbhsf_pkt_handler+0x1a4/0x298 [renesas_usbhs] [] usbhsf_irq_ready+0x128/0x178 [renesas_usbhs] [] usbhs_interrupt+0x440/0x490 [renesas_usbhs] [] __handle_irq_event_percpu+0x594/0xa58 [] handle_irq_event_percpu+0x84/0x12c [] handle_irq_event+0xb0/0x10c [] handle_fasteoi_irq+0x1e0/0x2ec [] generic_handle_irq+0x2c/0x44 [] __handle_domain_irq+0x190/0x194 [] gic_handle_irq+0x80/0xac Exception stack(0xffff200009e97c80 to 0xffff200009e97dc0) 7c80: 0000000000000000 0000000000000000 0000000000000003 ffff200008179298 7ca0: ffff20000ae1c180 dfff200000000000 0000000000000000 ffff2000081f9a88 7cc0: ffff200009eb5960 ffff200009e97cf0 0000000000001600 ffff0400041b064b 7ce0: 0000000000000000 0000000000000002 0000000200000001 0000000000000001 7d00: ffff20000842197c 0000ffff958c4970 0000000000000000 ffff8006da0d5b80 7d20: ffff8006d4678498 0000000000000000 000000126bde0a8b ffff8006d4678480 7d40: 0000000000000000 000000126bdbea64 ffff200008fd0000 ffff8006fffff980 7d60: 00000000495f0018 ffff200009e97dc0 ffff200008b6c4ec ffff200009e97dc0 7d80: ffff200008b6c4f0 0000000020000145 ffff8006da0d5b80 ffff8006d4678498 7da0: ffffffffffffffff ffff8006d4678498 ffff200009e97dc0 ffff200008b6c4f0 [] el1_irq+0xb4/0x12c [] cpuidle_enter_state+0x818/0x844 [] cpuidle_enter+0x18/0x20 [] call_cpuidle+0x98/0x9c [] do_idle+0x214/0x264 [] cpu_startup_entry+0x20/0x24 [] rest_init+0x30c/0x320 [] start_kernel+0x570/0x5b0 ---<-snip->--- Fixes: 132fcb460839 ("usb: gadget: Add Audio Class 2.0 Driver") Signed-off-by: Eugeniu Rosca Signed-off-by: Felipe Balbi Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/u_audio.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index e9644137f720..d3a639297e06 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -88,7 +88,7 @@ static const struct snd_pcm_hardware uac_pcm_hardware = { static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) { unsigned pending; - unsigned long flags; + unsigned long flags, flags2; unsigned int hw_ptr; int status = req->status; struct uac_req *ur = req->context; @@ -115,7 +115,14 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) if (!substream) goto exit; + snd_pcm_stream_lock_irqsave(substream, flags2); + runtime = substream->runtime; + if (!runtime || !snd_pcm_running(substream)) { + snd_pcm_stream_unlock_irqrestore(substream, flags2); + goto exit; + } + spin_lock_irqsave(&prm->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -174,6 +181,7 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes; hw_ptr = prm->hw_ptr; spin_unlock_irqrestore(&prm->lock, flags); + snd_pcm_stream_unlock_irqrestore(substream, flags2); if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual) snd_pcm_period_elapsed(substream); -- 2.18.0