sound: use-after-free in snd_timer_stop

75 views
Skip to first unread message

Dmitry Vyukov

unread,
Jan 12, 2016, 5:22:30 AM1/12/16
to Jaroslav Kysela, Takashi Iwai, Jie Yang, Mark Brown, alsa-...@alsa-project.org, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
Hello,

I've hit the following use-after-free while running syzkaller fuzzer.
It is followed by a splat of other reports and finally kernel death.
I wasn't able to reproduce it with a standalone C program (there is
probably some global state involved). But it reproduces by replaying
fuzzer logs in a loop (you will need Go toolchain):

$ go get github.com/google/syzkaller
$ cd $GOPATH/src/github.com/google/syzkaller
$ make executor execprog
$ scp bin/syz-executor bin/syz-execprog your@machine
$ scp snd_timer_stop your@machine # the attached file
on test machine:
$ ./syz-execprog -executor ./syz-executor -cover=0 -repeat=0 -procs=16
snd_timer_stop


==================================================================
BUG: KASAN: use-after-free in _snd_timer_stop+0x394/0x450 at addr
ffff8800356d0b70
Read of size 4 by task syz-executor/6313
=============================================================================
BUG kmalloc-256 (Not tainted): kasan: bad access detected
-----------------------------------------------------------------------------

INFO: Allocated in snd_timer_instance_new+0x52/0x3a0 age=20 cpu=1 pid=6312
[< none >] ___slab_alloc+0x486/0x4e0 mm/slub.c:2468
[< none >] __slab_alloc+0x66/0xc0 mm/slub.c:2497
[< inline >] slab_alloc_node mm/slub.c:2560
[< inline >] slab_alloc mm/slub.c:2602
[< none >] kmem_cache_alloc_trace+0x284/0x310 mm/slub.c:2619
[< inline >] kmalloc include/linux/slab.h:458
[< inline >] kzalloc include/linux/slab.h:602
[< none >] snd_timer_instance_new+0x52/0x3a0 sound/core/timer.c:105
[< none >] snd_timer_open+0x4ff/0xc50 sound/core/timer.c:286
[< none >] snd_seq_timer_open+0x223/0x540
sound/core/seq/seq_timer.c:279
[< none >] snd_seq_queue_use+0x147/0x230
sound/core/seq/seq_queue.c:526
[< none >] snd_seq_queue_alloc+0x36a/0x4d0
sound/core/seq/seq_queue.c:197
[< none >] snd_seq_ioctl_create_queue+0xdb/0x2b0
sound/core/seq/seq_clientmgr.c:1536
[< none >] snd_seq_do_ioctl+0x19a/0x1c0
sound/core/seq/seq_clientmgr.c:2209
[< none >] snd_seq_ioctl+0x5d/0x80 sound/core/seq/seq_clientmgr.c:2224
[< inline >] vfs_ioctl fs/ioctl.c:43
[< none >] do_vfs_ioctl+0x681/0xe40 fs/ioctl.c:607
[< inline >] SYSC_ioctl fs/ioctl.c:622
[< none >] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:613
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185

INFO: Freed in snd_timer_close+0x351/0x5e0 age=10 cpu=3 pid=6345
[< none >] __slab_free+0x1fc/0x320 mm/slub.c:2678
[< inline >] slab_free mm/slub.c:2833
[< none >] kfree+0x2a8/0x2d0 mm/slub.c:3662
[< none >] snd_timer_close+0x351/0x5e0 sound/core/timer.c:364
[< none >] snd_seq_timer_close+0x9e/0x100
sound/core/seq/seq_timer.c:312
[< none >] snd_seq_queue_timer_close+0x28/0x50
sound/core/seq/seq_queue.c:473
[< none >] snd_seq_ioctl_set_queue_timer+0x159/0x300
sound/core/seq/seq_clientmgr.c:1809
[< none >] snd_seq_do_ioctl+0x19a/0x1c0
sound/core/seq/seq_clientmgr.c:2209
[< none >] snd_seq_ioctl+0x5d/0x80 sound/core/seq/seq_clientmgr.c:2224
[< inline >] vfs_ioctl fs/ioctl.c:43
[< none >] do_vfs_ioctl+0x681/0xe40 fs/ioctl.c:607
[< inline >] SYSC_ioctl fs/ioctl.c:622
[< none >] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:613
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185

INFO: Slab 0xffffea0000d5b400 objects=22 used=8 fp=0xffff8800356d0b60
flags=0x1fffc0000004080
INFO: Object 0xffff8800356d0b60 @offset=2912 fp=0xffff8800356d27d0
CPU: 0 PID: 6313 Comm: syz-executor Tainted: G B 4.4.0+ #222
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
00000000ffffffff ffff880036757748 ffffffff82904add ffff88003e807000
ffff8800356d0b60 ffff8800356d0000 ffff880036757778 ffffffff8172af94
ffff88003e807000 ffffea0000d5b400 ffff8800356d0b60 ffff8800356d0b60

Call Trace:
[<ffffffff817344ae>] __asan_report_load4_noabort+0x3e/0x40
mm/kasan/report.c:294
[<ffffffff84aefda4>] _snd_timer_stop+0x394/0x450 sound/core/timer.c:488
[<ffffffff84aefe84>] snd_timer_stop+0x24/0x140 sound/core/timer.c:535
[<ffffffff84b6947e>] snd_seq_timer_close+0x7e/0x100
sound/core/seq/seq_timer.c:311
[<ffffffff84b6235b>] queue_delete+0x3b/0x90 sound/core/seq/seq_queue.c:146
[<ffffffff84b63f86>] snd_seq_queue_client_leave+0x36/0x130
sound/core/seq/seq_queue.c:593
[<ffffffff84b558a8>] seq_free_client1+0x58/0x290
sound/core/seq/seq_clientmgr.c:273
[<ffffffff84b55b45>] seq_free_client+0x65/0x160
sound/core/seq/seq_clientmgr.c:299
[<ffffffff84b5882d>] snd_seq_release+0x4d/0xb0
sound/core/seq/seq_clientmgr.c:380
[<ffffffff8177b453>] __fput+0x233/0x780 fs/file_table.c:208
[<ffffffff8177ba25>] ____fput+0x15/0x20 fs/file_table.c:244
[<ffffffff8139a8fb>] task_work_run+0x16b/0x200 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff81347b4b>] do_exit+0x8bb/0x2b20 kernel/exit.c:750
[<ffffffff81349f28>] do_group_exit+0x108/0x320 kernel/exit.c:880
[<ffffffff8136d124>] get_signal+0x5e4/0x1500 kernel/signal.c:2307
[<ffffffff81192d83>] do_signal+0x83/0x1c90 arch/x86/kernel/signal.c:712
[<ffffffff81006685>] exit_to_usermode_loop+0x1a5/0x210
arch/x86/entry/common.c:247
[< inline >] prepare_exit_to_usermode arch/x86/entry/common.c:282
[<ffffffff8100851a>] syscall_return_slowpath+0x2ba/0x340
arch/x86/entry/common.c:344
[<ffffffff85e74a62>] int_ret_from_sys_call+0x25/0x9f
arch/x86/entry/entry_64.S:281
==================================================================

On commit afd2ff9b7e1b367172f18ba7f693dfb62bdcb2dc (Jan 10).
snd_timer_stop

Takashi Iwai

unread,
Jan 12, 2016, 9:05:25 AM1/12/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jie Yang, Mark Brown, Jaroslav Kysela, LKML, Eric Dumazet, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
On Tue, 12 Jan 2016 11:22:09 +0100,
Dmitry Vyukov wrote:
>
> Hello,
>
> I've hit the following use-after-free while running syzkaller fuzzer.
> It is followed by a splat of other reports and finally kernel death.
> I wasn't able to reproduce it with a standalone C program (there is
> probably some global state involved). But it reproduces by replaying
> fuzzer logs in a loop (you will need Go toolchain):
>
> $ go get github.com/google/syzkaller
> $ cd $GOPATH/src/github.com/google/syzkaller
> $ make executor execprog

Just a note: I had to run "mkdir bin" beforehand.
Also for my distro, I had to remove -static.

> $ scp bin/syz-executor bin/syz-execprog your@machine
> $ scp snd_timer_stop your@machine # the attached file
> on test machine:
> $ ./syz-execprog -executor ./syz-executor -cover=0 -repeat=0 -procs=16
> snd_timer_stop

I tried this but couldn't reproduce the issue on my machine,
unfortunately. (Instead I hit another kernel panic regarding apparmor
:)

But looking through your log, it seems like a missing race
protection. Does the patch below work for you?


thanks,

Takashi

---
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 7dfd0f429410..8ea17d0a4299 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -142,8 +142,10 @@ static struct snd_seq_queue *queue_new(int owner, int locked)
static void queue_delete(struct snd_seq_queue *q)
{
/* stop and release the timer */
+ mutex_lock(&q->timer_mutex);
snd_seq_timer_stop(q->timer);
snd_seq_timer_close(q);
+ mutex_unlock(&q->timer_mutex);
/* wait until access free */
snd_use_lock_sync(&q->use_lock);
/* release resources... */
@@ -470,7 +472,9 @@ int snd_seq_queue_timer_close(int queueid)
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
+ mutex_lock(&queue->timer_mutex);
snd_seq_timer_close(queue);
+ mutex_unlock(&queue->timer_mutex);
queuefree(queue);
return result;
}

Takashi Iwai

unread,
Jan 12, 2016, 9:16:25 AM1/12/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jie Yang, Mark Brown, Jaroslav Kysela, LKML, Eric Dumazet, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
Gah, scratch this. The second hunk causes a deadlock.
The revised patch is below (just containing the first hunk).


Takashi

---
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 7dfd0f429410..0bec02e89d51 100644

Dmitry Vyukov

unread,
Jan 12, 2016, 11:46:35 AM1/12/16
to Takashi Iwai, alsa-...@alsa-project.org, Jie Yang, Mark Brown, Jaroslav Kysela, LKML, Eric Dumazet, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
Yes, this patch fixes the crashes for me.
Reproduction may require running syz-execprog for several minutes.

Tested-by: Dmitry Vyukov <dvy...@google.com>

Takashi Iwai

unread,
Jan 12, 2016, 11:52:19 AM1/12/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jie Yang, Mark Brown, Jaroslav Kysela, LKML, Eric Dumazet, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
Good to hear. FWIW, below is the final patch I'm going to queue.
Thanks!


Takashi

-- 8< --
From: Takashi Iwai <ti...@suse.de>
Subject: [PATCH] ALSA: seq: Fix race at timer setup and close

ALSA sequencer code has an open race between the timer setup ioctl and
the close of the client. This was triggered by syzkaller fuzzer, and
a use-after-free was caught there as a result.

This patch papers over it by adding a proper queue->timer_mutex lock
around the timer-related calls in the relevant code path.

Reported-by: Dmitry Vyukov <dvy...@google.com>
Tested-by: Dmitry Vyukov <dvy...@google.com>
Cc: <sta...@vger.kernel.org>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
sound/core/seq/seq_queue.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 7dfd0f429410..0bec02e89d51 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -142,8 +142,10 @@ static struct snd_seq_queue *queue_new(int owner, int locked)
static void queue_delete(struct snd_seq_queue *q)
{
/* stop and release the timer */
+ mutex_lock(&q->timer_mutex);
snd_seq_timer_stop(q->timer);
snd_seq_timer_close(q);
+ mutex_unlock(&q->timer_mutex);
/* wait until access free */
snd_use_lock_sync(&q->use_lock);
/* release resources... */
--
2.7.0

Reply all
Reply to author
Forward
0 new messages