From patchwork Mon Feb 1 10:57:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 8177931 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 26F76BEEE5 for ; Mon, 1 Feb 2016 10:57:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CB80E2040F for ; Mon, 1 Feb 2016 10:57:39 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 024B72044C for ; Mon, 1 Feb 2016 10:57:38 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id A07D4260688; Mon, 1 Feb 2016 11:57:36 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, RCVD_IN_DNSWL_NONE,UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 8C7CF2604D8; Mon, 1 Feb 2016 11:57:28 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id DECD32604EF; Mon, 1 Feb 2016 11:57:26 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by alsa0.perex.cz (Postfix) with ESMTP id 5459F2604D8 for ; Mon, 1 Feb 2016 11:57:21 +0100 (CET) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id D31B0AAC4; Mon, 1 Feb 2016 10:57:19 +0000 (UTC) Date: Mon, 01 Feb 2016 11:57:19 +0100 Message-ID: From: Takashi Iwai To: "Dmitry Vyukov" In-Reply-To: References: User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/24.5 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Cc: alsa-devel@alsa-project.org, LKML , Takashi Sakamoto , Kostya Serebryany , Mark Brown , Alexander Potapenko , syzkaller , Sasha Levin Subject: Re: [alsa-devel] sound: use-after-free in snd_seq_deliver_single_event X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP On Mon, 01 Feb 2016 11:26:57 +0100, Dmitry Vyukov wrote: > > Hello, > > The following program triggers use-after-free in > snd_seq_deliver_single_event (run in a tight parallel loop): > > // autogenerated by syzkaller (http://github.com/google/syzkaller) > #include > #include > #include > #include > #include > > #ifndef SYS_mmap > #define SYS_mmap 9 > #endif > #ifndef SYS_syz_open_dev > #define SYS_syz_open_dev 1000001 > #endif > #ifndef SYS_ioctl > #define SYS_ioctl 16 > #endif > #ifndef SYS_getpgrp > #define SYS_getpgrp 111 > #endif > #ifndef SYS_migrate_pages > #define SYS_migrate_pages 256 > #endif > #ifndef SYS_read > #define SYS_read 0 > #endif > #ifndef SYS_write > #define SYS_write 1 > #endif > #ifndef SYS_dup3 > #define SYS_dup3 292 > #endif > > long r[59]; > > void* thr(void* arg) > { > switch ((long)arg) { > case 0: > r[0] = syscall(SYS_mmap, 0x20000000ul, 0x47000ul, 0x3ul, 0x32ul, > 0xfffffffffffffffful, 0x0ul); > break; > case 1: > memcpy((void*)0x20000000, > "\x2f\x64\x65\x76\x2f\x73\x65\x71\x75\x65\x6e\x63\x65\x72", > 14); > r[2] = > syscall(SYS_open, "/dev/sequencer", 0x2ul, 0, 0, 0); > break; > case 2: > r[3] = syscall(SYS_mmap, 0x20047000ul, 0x1000ul, 0x3ul, 0x32ul, > 0xfffffffffffffffful, 0x0ul); > break; > case 3: > r[4] = syscall(SYS_ioctl, r[2], 0x540ful, 0x20047ffcul, 0, 0, 0); > if (r[4] != -1) > r[5] = *(uint32_t*)0x20047ffc; > break; > case 4: > r[6] = syscall(SYS_getpgrp, r[5], 0, 0, 0, 0, 0); > break; > case 5: > r[7] = syscall(SYS_mmap, 0x20047000ul, 0x1000ul, 0x3ul, 0x32ul, > 0xfffffffffffffffful, 0x0ul); > break; > case 6: > r[8] = syscall(SYS_mmap, 0x20047000ul, 0x1000ul, 0x3ul, 0x32ul, > 0xfffffffffffffffful, 0x0ul); > break; > case 7: > *(uint64_t*)0x20047000 = (uint64_t)0x5; > *(uint64_t*)0x20047000 = (uint64_t)0xfffffffffffffff8; > r[11] = syscall(SYS_migrate_pages, r[6], 0xfful, 0x20047000ul, > 0x20047000ul, 0, 0); > break; > case 8: > memcpy((void*)0x20043684, > "\x2f\x64\x65\x76\x2f\x64\x6d\x6d\x69\x64\x69\x23", 12); > r[13] = syscall(SYS_open, "/dev/dmmidi2", 0x8a000ul, 0, 0, 0); > break; > case 9: > r[14] = syscall(SYS_read, r[13], 0x20045000ul, 0x36ul, 0, 0, 0); > break; > case 10: > *(uint8_t*)0x2000042c = (uint8_t)0x0; > *(uint8_t*)0x2000042d = (uint8_t)0x9cf; > *(uint8_t*)0x2000042e = (uint8_t)0x9; > *(uint8_t*)0x2000042f = (uint8_t)0x0; > *(uint64_t*)0x20000444 = (uint64_t)0x0; > *(uint64_t*)0x2000044c = (uint64_t)0x989680; > *(uint8_t*)0x20000454 = (uint8_t)0x2; > *(uint8_t*)0x20000455 = (uint8_t)0x100000000; > *(uint8_t*)0x20000456 = (uint8_t)0x8d; > *(uint8_t*)0x20000457 = (uint8_t)0x7; > *(uint8_t*)0x20000464 = (uint8_t)0x51b2; > *(uint8_t*)0x20000465 = (uint8_t)0xfffffffffffff15a; > *(uint8_t*)0x20000466 = (uint8_t)0x4; > *(uint8_t*)0x20000467 = (uint8_t)0x4; > *(uint32_t*)0x20000468 = (uint32_t)0xffffffff; > *(uint8_t*)0x2000046c = (uint8_t)0x5; > *(uint8_t*)0x2000046d = (uint8_t)0xfffffffffffffff8; > *(uint8_t*)0x2000046e = (uint8_t)0x401; > *(uint8_t*)0x2000046f = (uint8_t)0x5; > *(uint64_t*)0x20000484 = (uint64_t)0x4; > *(uint64_t*)0x2000048c = (uint64_t)0x0; > *(uint8_t*)0x20000494 = (uint8_t)0xc2c1; > *(uint8_t*)0x20000495 = (uint8_t)0x1; > *(uint8_t*)0x20000496 = (uint8_t)0x6b; > *(uint8_t*)0x20000497 = (uint8_t)0x6; > *(uint8_t*)0x200004a0 = (uint8_t)0xfffffffffffffffa; > *(uint8_t*)0x200004a1 = (uint8_t)0x81; > *(uint8_t*)0x200004a2 = (uint8_t)0x0; > *(uint8_t*)0x200004a3 = (uint8_t)0xa6; > *(uint8_t*)0x200004a4 = (uint8_t)0x400; > *(uint8_t*)0x200004a5 = (uint8_t)0x3ff; > *(uint8_t*)0x200004a6 = (uint8_t)0x8; > *(uint8_t*)0x200004a7 = (uint8_t)0x3; > *(uint64_t*)0x200004bc = (uint64_t)0x0; > *(uint64_t*)0x200004c4 = (uint64_t)0x0; > *(uint8_t*)0x200004cc = (uint8_t)0x9e; > *(uint8_t*)0x200004cd = (uint8_t)0x7ff; > *(uint8_t*)0x200004ce = (uint8_t)0x7fff; > *(uint8_t*)0x200004cf = (uint8_t)0x9; > *(uint8_t*)0x200004e0 = (uint8_t)0xa; > *(uint32_t*)0x200004e4 = (uint32_t)0x6; > *(uint32_t*)0x200004e8 = (uint32_t)0xffffffff; > r[57] = syscall(SYS_write, r[2], 0x2000042cul, 0x78ul, 0, 0, 0); > break; > case 11: > r[58] = syscall(SYS_dup3, r[13], r[2], 0x80000ul, 0, 0, 0); > break; > } > return 0; > } > > int main() > { > long i; > pthread_t th[12]; > > memset(r, -1, sizeof(r)); > for (i = 0; i < 12; i++) { > pthread_create(&th[i], 0, thr, (void*)i); > usleep(10000); > } > for (i = 0; i < 12; i++) { > pthread_create(&th[i], 0, thr, (void*)i); > if (i % 2 == 0) > usleep(10000); > } > usleep(100000); > return 0; > } > > > ================================================================== > BUG: KASAN: use-after-free in do_raw_spin_lock+0x281/0x2b0 at addr > ffff88002abf1654 > Read of size 4 by task syz-executor/13987 > ============================================================================= > BUG kmalloc-96 (Not tainted): kasan: bad access detected > ----------------------------------------------------------------------------- > > INFO: Allocated in snd_midi_event_new+0x73/0x200 age=10 cpu=0 pid=13996 > [< 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 >] kzalloc include/linux/slab.h:607 > [< none >] snd_midi_event_new+0x73/0x200 > sound/core/seq/seq_midi_event.c:120 > [< none >] snd_virmidi_input_open+0xfd/0x380 > sound/core/seq/seq_virmidi.c:214 > [< none >] open_substream+0x3eb/0x780 sound/core/rawmidi.c:269 > [< 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 > > INFO: Freed in snd_midi_event_free+0x43/0x60 age=17 cpu=0 pid=13996 > [< none >] __slab_free+0x1fc/0x320 mm/slub.c:2680 > [< inline >] slab_free mm/slub.c:2835 > [< none >] kfree+0x2ac/0x2c0 mm/slub.c:3664 > [< none >] snd_midi_event_free+0x43/0x60 > sound/core/seq/seq_midi_event.c:142 > [< none >] snd_virmidi_input_close+0x87/0x120 > sound/core/seq/seq_virmidi.c:261 > [< none >] close_substream.part.14+0xda/0x540 sound/core/rawmidi.c:486 > [< inline >] close_substream sound/core/rawmidi.c:514 > [< none >] rawmidi_release_priv+0x1e4/0x250 sound/core/rawmidi.c:504 > [< none >] snd_rawmidi_release+0x62/0xf0 sound/core/rawmidi.c:539 > [< none >] __fput+0x236/0x780 fs/file_table.c:208 > [< none >] ____fput+0x15/0x20 fs/file_table.c:244 > [< none >] task_work_run+0x170/0x210 kernel/task_work.c:115 > [< inline >] exit_task_work include/linux/task_work.h:21 > [< none >] do_exit+0x8b5/0x2cb0 kernel/exit.c:748 > [< none >] do_group_exit+0x108/0x330 kernel/exit.c:878 > [< none >] get_signal+0x5e4/0x14f0 kernel/signal.c:2307 > [< none >] do_signal+0x83/0x1c90 arch/x86/kernel/signal.c:712 > [< none >] exit_to_usermode_loop+0x1a5/0x210 > arch/x86/entry/common.c:247 > [< inline >] prepare_exit_to_usermode arch/x86/entry/common.c:282 > [< none >] syscall_return_slowpath+0x2ba/0x340 > arch/x86/entry/common.c:344 > > INFO: Slab 0xffffea0000aafc00 objects=28 used=11 fp=0xffff88002abf0470 > flags=0x1fffc0000004080 > INFO: Object 0xffff88002abf1630 @offset=5680 fp=0xffff88002abf06a8 > CPU: 1 PID: 13987 Comm: syz-executor Tainted: G B 4.5.0-rc1+ #305 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 > 00000000ffffffff ffff880061aaf7d8 ffffffff82be11ad ffff88003e804900 > ffff88002abf1630 ffff88002abf0000 ffff880061aaf808 ffffffff8175b454 > ffff88003e804900 ffffea0000aafc00 ffff88002abf1630 000000000000000a > > Call Trace: > [] __asan_report_load4_noabort+0x3e/0x40 > mm/kasan/report.c:294 > [< inline >] debug_spin_lock_before kernel/locking/spinlock_debug.c:83 > [] do_raw_spin_lock+0x281/0x2b0 > kernel/locking/spinlock_debug.c:135 > [< inline >] __raw_spin_lock_irqsave > include/linux/spinlock_api_smp.h:119 > [] _raw_spin_lock_irqsave+0xa7/0xd0 > kernel/locking/spinlock.c:159 > [] snd_midi_event_decode+0x1f7/0x5c0 > sound/core/seq/seq_midi_event.c:391 > [< inline >] snd_virmidi_dev_receive_event > sound/core/seq/seq_virmidi.c:95 > [] snd_virmidi_event_input+0x214/0x310 > sound/core/seq/seq_virmidi.c:133 > [] > snd_seq_deliver_single_event.constprop.11+0x3f4/0x740 > sound/core/seq/seq_clientmgr.c:634 > [] snd_seq_deliver_event+0x122/0x800 > sound/core/seq/seq_clientmgr.c:828 > [] snd_seq_kernel_client_dispatch+0x126/0x170 > sound/core/seq/seq_clientmgr.c:2401 > [< inline >] snd_seq_oss_dispatch > sound/core/seq/oss/seq_oss_device.h:151 > [] snd_seq_oss_midi_reset+0x303/0x4a0 > sound/core/seq/oss/seq_oss_midi.c:481 > [] snd_seq_oss_reset+0x130/0x260 > sound/core/seq/oss/seq_oss_init.c:469 > [] snd_seq_oss_release+0x71/0x130 > sound/core/seq/oss/seq_oss_init.c:425 > [] odev_release+0x5a/0x80 sound/core/seq/oss/seq_oss.c:155 > [] __fput+0x236/0x780 fs/file_table.c:208 > [] ____fput+0x15/0x20 fs/file_table.c:244 > [] task_work_run+0x170/0x210 kernel/task_work.c:115 > [< inline >] tracehook_notify_resume include/linux/tracehook.h:191 > [] exit_to_usermode_loop+0x1d1/0x210 > arch/x86/entry/common.c:251 > [< inline >] prepare_exit_to_usermode arch/x86/entry/common.c:282 > [] syscall_return_slowpath+0x2ba/0x340 > arch/x86/entry/common.c:344 > [] int_ret_from_sys_call+0x25/0x9f > arch/x86/entry/entry_64.S:281 Looks like a race at closing virmidi device. Does the patch below fix it? thanks, Takashi diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 3da2d48610b3..f71aedfb408c 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -254,9 +254,13 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream) */ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) { + struct snd_virmidi_dev *rdev = substream->rmidi->private_data; struct snd_virmidi *vmidi = substream->runtime->private_data; - snd_midi_event_free(vmidi->parser); + + write_lock_irq(&rdev->filelist_lock); list_del(&vmidi->list); + write_unlock_irq(&rdev->filelist_lock); + snd_midi_event_free(vmidi->parser); substream->runtime->private_data = NULL; kfree(vmidi); return 0;