Re: Patch "usb: gadget: u_audio: protect stream runtime fields with stream spinlock" has been added to the 4.14-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Aug 26, 2018 at 04:23:55PM +0300, Vladimir Zapolskiy wrote:
> Hi Greg,
> 
> On 08/26/2018 10:14 AM, gregkh@xxxxxxxxxxxxxxxxxxx wrote:
> > 
> > This is a note to let you know that I've just added the patch titled
> > 
> >      usb: gadget: u_audio: protect stream runtime fields with stream spinlock
> > 
> > to the 4.14-stable tree which can be found at:
> >      http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
> > 
> > The filename of the patch is:
> >       usb-gadget-u_audio-protect-stream-runtime-fields-with-stream-spinlock.patch
> > and it can be found in the queue-4.14 subdirectory.
> > 
> > If you, or anyone else, feels it should not be added to the stable tree,
> > please let <stable@xxxxxxxxxxxxxxx> know about it.
> > 
> > 
> >  From foo@baz Sun Aug 26 09:13:00 CEST 2018
> > From: Vladimir Zapolskiy <vladimir_zapolskiy@xxxxxxxxxx>
> > Date: Thu, 21 Jun 2018 17:22:52 +0200
> > Subject: usb: gadget: u_audio: protect stream runtime fields with stream spinlock
> > 
> > From: Vladimir Zapolskiy <vladimir_zapolskiy@xxxxxxxxxx>
> > 
> > [ 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 : [<c029ef30>]    lr : [<cdd92b0e>]    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 <vladimir_zapolskiy@xxxxxxxxxx>
> > [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 <sound/core.h>
> >    #include <sound/pcm.h>
> >    #include <sound/pcm_params.h>
> >   +#include <linux/delay.h>
> > 
> >    #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:
> > [<ffff2000080925ac>] dump_backtrace+0x0/0x364
> > [<ffff200008092924>] show_stack+0x14/0x1c
> > [<ffff200008f8dbcc>] dump_stack+0x108/0x174
> > [<ffff2000083c71b8>] print_address_description+0x7c/0x32c
> > [<ffff2000083c78e8>] kasan_report+0x324/0x354
> > [<ffff2000083c6114>] __asan_load8+0x24/0x94
> > [<ffff2000021d1b34>] u_audio_iso_complete+0x24c/0x520 [u_audio]
> > [<ffff20000152fe50>] usb_gadget_giveback_request+0x480/0x4d0 [udc_core]
> > [<ffff200001860ab8>] usbhsg_queue_done+0x100/0x130 [renesas_usbhs]
> > [<ffff20000185f814>] usbhsf_pkt_handler+0x1a4/0x298 [renesas_usbhs]
> > [<ffff20000185fb38>] usbhsf_irq_ready+0x128/0x178 [renesas_usbhs]
> > [<ffff200001859cc8>] usbhs_interrupt+0x440/0x490 [renesas_usbhs]
> > [<ffff2000081a0288>] __handle_irq_event_percpu+0x594/0xa58
> > [<ffff2000081a07d0>] handle_irq_event_percpu+0x84/0x12c
> > [<ffff2000081a0928>] handle_irq_event+0xb0/0x10c
> > [<ffff2000081a8384>] handle_fasteoi_irq+0x1e0/0x2ec
> > [<ffff20000819e5f8>] generic_handle_irq+0x2c/0x44
> > [<ffff20000819f0d0>] __handle_domain_irq+0x190/0x194
> > [<ffff20000808177c>] 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
> > [<ffff200008084034>] el1_irq+0xb4/0x12c
> > [<ffff200008b6c4f0>] cpuidle_enter_state+0x818/0x844
> > [<ffff200008b6c59c>] cpuidle_enter+0x18/0x20
> > [<ffff20000815f2e4>] call_cpuidle+0x98/0x9c
> > [<ffff20000815f674>] do_idle+0x214/0x264
> > [<ffff20000815facc>] cpu_startup_entry+0x20/0x24
> > [<ffff200008fb09d8>] rest_init+0x30c/0x320
> > [<ffff2000095f1338>] start_kernel+0x570/0x5b0
> > ---<-snip->---
> > 
> > Fixes: 132fcb460839 ("usb: gadget: Add Audio Class 2.0 Driver")
> > Signed-off-by: Eugeniu Rosca <erosca@xxxxxxxxxxxxxx>
> > 
> > Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>
> > 
> > Signed-off-by: Sasha Levin <alexander.levin@xxxxxxxxxxxxx>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> > ---
> >   drivers/usb/gadget/function/u_audio.c |   13 ++++++++++++-
> >   1 file changed, 12 insertions(+), 1 deletion(-)
> > 
> > --- a/drivers/usb/gadget/function/u_audio.c
> > +++ b/drivers/usb/gadget/function/u_audio.c
> > @@ -25,6 +25,7 @@
> >   #include <sound/core.h>
> >   #include <sound/pcm.h>
> >   #include <sound/pcm_params.h>
> > +#include <linux/delay.h>
> 
> See a comment below...
> 
> >   #include "u_audio.h"
> > @@ -88,7 +89,7 @@ static const struct snd_pcm_hardware uac
> >   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 +116,14 @@ static void u_audio_iso_complete(struct
> >   	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) {
> > @@ -146,6 +154,8 @@ static void u_audio_iso_complete(struct
> >   	spin_unlock_irqrestore(&prm->lock, flags);
> > +	udelay(500); //delay here to increase probability of parallel activities
> > +
> 
> ^^^^^
> 
> That part of the change came from the commit message, it just describes
> instrumentation, and adding it to the change itself is wrong.
> 
> Note that the source commit 56bc61587daad does not have such issue.

Ugh, that's a mess.  I've fixed it up now, thanks for catching that.
Putting diffs in a changelog text is a pain.

greg k-h



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux