sound: use-after-free in _snd_timer_stop
From: Dmitry Vyukov
Date: Mon Jan 25 2016 - 15:13:52 EST
Hello,
The following program causes use-after-free in _snd_timer_stop (if
run in a parallel loop):
// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
long r[53];
void* thr(void* arg)
{
switch ((long)arg) {
case 0:
r[0] = syscall(SYS_mmap, 0x20000000ul, 0x65e000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);
break;
case 1:
r[11] = open("/dev/snd/timer", O_RDWR);
break;
case 2:
*(uint32_t*)0x20653000 = (uint32_t)0x0;
*(uint32_t*)0x20653004 = (uint32_t)0x2;
*(uint32_t*)0x20653008 = (uint32_t)0x0;
*(uint32_t*)0x2065300c = (uint32_t)0x0;
*(uint32_t*)0x20653010 = (uint32_t)0x0;
*(uint8_t*)0x20653014 = (uint8_t)0x0;
*(uint8_t*)0x20653015 = (uint8_t)0x0;
*(uint8_t*)0x20653016 = (uint8_t)0x0;
*(uint8_t*)0x20653017 = (uint8_t)0x0;
*(uint8_t*)0x20653018 = (uint8_t)0x0;
*(uint8_t*)0x20653019 = (uint8_t)0x0;
*(uint8_t*)0x2065301a = (uint8_t)0x0;
*(uint8_t*)0x2065301b = (uint8_t)0x0;
*(uint8_t*)0x2065301c = (uint8_t)0x0;
*(uint8_t*)0x2065301d = (uint8_t)0x0;
*(uint8_t*)0x2065301e = (uint8_t)0x0;
*(uint8_t*)0x2065301f = (uint8_t)0x0;
*(uint8_t*)0x20653020 = (uint8_t)0x0;
*(uint8_t*)0x20653021 = (uint8_t)0x0;
*(uint8_t*)0x20653022 = (uint8_t)0x0;
*(uint8_t*)0x20653023 = (uint8_t)0x0;
*(uint8_t*)0x20653024 = (uint8_t)0x0;
*(uint8_t*)0x20653025 = (uint8_t)0x0;
*(uint8_t*)0x20653026 = (uint8_t)0x0;
*(uint8_t*)0x20653027 = (uint8_t)0x0;
*(uint8_t*)0x20653028 = (uint8_t)0x0;
*(uint8_t*)0x20653029 = (uint8_t)0x0;
*(uint8_t*)0x2065302a = (uint8_t)0x0;
*(uint8_t*)0x2065302b = (uint8_t)0x0;
*(uint8_t*)0x2065302c = (uint8_t)0x0;
*(uint8_t*)0x2065302d = (uint8_t)0x0;
*(uint8_t*)0x2065302e = (uint8_t)0x0;
*(uint8_t*)0x2065302f = (uint8_t)0x0;
*(uint8_t*)0x20653030 = (uint8_t)0x0;
*(uint8_t*)0x20653031 = (uint8_t)0x0;
*(uint8_t*)0x20653032 = (uint8_t)0x0;
*(uint8_t*)0x20653033 = (uint8_t)0x0;
r[49] = syscall(SYS_ioctl, r[11], 0x40345410ul, 0x20653000ul, 0, 0, 0);
break;
case 3:
r[50] = syscall(SYS_ioctl, r[11], 0x54a2ul, 0, 0, 0, 0);
break;
case 4:
open("/dev/sequencer", O_RDWR);
break;
}
return 0;
}
int main()
{
long i;
pthread_t th[5];
srand(getpid());
memset(r, -1, sizeof(r));
for (i = 0; i < 5; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
usleep(10000);
}
for (i = 0; i < 5; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
if (rand()%2)
usleep(rand()%10000);
}
usleep(100000);
return 0;
}
BUG: KASAN: use-after-free in snd_timer_notify1+0x42b/0x460 at addr
ffff8800331c88b8
Read of size 8 by task a.out/7186
=============================================================================
BUG kmalloc-256 (Tainted: G B W ): kasan: bad access detected
-----------------------------------------------------------------------------
INFO: Allocated in snd_timer_instance_new+0x52/0x3a0 age=105 cpu=0 pid=7291
[< none >] ___slab_alloc+0x4c2/0x500 mm/slub.c:2470
[< none >] __slab_alloc+0x66/0xc0 mm/slub.c:2499
[< inline >] slab_alloc_node mm/slub.c:2562
[< inline >] slab_alloc mm/slub.c:2604
[< none >] kmem_cache_alloc_trace+0x27a/0x300 mm/slub.c:2621
[< inline >] kmalloc include/linux/slab.h:463
[< inline >] kzalloc include/linux/slab.h:607
[< none >] snd_timer_instance_new+0x52/0x3a0 sound/core/timer.c:106
[< none >] snd_timer_open+0xbb/0xd20 sound/core/timer.c:251
[< inline >] snd_timer_user_tselect sound/core/timer.c:1572
[< inline >] __snd_timer_user_ioctl sound/core/timer.c:1848
[< none >] snd_timer_user_ioctl+0x8db/0x25f0 sound/core/timer.c:1878
[< inline >] vfs_ioctl fs/ioctl.c:43
[< none >] do_vfs_ioctl+0x18c/0xfb0 fs/ioctl.c:674
[< inline >] SYSC_ioctl fs/ioctl.c:689
[< none >] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:680
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
INFO: Freed in snd_timer_close+0x55d/0x750 age=10 cpu=0 pid=7333
[< none >] __slab_free+0x1fc/0x320 mm/slub.c:2680
[< inline >] slab_free mm/slub.c:2835
[< none >] kfree+0x2b7/0x2e0 mm/slub.c:3664
[< none >] snd_timer_close+0x55d/0x750 sound/core/timer.c:375
[< inline >] snd_timer_user_tselect sound/core/timer.c:1562
[< inline >] __snd_timer_user_ioctl sound/core/timer.c:1848
[< none >] snd_timer_user_ioctl+0x7b6/0x25f0 sound/core/timer.c:1878
[< inline >] vfs_ioctl fs/ioctl.c:43
[< none >] do_vfs_ioctl+0x18c/0xfb0 fs/ioctl.c:674
[< inline >] SYSC_ioctl fs/ioctl.c:689
[< none >] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:680
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
INFO: Slab 0xffffea0000cc7200 objects=22 used=16 fp=0xffff8800331cbbb8
flags=0x1fffc0000004080
INFO: Object 0xffff8800331c8888 @offset=2184 fp=0xffff8800331c9998
CPU: 2 PID: 7186 Comm: a.out Tainted: G B W 4.5.0-rc1+ #283
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
00000000ffffffff ffff88003372f700 ffffffff8299a06d ffff88003e807000
ffff8800331c8888 ffff8800331c8000 ffff88003372f730 ffffffff81752854
ffff88003e807000 ffffea0000cc7200 ffff8800331c8888 ffff88003372f878
Call Trace:
[< inline >] kasan_report mm/kasan/report.c:274
[<ffffffff8175befe>] __asan_report_load8_noabort+0x3e/0x40
mm/kasan/report.c:295
[<ffffffff84f5ea5b>] snd_timer_notify1+0x42b/0x460 sound/core/timer.c:424
[<ffffffff84f5ed52>] _snd_timer_stop+0x2c2/0x670 sound/core/timer.c:537
[<ffffffff84f5f122>] snd_timer_stop+0x22/0x140 sound/core/timer.c:552
[<ffffffff84fdf617>] snd_seq_timer_close+0x77/0x130
sound/core/seq/seq_timer.c:311
[<ffffffff84fd834e>] queue_delete+0x4e/0xb0 sound/core/seq/seq_queue.c:147
[<ffffffff84fd85bc>] snd_seq_queue_delete+0x3c/0x60
sound/core/seq/seq_queue.c:213
[<ffffffff84fcd84a>] snd_seq_ioctl_delete_queue+0xca/0x120
sound/core/seq/seq_clientmgr.c:1569
[<ffffffff84fcf4ad>] snd_seq_do_ioctl+0x19d/0x1c0
sound/core/seq/seq_clientmgr.c:2209
[<ffffffff84fd0ecb>] snd_seq_kernel_client_ctl+0xdb/0x170
sound/core/seq/seq_clientmgr.c:2423
[<ffffffff84fe7e19>] delete_seq_queue.part.3+0x99/0xf0
sound/core/seq/oss/seq_oss_init.c:389
[< inline >] delete_seq_queue sound/core/seq/oss/seq_oss_init.c:385
[<ffffffff84fe8c3b>] snd_seq_oss_release+0xfb/0x130
sound/core/seq/oss/seq_oss_init.c:434
[<ffffffff84fe724a>] odev_release+0x5a/0x80 sound/core/seq/oss/seq_oss.c:155
[<ffffffff817b2376>] __fput+0x236/0x780 fs/file_table.c:208
[<ffffffff817b2945>] ____fput+0x15/0x20 fs/file_table.c:244
[<ffffffff813ad760>] task_work_run+0x170/0x210 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff81358da5>] do_exit+0x8b5/0x2c60 kernel/exit.c:748
[<ffffffff8135b2c8>] do_group_exit+0x108/0x330 kernel/exit.c:878
[< inline >] SYSC_exit_group kernel/exit.c:889
[<ffffffff8135b50d>] SyS_exit_group+0x1d/0x20 kernel/exit.c:887
[<ffffffff86359636>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
==================================================================
181.377203] ------------[ cut here ]------------
WARNING: CPU: 1 PID: 29599 at lib/list_debug.c:68 __list_del_entry+0x14c/0x1e0()
list_del corruption. prev->next should be ffff88006346f690, but was
ffff8800351ebc40
Modules linked in:
CPU: 1 PID: 29599 Comm: a.out Not tainted 4.5.0-rc1+ #283
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
00000000ffffffff ffff88003437fa78 ffffffff8299a06d ffff88003437fae8
ffff880034208000 ffffffff866fd220 ffff88003437fab8 ffffffff8134fcf9
ffffffff82a0187c ffffed000686ff59 ffffffff866fd220 0000000000000044
Call Trace:
[< inline >] __dump_stack lib/dump_stack.c:15
[<ffffffff8299a06d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
[<ffffffff8134fcf9>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
[<ffffffff8134fe09>] warn_slowpath_fmt+0xa9/0xd0 kernel/panic.c:494
[<ffffffff82a0187c>] __list_del_entry+0x14c/0x1e0 lib/list_debug.c:66
[< inline >] list_del_init include/linux/list.h:156
[<ffffffff84f5edf6>] _snd_timer_stop+0x366/0x670 sound/core/timer.c:507
[<ffffffff84f5f122>] snd_timer_stop+0x22/0x140 sound/core/timer.c:552
[<ffffffff84f5f273>] snd_timer_close+0x33/0x750 sound/core/timer.c:322
[<ffffffff84f5fa27>] snd_timer_user_release+0x97/0x130 sound/core/timer.c:1322
[<ffffffff817b2376>] __fput+0x236/0x780 fs/file_table.c:208
[<ffffffff817b2945>] ____fput+0x15/0x20 fs/file_table.c:244
[<ffffffff813ad760>] task_work_run+0x170/0x210 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff81358da5>] do_exit+0x8b5/0x2c60 kernel/exit.c:748
[<ffffffff8135b2c8>] do_group_exit+0x108/0x330 kernel/exit.c:878
[< inline >] SYSC_exit_group kernel/exit.c:889
[<ffffffff8135b50d>] SyS_exit_group+0x1d/0x20 kernel/exit.c:887
[<ffffffff86359636>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
---[ end trace e005332b84fa3a56 ]---
==================================================================
Later the machine usually hangs.
On commit 92e963f50fc74041b5e9e744c330dca48e04f08d