sound: out-of-bounds write in snd_rawmidi_kernel_write1

52 views
Skip to first unread message

Dmitry Vyukov

unread,
Feb 3, 2016, 3:58:10 AM2/3/16
to Jaroslav Kysela, Takashi Iwai, alsa-...@alsa-project.org, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin
Hello,

The following program triggers an out-of-bounds write in
snd_rawmidi_kernel_write1 (run in parallel loop). It seems to try to
copy -1 bytes (aka 4GB) from user space into kernel smashing all on
its way.

==================================================================
BUG: KASAN: use-after-free in memset+0x1a/0x30 at addr ffff8800326e3cef
Write of size 4294950912 by task a.out/7292
=============================================================================
BUG kmalloc-4096 (Not tainted): kasan: bad access detected
-----------------------------------------------------------------------------

INFO: Allocated in open_substream+0x2ff/0x780 age=288 cpu=1 pid=7287
[< none >] ___slab_alloc+0x564/0x5b0 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+0x25c/0x300 mm/slub.c:2621
[< inline >] kmalloc include/linux/slab.h:463
[< inline >] snd_rawmidi_runtime_create sound/core/rawmidi.c:127
[< none >] open_substream+0x2ff/0x780 sound/core/rawmidi.c:266
[< none >] rawmidi_open_priv+0x144/0x300 sound/core/rawmidi.c:312
[< none >] snd_rawmidi_open+0x3fb/0xa90 sound/core/rawmidi.c:416
[< none >] soundcore_open+0x30f/0x640 sound/sound_core.c:639
[< none >] chrdev_open+0x22a/0x4c0 fs/char_dev.c:388
[< none >] do_dentry_open+0x6a2/0xcb0 fs/open.c:736
[< none >] vfs_open+0x17b/0x1f0 fs/open.c:853
[< inline >] do_last fs/namei.c:3254
[< none >] path_openat+0xde9/0x5e30 fs/namei.c:3386
[< none >] do_filp_open+0x18e/0x250 fs/namei.c:3421
[< none >] do_sys_open+0x1fc/0x420 fs/open.c:1022
[< inline >] SYSC_open fs/open.c:1040
[< none >] SyS_open+0x2d/0x40 fs/open.c:1035
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185

Call Trace:
[<ffffffff817654b7>] __asan_storeN+0x127/0x1a0 mm/kasan/kasan.c:522
[<ffffffff8176582a>] memset+0x1a/0x30 mm/kasan/kasan.c:280
[<ffffffff82c15294>] copy_user_handle_tail+0xb4/0xd0
arch/x86/lib/usercopy_64.c:86
[< inline >] copy_from_user ./arch/x86/include/asm/uaccess.h:735
[<ffffffff852855da>] snd_rawmidi_kernel_write1+0x34a/0x760
sound/core/rawmidi.c:1250
[<ffffffff852878b3>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1318
[<ffffffff817b8be1>] do_loop_readv_writev+0x141/0x1e0 fs/read_write.c:719
[<ffffffff817bcb38>] do_readv_writev+0x5f8/0x6e0 fs/read_write.c:849
[<ffffffff817bcd56>] vfs_writev+0x86/0xc0 fs/read_write.c:886
[< inline >] SYSC_writev fs/read_write.c:919
[<ffffffff817bfec1>] SyS_writev+0x111/0x2b0 fs/read_write.c:911
[<ffffffff86661376>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
==================================================================

// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include <pthread.h>
#include <stdint.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>

long r[19];

int main()
{
memset(r, -1, sizeof(r));
r[0] = syscall(SYS_mmap, 0x20000000ul, 0x22000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);
r[2] = syscall(SYS_open, "/dev/midi3", 0x2ul, 0, 0, 0);
*(uint64_t*)0x20013ffe = (uint64_t)0x20013f69;
*(uint64_t*)0x20014006 = (uint64_t)0x97;
*(uint64_t*)0x2001400e = (uint64_t)0x20003ffe;
*(uint64_t*)0x20014016 = (uint64_t)0x3;
*(uint64_t*)0x2001401e = (uint64_t)0x2001ef70;
*(uint64_t*)0x20014026 = (uint64_t)0x92;
*(uint64_t*)0x2001402e = (uint64_t)0x20014730;
*(uint64_t*)0x20014036 = (uint64_t)0x1;
*(uint64_t*)0x2001403e = (uint64_t)0x2001e000;
*(uint64_t*)0x20014046 = (uint64_t)0x1000;
memcpy((void*)0x20013f69,
"\x0e\x6f\xfe\xa4\xc8\xbf\xaa\x28\x69\x82\xe0\x8c\x45\xab\x90"
"\xb9\x6a\xeb\x50\x3d\x1a\x59\x59\x33\x0a\xa5\xb8\xfe\x83\x75"
"\x1f\xb5\x25\x76\x65\x53\xb6\xe7\xe2\xe7\xe3\xd7\x55\x36\xb6"
"\x59\x2f\xf8\x61\xda\xdb\x73\x32\x94\xb1\x0e\x17\x87\xad\x8f"
"\x73\x6c\xc7\xeb\x47\xa2\x65\x77\xfb\xfc\xec\x70\x5c\x9e\x01"
"\x78\xef\x1b\x69\xab\xef\x58\x13\x35\x99\xf0\x2b\x25\x99\xdb"
"\xba\x16\xa7\x43\xc5\x19\x32\x91\x13\x24\x15\xd1\x5e\xb0\x1a"
"\x5f\x63\xe2\xc3\x61\x9a\x79\x82\x57\x60\x21\x79\x6e\xf5\x21"
"\x74\x18\xcf\x8f\x73\x93\x70\x3a\xfe\xf8\xe3\xde\x6a\x85\x3b"
"\x5a\xfc\x0b\xfe\x02\x8f\x32\xe6\xc5\x14\x1c\x07\x24\xce\xcb"
"\x95",
151);
memcpy((void*)0x20003ffe, "\x3d\x07\x31", 3);
memcpy((void*)0x2001ef70,
"\x5c\x39\xe0\x3f\xe7\xdd\x08\xeb\x7c\xb0\xe7\x31\x09\xdf\x84"
"\x1a\xbb\x98\xe1\xc8\x08\x00\x3b\xe9\xef\x62\x4a\x18\x10\xff"
"\xa1\x7f\xa0\xd6\x81\x86\xed\xb5\x43\x33\x7c\xa6\x01\xb8\xfc"
"\xe1\xee\x43\x95\x05\xf1\x5d\xa6\xb4\xb1\x62\x74\x82\xc6\x8b"
"\x9f\xfb\x9b\xe8\x41\xee\x2e\x44\xc0\x20\x37\xca\xe5\x33\xf3"
"\xeb\x9e\x2e\x15\x56\xce\x26\x5e\x6c\xee\xca\x49\x00\xe6\xf2"
"\x21\xd4\x07\xf1\x00\xee\x21\x5a\xd5\x7a\x84\x4c\x3e\x7c\x8d"
"\xe5\xb5\x35\x57\x69\xe4\x18\x09\x5b\xa7\xdb\xe6\x2f\x56\x78"
"\x83\xa1\x0c\xdd\x07\x74\x32\xb2\x85\x75\xeb\x51\x5b\x22\xd1"
"\x57\x95\xcd\xc2\xc4\xf9\x2e\xd8\xce\x9a\x52",
146);
memcpy((void*)0x20014730, "\xc3", 1);
memcpy(
(void*)0x2001e000,
"\xff\x20\xcc\xa3\x99\x07\x76\x17\xc4\x29\xef\xa5\x6a\xef\x9c\x9b"
"\x58\x94\x16\xfc\x87\x60\xb1\x04\x16\x80\x1d\xcb\xfd\x8b\xd7\x9a"
"\x41\x87\xb2\xdf\xe8\xc3\x17\x50\xd6\x5a\x01\x06\xc7\xc5\xb1\xf3"
"\x56\x57\x81\xa8\x2c\x0b\x81\x67\x93\x59\xc1\xbb\xb5\x2d\x45\xc5"
"\x27\x05\x66\x0b\xfd\x28\x1e\xdb\x45\x89\x34\x0b\x03\xfe\x5f\xa7"
"\x47\xeb\xa1\xe0\xff\xe1\xdb\x12\xa7\x11\x37\xe0\x96\x53\xa2\x29"
"\x1d\x3c\x3c\xda\x8e\x97\xeb\x58\x64\x8d\xff\x13\x70\x08\x96\x28"
"\x32\x4e\xce\x4c\xb3\x17\x1c\x74\xa8\x8d\x7b\x78\x32\x4b\xcc\xf8"
"\xf7\xcb\x33\x5c\xd5\x6b\xa3\x2a\x9c\x7c\x41\x3e\x87\x92\xec\x22"
"\x44\x36\x28\x2d\x76\xde\x44\xa8\xef\x9d\x2c\xa2\xf2\xc5\x94\x2b"
"\x3a\x17\xa4\xd7\x82\x4e\xef\xee\x1a\x4a\x6b\x98\xd5\xe4\x40\xbc"
"\x5a\xe1\x76\x47\x17\x2b\x45\xb6\xb6\xa4\xeb\x5a\x54\x82\x6a\x98"
"\x14\xf0\x4e\x5a\x8c\x30\x6a\x0f\xcb\x0f\x1b\x62\x8c\x48\x54\x16"
"\xb8\x94\x28\xd0\xcc\x47\x4f\xb4\x01\x40\x3c\xb7\xed\xf0\x96\x2a"
"\x55\xb2\xac\xf6\xa2\xab\x93\x19\x3f\xf6\xf8\xad\x8f\xa3\x5a\x6f"
"\x15\x26\xa3\x25\xbb\x58\x6e\x02\x58\xfa\x3a\xcf\xd9\xf8\x17\xb9"
"\xa1\x4c\x45\x16\x45\xcb\x7a\x84\x37\x3a\xb4\x3a\xc6\x98\xa9\x5c"
"\xf4\x9e\xdb\xcf\xa9\xbb\xcc\xcb\x15\x36\x52\xb0\xcc\x3d\xd0\xfa"
"\xd6\xc0\xff\xf6\xb7\x0e\x80\x31\x8e\x76\xfc\xe9\xd8\xf6\xb4\xbc"
"\xfa\xec\x94\x13\x64\x9d\x13\x7e\x91\x9c\x10\x27\xda\xc8\xea\x9b"
"\xc2\x09\x58\x81\x9e\x44\xf2\xc3\xef\x94\x6d\x2f\xa9\xa5\x19\xd7"
"\x78\x61\x2e\xd3\x01\x8a\xc3\xac\x1b\xb9\xaa\x00\x12\xc5\x7e\x7f"
"\x7b\x34\x27\x4c\x38\x00\x9c\x57\xa6\xe2\x5a\x5a\xe6\x00\x01\x56"
"\xa2\xed\xa6\xcd\x95\x0b\xde\x5e\x09\x62\x61\x7c\x2b\x16\x13\xb4"
"\x04\xf8\x1a\x5b\x15\x9d\x62\xd5\xac\x4b\x5b\x35\x70\xd0\xe2\x26"
"\xf9\xc0\x7c\x73\xad\x9c\xd5\xef\x7b\x9f\x01\x8b\xb6\xb3\x85\xbf"
"\x34\xa2\x8c\xce\x8a\xaf\xe1\x5b\xdd\x7f\xa6\x23\x55\x8b\xa4\xa3"
"\x06\x2f\xf1\xa0\xd8\x2a\xcc\x9a\x94\x19\x22\xfe\x65\x69\x9b\xcb"
"\x6d\x6c\x1c\x38\x25\x82\x9b\xec\xe1\x75\xb4\xbe\xac\x21\x4b\xec"
"\xfd\x22\x76\xcb\x35\x4b\xaa\x5c\x3a\x7b\xaa\x6f\x3c\x68\xa7\xa5"
"\x3d\xa2\xd5\x25\x9a\xe4\x6f\x80\xc5\xb5\xcf\x76\x37\xd8\xd9\x25"
"\xe6\xc7\x26\x40\xdf\x1d\xd3\x41\xb2\x58\x69\xa7\x18\x57\xf8\x35"
"\x26\x70\x30\x08\x76\xed\x2b\x37\x2a\x54\x7d\xa5\x7a\x66\x8d\xbf"
"\x4a\x20\x3d\x1b\xd1\x28\x1e\x7e\xfe\xd3\xb1\x6c\x64\x87\x70\x27"
"\x9e\xcf\x07\xd9\x5a\x9e\xbb\xdb\x3b\xb2\xcb\x50\x78\x3c\x45\x76"
"\xec\x59\xa9\xca\xb2\x80\x8c\xc5\x62\x76\x8c\x76\x61\xb5\xf2\xcf"
"\x0f\x37\x7d\x44\x7f\xc3\x2c\xef\x7a\x07\x3b\xe2\xb9\x9b\x15\xc6"
"\xa6\xb5\xdf\x02\x12\x75\x7d\x8c\x09\x1a\x50\x91\x70\x46\xbb\x18"
"\xf7\x44\x05\xc8\xdb\x78\xa2\x87\xd6\x0a\x5f\x14\xf0\xaf\x61\xd7"
"\x14\x91\x31\xae\xad\xea\x05\xb3\xd7\xc3\xae\x57\xe5\xbe\x9a\x43"
"\xde\x55\xcc\x8e\x91\xac\x5c\xb5\xb9\x0a\x68\x28\x41\xdc\x09\x69"
"\x0b\x86\xa1\x46\x67\x96\x04\xf6\x2e\x6e\x07\x11\x62\xb5\x96\x09"
"\x2b\x5f\xcb\x7a\x9b\xcb\x77\x1b\x79\xb0\xab\x05\x89\x15\x5a\xcd"
"\xab\xd6\x82\x8c\xb0\x65\xc1\x88\x6c\x14\x60\x3d\x77\xf7\xb4\xc1"
"\xdf\x43\x0a\x80\x37\xc4\x82\x31\x27\x93\x2d\x93\x06\xfb\x92\xce"
"\x19\x3b\xb8\xcf\x4f\x42\xf6\x44\x7a\x5d\xed\xe7\x09\x79\x19\x42"
"\xb8\x30\x7e\x4b\x36\xd9\x75\x46\xd8\x7b\xba\x32\x01\x29\x8b\xec"
"\xdb\x66\xcf\x4b\x04\xde\x8d\x5e\x1d\xf1\x58\xc1\x3b\xcb\x04\x13"
"\x3d\x8a\x9e\xa8\x8f\xce\x0c\xed\x8c\x1e\xf0\x3e\x8c\x59\x14\x53"
"\x17\x9d\xb8\x47\x33\xbc\xa3\xe2\xdc\x16\xaf\xd2\x28\xe4\xfe\xa1"
"\xaf\x98\x7a\xc9\x4b\x3b\x38\xea\x8e\x1a\x36\x3d\xb4\xb8\x9d\x28"
"\xbc\xc6\x9f\xd4\x21\xa9\x52\xbd\x1c\x77\x69\xb8\x41\x0e\x66\x9a"
"\x29\x99\x50\x4c\x76\x46\x99\xcc\xbc\x5a\x23\x1c\x19\xbb\x25\x07"
"\xf5\xb3\x5c\x38\x9d\xed\xc5\x85\xea\xb4\xd6\x14\xdb\xd1\x54\xb7"
"\x13\xec\xcb\x24\xce\x8c\xf9\xb5\xc7\xbe\x54\x17\x29\x19\xa2\xaf"
"\xb6\xd3\x14\xae\x83\xa7\x43\xb7\xbe\x28\xba\x2c\x52\xc0\xaa\x37"
"\x98\x14\x87\xe9\xbd\x2e\x1c\x93\x29\xd4\xad\x87\x4e\x9a\x7b\x94"
"\x30\x72\x68\x31\x2c\xa5\x2b\xed\x52\xc9\x31\x43\xf1\x2c\x77\xcb"
"\x73\x64\x07\x3f\x8a\x59\x59\xf3\x8a\x9c\x9e\xb0\xb6\x7b\x8d\x0e"
"\x6b\x5a\x33\xcd\x04\x5e\x77\x93\xd4\x23\xb0\xbe\xca\x08\x95\xd6"
"\x02\xd2\x22\xbb\x8d\x4c\xbc\x68\x6b\xc7\x6f\x47\x3d\x78\x4e\x56"
"\xaf\x86\x11\x9f\x8b\x16\x22\x8b\x93\x89\x10\x58\xaa\x1a\xaf\x97"
"\xc7\x33\x97\xcd\x6d\xb2\x17\xa3\x90\xd5\x92\x5e\xb7\xeb\x9f\x13"
"\x02\x34\xa3\x2c\xe8\x0c\xc9\xf0\xe6\xda\x06\x70\xe5\x87\xe9\xbf"
"\x8e\x68\x34\x5a\xfb\xe5\x39\x6a\xde\xc4\x15\xae\x4c\xe0\x6e\x0b"
"\x42\x2f\x2a\x77\xd3\x5b\x69\xa0\x07\xaf\x1c\x55\xa8\x28\x24\x81"
"\xc0\x34\xd5\xde\xca\xcf\xa9\x85\x58\x90\xd4\x5b\xf3\x73\xd1\xfb"
"\xc4\x25\x64\xb0\x15\xf6\x98\x73\x65\x38\x89\x72\xa6\x5b\x5e\xdb"
"\xca\x92\xeb\x39\xb9\x90\x29\x18\x72\xeb\xee\xa0\x90\x1a\x34\x4c"
"\x62\x4f\xd9\x2f\x69\x49\x88\x4c\x24\x26\x02\x3b\x74\x12\xf1\x4c"
"\x78\x25\xbb\xd3\x26\xc9\x25\xf0\xda\x68\x5a\x50\x7b\x69\x90\x9e"
"\xd7\x50\x07\x9d\x4d\xec\x0b\xf8\x88\x78\x2b\xb9\x9e\x9a\x41\x40"
"\x7f\xbe\xad\x6f\x4d\x3e\x83\x7f\x6a\x89\x79\x32\x68\x97\x37\x96"
"\x90\x41\xde\x3a\x69\x49\xf3\x7e\x0a\xb6\x4a\x0f\x3c\x41\x69\x8a"
"\xcb\xad\xb7\xe7\xf4\x59\x95\xa5\xf4\x8d\xac\xeb\xdf\x07\xf3\x1e"
"\x81\x52\x66\x19\xb4\x07\xe6\x63\x0e\xda\x2d\x0e\xf6\x72\x94\x84"
"\x53\x70\x22\x0e\x46\xa6\xe5\x4e\x9d\x34\x38\xa1\x6d\x2b\xdf\xa9"
"\x67\x33\x81\xcf\xa5\x92\xff\x94\x2b\x19\x1f\x55\x05\xd8\xbc\x2d"
"\xab\x7b\x15\xa2\x4c\xe7\xcb\xdb\x96\xfc\xb2\x51\x34\xb4\x84\xba"
"\x1d\x68\x7a\xff\x64\x71\xa8\x46\x12\x97\xe6\xf5\x14\x4e\xf5\xcb"
"\x72\xce\xaf\x3e\xf7\x60\x27\x42\xa0\x92\xdf\x90\x86\x40\x55\x94"
"\x95\x11\xf4\xe4\xbf\xbc\x6e\xa6\x7f\x3f\x01\x8c\xa6\x01\xa2\x4e"
"\x4e\x4d\xaf\x62\x3b\x55\x8d\x91\x34\x35\x43\x23\x51\x3b\xf6\x3e"
"\xbd\x79\x04\x25\x20\xc1\x13\x23\xe2\x46\x78\xde\xd5\x0d\xb6\x89"
"\x2c\x43\x71\x9a\x89\x8a\x3c\x70\xee\x20\x6b\x8b\x9c\x31\x48\x3a"
"\x41\x9a\xde\xf0\x18\x46\xee\x47\x09\xcb\xad\x2a\x6b\x95\x2d\x72"
"\xd7\x01\xf8\x68\xfe\x75\x37\x15\x6a\x15\x65\x8e\x95\x88\x66\x08"
"\xea\x31\x6d\xee\x8f\xc9\xac\x01\x06\x89\x3a\x82\x35\x79\x0a\x40"
"\x37\x51\x1a\x53\xd9\x85\xd6\x99\x12\xbf\xb6\xe0\x72\x3c\xc2\xfe"
"\x07\x1e\x92\xce\x18\x9f\xfb\xa0\xf6\xd3\x42\xbb\x41\xce\x31\x61"
"\x2f\xe1\x8d\x55\x80\x03\x16\xb0\xd9\x2d\xd3\x64\xca\x62\x49\x5f"
"\x3e\x28\xe6\x54\xd5\xb9\xdf\x7f\x5a\xcb\xa2\x87\xbc\x34\xbe\x06"
"\x0a\x4c\x77\x34\xa6\xae\xbd\xad\x22\x62\xf2\x56\x28\x99\x21\x4b"
"\x58\x68\x1f\xa5\xb6\x89\x5e\xa4\x76\x58\x60\x8a\x61\x17\x63\x77"
"\xbd\xef\x1c\x3e\xfd\xc2\x26\x29\x69\xd9\xa0\x6e\xef\x81\x6d\xec"
"\xa0\x14\xac\x42\x47\x77\xd5\x1e\xa5\xc7\x40\xa3\x7e\xac\x80\xf7"
"\x1f\x25\xa7\x04\x58\xbe\x65\x32\xe2\xb0\x47\x9d\x71\xa1\x5c\x60"
"\x25\xa6\x9c\xb4\x9d\x6f\xf3\xfc\x66\x51\x50\xaa\x98\x1b\x16\x57"
"\x66\xb8\xcc\x81\x30\x7c\x25\xd9\x6e\xef\x86\x3e\x05\xf5\x58\x51"
"\xd5\x5f\xec\x3b\x78\x5e\xe1\x20\x1b\x44\x8d\xee\x3d\x01\xd2\xbe"
"\x72\x54\x46\x71\xd7\x38\x65\xa4\xf8\x75\xa5\x30\xca\x74\x20\xb8"
"\xbe\xcf\x6f\x59\xa6\x52\x7b\x23\x4b\xf5\x90\x50\x12\x85\xf1\xd6"
"\xa2\x75\xf4\xd9\xd6\x52\xb1\xcd\x0b\x1f\x79\xfa\x0a\xda\xa0\x70"
"\xa1\x02\x78\xcb\xc4\x68\x16\x3f\xc4\x87\x6a\x0e\xb6\xba\x09\x26"
"\x3d\xc0\x0f\x38\xbd\x38\x4f\x04\x92\xdb\xe5\x2d\xf6\x07\x74\xcf"
"\x66\x9b\x02\x2f\x49\x71\xf8\x3c\xd2\x9c\x31\x5d\x3b\xd0\x17\x8d"
"\x90\xf3\x58\x4c\x5e\x41\xb7\x6e\x8c\xe4\x73\xd3\xd5\x76\x1b\x94"
"\xb0\x08\x11\xf7\x9e\x08\x4f\x3a\xd7\xdb\x69\x47\x77\xbb\xae\xc2"
"\x85\xf9\xfb\x0c\x1e\xfa\xaa\xb9\xe7\xb4\x1c\x1d\xf0\x4d\xd3\x95"
"\x57\x12\xea\xc4\x21\xb2\xa6\x45\x26\x4d\x1c\x91\xf0\x69\xda\xa1"
"\x09\x05\xd7\x6c\xe4\x3a\x08\xc8\x2d\xf0\x8b\xc8\x21\x99\xad\xf4"
"\xb9\x9c\x2a\x86\x88\xf1\x40\x31\xe0\xb4\xe8\xdd\xaf\x59\x0b\x38"
"\x9a\x57\xfb\xa0\x9c\xdc\x1d\xca\xab\x51\xb3\x20\xaa\x71\xca\x01"
"\x4a\x85\x3f\x5c\x0c\x3f\x22\x73\x0d\x0f\xbf\x3e\x0f\x05\x26\xb0"
"\xd0\x48\xb4\xe2\x5b\x83\xbd\x90\x30\x9e\xf3\xbd\xd6\x78\xc4\x7d"
"\x8a\xe8\x88\x72\x14\x30\x11\x51\xf3\x8d\x44\x8c\x17\xc2\x22\x04"
"\xcc\xea\x02\x38\x23\x43\x3a\x77\x1d\xcd\x95\xc2\xa2\xc2\xbc\xef"
"\x26\xec\x54\xab\xe3\x80\x7e\x77\x3b\xdf\x6a\xb9\x7e\xbf\x40\x93"
"\x87\x6d\x0e\x66\xb9\xce\x95\x1c\xb5\x2b\x86\x16\x90\x67\x1a\x87"
"\xe7\x96\x59\xb4\x96\x44\xf9\x31\x0c\x0c\xab\x1f\xfc\xac\x29\xee"
"\xbd\x51\x64\xb4\x21\x51\xf9\x4a\x74\x08\xaa\xbb\x49\xad\xf8\xc6"
"\x9f\x41\xe5\x30\xf9\xd1\x5b\x32\x4b\x0a\xb9\xba\x3a\xac\x90\xa1"
"\x12\xd7\x36\x8b\xba\x86\xe2\xe7\x5c\x3d\x27\xce\x8f\x83\x0a\x59"
"\x28\x6f\xe3\x71\x93\x4d\x89\xc1\x39\x3a\x0f\xdf\x68\x03\xe8\xf2"
"\x95\xa9\x71\x0f\x6d\xd5\x1d\xba\x50\x3c\x6a\xfe\xcf\xdd\xc4\x98"
"\xf3\xf2\xe8\x8a\xd6\xca\xfc\xb1\x42\x21\x37\x52\x97\xfb\x8d\x0a"
"\xe7\x72\x65\xc3\x4a\xf8\x4c\xb8\x04\xdd\x2e\x8e\xcd\xb3\x68\xe1"
"\xbf\x9c\xd3\xef\x0c\xe0\xda\xff\x9c\x6f\xab\xcc\x97\x53\xfa\xdd"
"\xd5\x47\xf1\xaa\x89\x9e\xa2\x1a\x5e\xb4\x18\xb3\x3f\xf8\xb8\x49"
"\x61\x81\xac\xd0\x5a\x7b\x5c\x77\x96\x4e\xd9\x70\x54\x69\x78\xd4"
"\x4e\xc1\xba\xe5\x0a\xc9\xec\x44\xd6\x00\x66\xe7\xd8\x31\x51\x7f"
"\x18\xef\xee\x6a\x6c\xb9\x27\x34\xe9\x91\x28\x54\xd4\x39\xf0\x82"
"\x6d\xa7\x26\x85\x34\x3b\x59\x7a\x2a\x94\xfb\x34\x0d\x84\xae\xc2"
"\x18\x79\x2d\x4a\xb0\xf9\x62\xdf\x3e\x5e\x71\x13\x6e\x22\xb9\xdb"
"\x15\xce\xf1\xad\x69\x48\xb3\x61\x27\x83\x7d\xdc\x5b\xdb\x20\x66"
"\x39\x24\x21\xac\xd6\xac\xca\xfb\x6e\x05\xd6\x1e\x32\xa7\xbf\x81"
"\x3f\xb3\x18\x8a\x31\xbb\x1e\x67\x21\x93\x4b\xb1\x14\x54\xfd\xfe"
"\x4e\xaa\x8c\xdc\x12\x02\x72\x14\x8e\x01\xf7\xe8\xbc\x1b\x6c\x6a"
"\x1b\xe6\xb2\xbd\x69\x5e\x75\x54\xa7\xf0\x3a\x84\x2e\x5a\x65\x4e"
"\x70\x81\x31\xdd\xde\x36\xaa\x2d\xdd\xed\x8e\x3a\x54\x80\x5a\xac"
"\xce\x1c\x48\xb9\xc3\x44\x1a\x94\xe0\xb3\x34\x19\xba\x08\x74\x8a"
"\xf5\x0e\x74\x35\x78\x83\x15\xe2\x41\xba\x4a\x21\xb9\xd9\x03\x01"
"\x58\x03\x2b\xa6\xc3\x26\xcf\x8e\x8c\x27\x4f\x2d\x59\x0c\xca\xf3"
"\xa6\xe9\xa1\xaf\x34\x43\x35\x1f\x55\x36\x3a\x6a\x5e\xe5\x41\xf8"
"\xd5\x18\xe8\x31\x31\xc4\x4e\x66\xe4\x10\x43\x81\x43\xb2\xe7\xab"
"\xe6\xe6\x3f\x8f\xb3\xd9\xd9\x79\xf6\xc8\xfb\x8f\x6e\xee\xba\x3e"
"\x43\x5d\x8e\xca\xcb\x05\x34\x43\x2c\xb3\x6b\xc9\xbd\x27\xfe\xcf"
"\xe6\x38\x86\xdc\x98\xb0\x0f\x13\x92\xf2\x91\x57\x51\xb2\xd2\x5b"
"\x84\xef\x5c\xd2\xa4\x75\x82\x54\x24\x74\x5a\x4a\xee\x82\x2d\xaa"
"\x1e\x97\x2e\xae\x77\x75\x6c\x39\x2f\x13\x71\xab\x8e\x19\xbc\x49"
"\x1a\x14\x1a\xc9\x26\xcd\xc3\x0d\x31\xf2\x7e\x1c\x85\x38\x24\x04"
"\x60\x54\x2b\xfe\xec\x8b\xbc\xc0\x71\xe6\xc2\x8d\xe1\x82\x8b\xf0"
"\xae\xed\x06\x7c\x2f\x93\x3d\xfb\x9a\x61\xc3\xac\x96\xf7\x24\x4a"
"\x69\xc8\x26\x2c\xba\x42\x0c\x11\xf5\x65\x20\x62\x73\x37\x59\xca"
"\xe9\x50\xe2\xb0\x20\x4c\x79\x90\xe2\x24\xc3\x99\xaa\x79\x0b\x92"
"\x57\x6f\x91\x96\x3d\xe8\xd5\xb1\x34\x12\xaa\xb9\x43\x6f\xed\xec"
"\xbc\x7f\xe7\xeb\xab\x73\x52\x5f\x59\x63\x04\x1f\xa2\x6e\x08\x41"
"\x43\x28\xd1\xdf\xfe\xbc\x76\x27\xa1\x8c\xd3\x30\xc5\xe3\xf7\x31"
"\xdc\x59\xc2\x95\x86\x71\xcd\x89\xeb\xeb\x76\x93\xcf\xb1\xa0\xa3"
"\x42\x3e\x34\x24\x77\x1e\x58\x1a\x99\x46\xe1\x8a\xd9\xe9\xad\xdc"
"\xcb\xdc\x75\x5c\x36\x17\x2a\x92\x5d\x7d\x05\xc9\xee\x68\x3e\x69"
"\x67\xb8\x89\x7b\x7e\xba\x85\x88\xa0\xf3\xef\xab\x84\x2b\xa5\x7c"
"\x54\x57\xf6\xac\x65\xd1\x93\x29\xb5\x61\xc7\xcb\x6c\x33\x86\xae"
"\x31\x2b\xe8\x65\x95\xc8\xb6\x76\x64\x63\x05\x02\xc5\x4b\x32\xe6"
"\x41\x4c\xfc\xd0\xd4\xe4\x69\x14\xf0\xc0\x80\x5f\x0b\xb9\x94\x92"
"\xf7\x58\xdf\x68\xb2\x7f\x74\x1e\xc4\xd0\x41\xf1\x9d\xe9\x60\x02"
"\xf1\x0f\x41\xb8\x4c\x1a\x8f\xcb\xed\x47\xc6\xb1\xa4\x46\x63\x1e"
"\xcb\xc7\xe5\x75\x44\x82\x44\x5a\x5b\x0a\x62\xd3\x85\xfd\x0d\x72"
"\xc6\x1b\x3a\x35\xc8\xd9\xd0\x92\xc1\xd7\xcd\x9a\xbf\x33\x01\xa3"
"\xe0\x9c\x58\x73\x36\x56\xc8\x26\x8d\xc3\xb6\x98\xe5\x87\x79\x91"
"\xf2\x8f\x4d\x5a\x68\x13\xbd\x37\xa6\xf1\x9a\x2e\xe6\x22\xfa\x71"
"\x43\x17\x9a\x93\xa9\x82\x2c\xb8\xee\x54\x38\x31\xbc\x64\x54\x20"
"\x61\x48\x1c\xfa\xde\xf0\x49\xfd\x34\xb1\xee\x06\x94\x63\xd5\x27"
"\x10\xde\x2b\xbe\x97\x76\x6f\xc1\x65\x2f\x81\x36\xc6\x62\xef\x48"
"\xf4\x5b\xb2\x02\x9b\x1c\x24\x98\xbb\xed\x3e\xe8\x85\xc3\xe2\x45"
"\xdb\x69\x35\xd5\x97\xf9\x86\x5c\x8a\xe2\xd4\x33\xaf\x3b\x1c\xbc"
"\x8a\xf5\xfb\x9d\x83\xec\x73\x00\x0a\xd3\xca\x10\xe5\x3e\x38\x1e"
"\x5e\xfd\xb9\x54\x92\xe0\x44\x08\x7f\xeb\xb7\x59\x49\x48\x15\x0d"
"\x85\xb0\x72\x4d\xc0\x99\x4e\x66\x3b\xd5\x0d\xaa\xb4\xf8\xb6\x9a"
"\x8b\xc9\x8d\x6e\x2f\x7a\xb4\xd5\xe3\x00\x82\x80\xa5\x70\x34\xdf"
"\xb1\x5c\xd1\xab\x8b\x64\x56\x43\x9e\xb4\x91\x5f\x0e\x90\x3f\xd8"
"\xd0\xe3\xfc\x31\x13\x0a\x04\xbe\x4b\x2a\x2a\xdf\x44\x4c\xb2\x69"
"\xab\xe0\x8a\x11\x2c\x01\xe6\x59\x2f\x07\x51\x84\xa4\x85\x94\x46"
"\xe9\x30\x9f\xf5\x91\x25\x93\x85\x93\xe9\xd6\x35\x9f\x5f\x85\xa6"
"\x7b\x59\x92\xb1\x7a\x79\xc6\x71\x0d\xc7\xd3\x20\xfa\x84\xcc\xf4"
"\xab\x4c\xf7\xd2\xe6\xd7\xec\x62\x85\x52\x2f\x1f\x4c\x92\x8e\x85"
"\x93\x3c\x6f\xfd\xe8\xb9\xaa\xec\x9b\xe7\x0d\xa4\x1b\x13\x31\x97"
"\x29\x20\x3d\xc5\xd0\xd4\x4d\xec\x4a\x18\x9c\x28\x48\xa3\x6c\x14"
"\x86\x5d\xe0\xc1\x60\x6d\x90\x5d\xaa\x6c\x70\xbd\x6a\xe0\x68\xb5"
"\x74\x8c\x46\x09\x86\x9a\xb1\xba\xe4\xf6\x3f\xd0\x88\x1f\x54\x83"
"\x14\x17\x5b\x5a\x52\xd5\x72\x09\x22\x28\xdb\x18\x2d\xeb\xac\x59"
"\x10\x1b\x88\x6d\x45\xa7\x2e\x19\xfd\xdc\x4f\xb1\x1f\xde\x8d\xcc"
"\x95\xbe\x19\x56\x22\x10\x89\x68\x80\x4e\x7c\x7e\xac\xba\xce\x73"
"\x2b\x1b\x8c\x38\x85\x59\x9d\xa7\x12\xb5\x8c\x0e\x7f\xd3\x2b\xf5"
"\x9d\x46\xe8\x65\xc8\xe5\x40\x9e\x6b\x84\x0b\x5a\xc7\x52\x89\x59"
"\x35\x57\x8f\x71\x0a\x37\xc0\xf0\xf3\x0f\x06\xd2\x8e\xab\x2a\x92"
"\xf3\x4e\x5e\x14\xe0\xfd\x04\xa0\xc1\x5a\x93\x52\x31\x45\x14\x77"
"\x1d\xe6\x81\x49\xca\xe3\x7f\xf0\x89\x80\x3e\x6a\x49\xbc\x6c\x0b"
"\xb5\x46\x3f\x32\x48\x3e\x9c\x61\x3b\x50\xf4\x18\x48\x83\xb5\x19"
"\x22\x35\x5b\x08\xcb\xb2\x89\x87\x4d\x1f\xb3\xd6\xaf\x4a\x02\xe8"
"\x9e\xe0\xdc\x04\xc7\x25\x4e\x49\xe6\x5a\xb5\x43\x68\x26\x0d\xb6"
"\xd2\x64\xbe\x27\x79\x30\xf0\x2b\xd5\x13\xca\x99\x6b\x2d\x6a\x0e"
"\x40\xa7\x1d\xcc\xb7\x4f\xec\xdc\x23\x06\xb1\x3a\xd8\xe1\x24\x86"
"\xde\x73\xa4\x22\x7c\x5d\xd8\x6f\xbd\xdc\xd9\xab\x8d\x7b\x16\x22"
"\xa7\x6b\xd8\x8a\xdf\x5f\xa0\x3b\x34\x11\xc9\x40\x6f\xab\xc2\x37"
"\xdc\x6b\xd2\x25\x44\xa5\xc7\xec\x67\x0c\x3f\xf6\xba\x77\x53\x2e"
"\xd0\xae\xc2\x0e\xe2\x56\x2d\x72\x92\xb2\x91\xfe\x04\x89\xc3\x34"
"\x20\x6d\x8a\x92\xb1\x1a\xfc\xff\xcd\xd9\xc0\xc1\xa0\xa7\x7d\x9e"
"\xe8\x5e\x76\xf1\x81\x03\xdf\xd4\x0b\x98\x0a\x36\xd4\x1a\x50\xd0"
"\xe3\x2f\x51\xc2\xd8\x4e\xc9\x77\xbc\xb8\x7f\x38\xe3\x00\xdb\x2f"
"\xbc\x48\x16\x6a\x28\xcf\x56\xd2\x58\x01\xbb\x21\x72\x55\xfa\x3c"
"\xd3\xc9\x04\x80\xdc\x38\xa6\xa5\xcd\xed\xba\xd1\xbc\xb7\x9a\x7e"
"\xb4\xe8\x59\x2a\x8d\x2e\xcf\x7c\xdd\x31\xf7\x8b\x96\x71\xf0\x06"
"\xfb\x29\x23\xf6\x0d\x66\x59\x8e\x82\x95\x8d\x42\x8e\x4e\x01\x9e"
"\x6d\x19\x83\x04\x36\x3d\xe3\x8a\xc4\x54\x90\x23\xa9\x81\xda\xcb"
"\x08\x6f\x9a\xd2\x13\x8d\x46\x1c\x4d\xf3\xa9\x3e\x60\x5d\x90\x3b"
"\xca\x95\x82\x1b\xa2\x1a\x19\xc5\x5c\x5a\xc9\x67\xcf\x65\xe4\x8d"
"\xb2\x2b\x4e\x0c\x7f\x7b\xfa\x32\x49\x69\xda\x5a\xb4\x9c\x06\xbf"
"\x12\xa4\x0f\x4a\x8c\xd0\x73\x8e\xdf\x66\x72\xd9\x29\xab\x06\x3a"
"\xf1\x3c\xd8\x30\xd6\xbb\x0e\x37\x07\x4e\xe5\xf6\x87\x8a\x4a\xd0"
"\x66\x68\x84\xd1\x23\x62\xb6\x07\x77\x0e\x60\x7d\x30\x22\xc2\xff"
"\x53\x46\x60\x69\xb0\x73\xe5\x33\x25\x0b\x47\x68\xa0\xf4\x52\x3d"
"\x91\x6e\x1c\x4d\x9e\x0a\x16\xd5\xb3\x3b\x2d\x3a\x7a\x87\x6c\xfe"
"\x7b\xc8\x81\xa8\xe6\xce\xb9\xb3\xc5\xc2\xd1\xde\x90\x92\x0f\x57"
"\x71\x90\x6a\x73\x4b\x5b\x07\x97\xe6\xda\x7d\xdb\xd5\xd1\x3e\xa6"
"\xbf\x26\x23\x46\xc6\xcf\xef\x2a\xed\xa7\xc0\x52\xda\x40\x2e\xd6"
"\x2e\xc4\xf1\xb2\x2f\x69\xac\x73\xe4\x2d\x75\xea\x19\x4c\xb5\x50"
"\xbc\x03\x51\x9c\x05\xda\x8a\x3b\xc9\x98\xd2\x43\x40\xc6\xd9\x0f"
"\x53\x2e\x24\x56\x55\x4e\x41\xc9\xcd\xa9\x06\xe8\xbc\x69\x10\xaa"
"\x99\x3d\x56\x9e\xd2\xbc\x48\xcd\x58\x2d\xe3\x16\x6a\x23\x3d\x85"
"\xc5\x14\x80\x46\x07\x96\xcf\xd9\xdc\xff\x14\x39\xfd\x5c\xc2\x2d"
"\xb9\xf9\x51\x09\x5d\xd3\xe4\xf6\x3f\x51\x62\x10\xf6\xd4\x76\x78"
"\x11\xf0\xd5\x63\xb8\x53\x2b\xb2\xa0\x58\x4e\x71\x90\xea\xb6\xc6"
"\x92\x59\x06\x8d\x53\x63\x0a\x0c\xd4\x62\x2d\x57\x12\xf9\xf8\xd8"
"\xdb\x10\x40\x2e\x09\x83\x1b\xbb\x8c\xdd\xbc\x0c\xa0\xc8\x14\x23"
"\xa5\x93\xed\xd9\x2d\x0b\xc0\xfd\x0e\x1d\xd1\xbb\x95\x96\xb6\xbc"
"\x81\x31\x6f\x20\x6f\x72\x1c\x4a\x87\xfb\x66\x2d\x79\x3c\xa4\x6d"
"\x05\xc1\x71\x50\x83\xad\xea\x03\x26\x2b\xe4\x10\xc8\x33\x0b\x61"
"\xdf\x30\x4b\x27\x8f\xfe\xbd\xcc\x8d\xda\x4f\xaf\x8f\xad\xaa\x25"
"\xa1\x50\x95\x95\x7d\x8e\x35\xec\xe8\x7e\xd4\x98\x68\xe4\x95\xac"
"\xa6\x98\x95\x38\xf8\xd2\xab\xdc\xb9\x77\xfc\xa9\xbf\xb5\x18\xed"
"\xca\x15\xb2\xe7\xd0\x23\xcb\xc4\x73\xc0\x85\x0b\x57\xeb\xf4\xe6"
"\x11\x97\xb1\x03\xa6\x66\x0a\x24\x3b\xb6\xe8\x2f\xfe\x9c\x78\x0a"
"\x42\x01\xe9\x35\x58\xf7\x55\x13\x80\x24\x23\x30\x62\x6c\x7b\x86"
"\xff\x7e\x12\x34\xf3\x33\x4c\x1c\xed\x5a\x96\xd6\xcd\x04\xfb\xf9"
"\x7c\xde\xc0\xd5\x70\x52\x4e\x0f\xa2\x8e\x6b\xa6\x8f\x3a\x08\xf9"
"\x08\x0f\x2f\xd7\xa2\xb1\x91\x53\x65\x63\x63\xb8\x31\xba\xf4\x21"
"\xb5\x17\xd7\x59\x94\xd0\x0e\x8c\x91\x5c\x37\xf8\x3a\xd8\x8c\x7f"
"\x76\xd0\x63\x7a\xd9\xb4\xa6\x3d\xf8\xfb\x72\xd5\x65\xf0\x10\x4a"
"\x42\x15\x70\xb1\x9b\x5f\xf8\xf9\x9f\x5b\x29\x0a\x28\x2a\x68\x6b"
"\xaf\xec\x84\x94\xbc\x22\xdf\xe8\x3e\xcb\xee\xc3\xc8\x03\x00\xf3"
"\x02\xff\x07\x4d\x95\x62\x12\x9e\x51\x1a\x20\x4a\x5a\xa2\x66\x81"
"\x3d\x29\x98\x23\x17\x11\x95\x84\x51\x9f\x40\x7a\x3d\x6f\x61\xbe"
"\x2b\x1b\x03\x82\xad\xb6\x8f\x69\x3d\x31\x39\xc7\x8b\x0a\x77\x6e"
"\x02\x88\xdd\x13\x6a\x9c\x72\x46\x5d\xf0\x92\xb4\x76\xac\xc0\xbd"
"\x8d\x2e\x3c\xcb\xa3\x89\x31\x07\x36\x68\x35\x03\x4c\x95\x6d"
"\xbd",
4096);
r[18] = syscall(SYS_writev, r[2], 0x20013ffeul, 0x5ul, 0, 0, 0);
return 0;
}

On commit 34229b277480f46c1e9a19f027f30b074512e68b.

Takashi Iwai

unread,
Feb 3, 2016, 4:35:15 AM2/3/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jaroslav Kysela, LKML, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
On Wed, 03 Feb 2016 09:57:50 +0100,
Dmitry Vyukov wrote:
>
> Hello,
>
> The following program triggers an out-of-bounds write in
> snd_rawmidi_kernel_write1 (run in parallel loop). It seems to try to
> copy -1 bytes (aka 4GB) from user space into kernel smashing all on
> its way.

What card is /dev/midi3? Please check /proc/asound/cards.
Is it MTPAV?


Takashi

Takashi Iwai

unread,
Feb 3, 2016, 4:41:15 AM2/3/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jaroslav Kysela, LKML, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
In anyway the patch below should paper over it. But it's still
strange that it gets a negative value there. Could you put

WARN_ON(count1 < 0)

before the newly added check?

I tried it locally with virmidi but it didn't appear, so far. Maybe
my setup is too slow and has fewer CPUs than yours.


thanks,

Takashi

---
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 26ca02248885..2fef77d9de50 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1239,6 +1239,8 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
}
while (count > 0 && runtime->avail > 0) {
count1 = runtime->buffer_size - runtime->appl_ptr;
+ if (count1 <= 0)
+ break;
if (count1 > count)
count1 = count;
if (count1 > (long)runtime->avail)

Takashi Iwai

unread,
Feb 3, 2016, 6:39:33 AM2/3/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jaroslav Kysela, LKML, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
On Wed, 03 Feb 2016 10:41:14 +0100,
Takashi Iwai wrote:
>
> On Wed, 03 Feb 2016 10:35:14 +0100,
> Takashi Iwai wrote:
> >
> > On Wed, 03 Feb 2016 09:57:50 +0100,
> > Dmitry Vyukov wrote:
> > >
> > > Hello,
> > >
> > > The following program triggers an out-of-bounds write in
> > > snd_rawmidi_kernel_write1 (run in parallel loop). It seems to try to
> > > copy -1 bytes (aka 4GB) from user space into kernel smashing all on
> > > its way.
> >
> > What card is /dev/midi3? Please check /proc/asound/cards.
> > Is it MTPAV?
>
> In anyway the patch below should paper over it. But it's still
> strange that it gets a negative value there. Could you put
>
> WARN_ON(count1 < 0)
>
> before the newly added check?
>
> I tried it locally with virmidi but it didn't appear, so far. Maybe
> my setup is too slow and has fewer CPUs than yours.

Scratch my previous patch, I could reproduce the issue on a faster
machine in my office now :) Will work on it.


Takashi

Takashi Iwai

unread,
Feb 3, 2016, 7:02:36 AM2/3/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jaroslav Kysela, LKML, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
On Wed, 03 Feb 2016 12:39:31 +0100,
This turned out to be a race in updates of runtime->appl_ptr & co.
We do temporary spin unlock and relock while copying the user-space
data, and then update these values. Meanwhile these values are
referred as the position to copy, and the concurrent accesses may lead
to the negative value.

Below is a quick fix for that, just updating these before the
temporary unlock.

The patch also fixes the read size where it has more race problems...

It seems working on my machine. Let me know if this works for you,
too. Then I'll cook up the official patch.


thanks,

Takashi

---
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 26ca02248885..795437b10082 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -942,31 +942,36 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
unsigned long flags;
long result = 0, count1;
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ unsigned long appl_ptr;

+ spin_lock_irqsave(&runtime->lock, flags);
while (count > 0 && runtime->avail) {
count1 = runtime->buffer_size - runtime->appl_ptr;
if (count1 > count)
count1 = count;
- spin_lock_irqsave(&runtime->lock, flags);
if (count1 > (int)runtime->avail)
count1 = runtime->avail;
+
+ /* update runtime->appl_ptr before unlocking for userbuf */
+ appl_ptr = runtime->appl_ptr;
+ runtime->appl_ptr += count1;
+ runtime->appl_ptr %= runtime->buffer_size;
+ runtime->avail -= count1;
+
if (kernelbuf)
- memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
+ memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
if (userbuf) {
spin_unlock_irqrestore(&runtime->lock, flags);
if (copy_to_user(userbuf + result,
- runtime->buffer + runtime->appl_ptr, count1)) {
+ runtime->buffer + appl_ptr, count1)) {
return result > 0 ? result : -EFAULT;
}
spin_lock_irqsave(&runtime->lock, flags);
}
- runtime->appl_ptr += count1;
- runtime->appl_ptr %= runtime->buffer_size;
- runtime->avail -= count1;
- spin_unlock_irqrestore(&runtime->lock, flags);
result += count1;
count -= count1;
}
+ spin_unlock_irqrestore(&runtime->lock, flags);
return result;
}

@@ -1223,6 +1228,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
unsigned long flags;
long count1, result;
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ unsigned long appl_ptr;

if (!kernelbuf && !userbuf)
return -EINVAL;
@@ -1243,12 +1249,19 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
count1 = count;
if (count1 > (long)runtime->avail)
count1 = runtime->avail;
+
+ /* update runtime->appl_ptr before unlocking for userbuf */
+ appl_ptr = runtime->appl_ptr;
+ runtime->appl_ptr += count1;
+ runtime->appl_ptr %= runtime->buffer_size;
+ runtime->avail -= count1;
+
if (kernelbuf)
- memcpy(runtime->buffer + runtime->appl_ptr,
+ memcpy(runtime->buffer + appl_ptr,
kernelbuf + result, count1);
else if (userbuf) {
spin_unlock_irqrestore(&runtime->lock, flags);
- if (copy_from_user(runtime->buffer + runtime->appl_ptr,
+ if (copy_from_user(runtime->buffer + appl_ptr,
userbuf + result, count1)) {
spin_lock_irqsave(&runtime->lock, flags);
result = result > 0 ? result : -EFAULT;
@@ -1256,9 +1269,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
}
spin_lock_irqsave(&runtime->lock, flags);
}
- runtime->appl_ptr += count1;
- runtime->appl_ptr %= runtime->buffer_size;
- runtime->avail -= count1;
result += count1;
count -= count1;
}

Dmitry Vyukov

unread,
Feb 3, 2016, 8:25:44 AM2/3/16
to Takashi Iwai, alsa-...@alsa-project.org, Jaroslav Kysela, LKML, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
Yes, it was MTPAV. There is only generic code in the stack traces, so
I though it may be a generic issue. Though, of course, the driver
could mess things already.
I've dropped CONFIG_SND_MTPAV now.

Dmitry Vyukov

unread,
Feb 3, 2016, 8:37:38 AM2/3/16
to Takashi Iwai, alsa-...@alsa-project.org, Jaroslav Kysela, LKML, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
Yes, it fixes the crash for me. Thanks!

Takashi Iwai

unread,
Feb 3, 2016, 9:26:44 AM2/3/16
to Dmitry Vyukov, alsa-...@alsa-project.org, Jaroslav Kysela, LKML, Alexander Potapenko, Kostya Serebryany, syzkaller, Sasha Levin
Great, I'll queue the fix. FWIW, below is the final form I'm going to
push.


thanks,

Takashi

-- 8< --
From: Takashi Iwai <ti...@suse.de>
Subject: [PATCH] ALSA: rawmidi: Fix race at copying & updating the position

The rawmidi read and write functions manage runtime stream status
such as runtime->appl_ptr and runtime->avail. These point where to
copy the new data and how many bytes have been copied (or to be
read). The problem is that rawmidi read/write call copy_from_user()
or copy_to_user(), and the runtime spinlock is temporarily unlocked
and relocked while copying user-space. Since the current code
advances and updates the runtime status after the spin unlock/relock,
the copy and the update may be asynchronous, and eventually
runtime->avail might go to a negative value when many concurrent
accesses are done. This may lead to memory corruption in the end.

For fixing this race, in this patch, the status update code is
performed in the same lock before the temporary unlock. Also, the
spinlock is now taken more widely in snd_rawmidi_kernel_read1() for
protecting more properly during the whole operation.

BugLink: http://lkml.kernel.org/r/CACT4Y+b-dCmNf1GpgPKfDO0i...@mail.gmail.com
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/rawmidi.c | 34 ++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)
--
2.7.0

Reply all
Reply to author
Forward
0 new messages