Skip to content

Commit 2f4c63e

Browse files
tiwai0day robot
authored andcommitted
sound: use-after-free in snd_seq_queue_alloc
On Wed, 08 Feb 2017 10:41:14 +0100, Dmitry Vyukov wrote: > > Hello, > > > I've got the following report while running syzkaller fuzzer on > 8b1b41e: > > BUG: KASAN: use-after-free in snd_seq_queue_alloc+0x663/0x690 > sound/core/seq/seq_queue.c:200 at addr ffff880086ba1d00 > Read of size 4 by task syz-executor2/31851 > CPU: 2 PID: 31851 Comm: syz-executor2 Not tainted 4.10.0-rc5+ torvalds#201 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 > > Call Trace: > __asan_report_load4_noabort+0x3e/0x40 mm/kasan/report.c:327 > snd_seq_queue_alloc+0x663/0x690 sound/core/seq/seq_queue.c:200 > snd_seq_ioctl_create_queue+0xad/0x310 sound/core/seq/seq_clientmgr.c:1508 > snd_seq_ioctl+0x2da/0x4d0 sound/core/seq/seq_clientmgr.c:2130 > vfs_ioctl fs/ioctl.c:43 [inline] > do_vfs_ioctl+0x1bf/0x1790 fs/ioctl.c:683 > SYSC_ioctl fs/ioctl.c:698 [inline] > SyS_ioctl+0x8f/0xc0 fs/ioctl.c:689 > entry_SYSCALL_64_fastpath+0x1f/0xc2 > > Allocated: > PID = 31851 > [<ffffffff83483a17>] kzalloc include/linux/slab.h:490 [inline] > [<ffffffff83483a17>] queue_new sound/core/seq/seq_queue.c:113 [inline] > [<ffffffff83483a17>] snd_seq_queue_alloc+0x107/0x690 > sound/core/seq/seq_queue.c:191 > [<ffffffff834748dd>] snd_seq_ioctl_create_queue+0xad/0x310 > sound/core/seq/seq_clientmgr.c:1508 > [<ffffffff8347878a>] snd_seq_ioctl+0x2da/0x4d0 > sound/core/seq/seq_clientmgr.c:2130 > [<ffffffff81aa41cf>] vfs_ioctl fs/ioctl.c:43 [inline] > [<ffffffff81aa41cf>] do_vfs_ioctl+0x1bf/0x1790 fs/ioctl.c:683 > [<ffffffff81aa582f>] SYSC_ioctl fs/ioctl.c:698 [inline] > [<ffffffff81aa582f>] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:689 > [<ffffffff841c9c81>] entry_SYSCALL_64_fastpath+0x1f/0xc2 > > Freed: > PID = 31854 > [<ffffffff81a0b5c3>] kfree+0xd3/0x250 mm/slab.c:3822 > [<ffffffff834817e0>] queue_delete+0x90/0xb0 sound/core/seq/seq_queue.c:156 > [<ffffffff834826cc>] snd_seq_queue_delete+0x3c/0x50 > sound/core/seq/seq_queue.c:213 > [<ffffffff8347480a>] snd_seq_ioctl_delete_queue+0x6a/0x90 > sound/core/seq/seq_clientmgr.c:1534 > [<ffffffff8347878a>] snd_seq_ioctl+0x2da/0x4d0 > sound/core/seq/seq_clientmgr.c:2130 > [<ffffffff81aa41cf>] vfs_ioctl fs/ioctl.c:43 [inline] > [<ffffffff81aa41cf>] do_vfs_ioctl+0x1bf/0x1790 fs/ioctl.c:683 > [<ffffffff81aa582f>] SYSC_ioctl fs/ioctl.c:698 [inline] > [<ffffffff81aa582f>] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:689 > > > > Looking at the code: > > int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags) > { > struct snd_seq_queue *q; > > q = queue_new(client, locked); > if (q == NULL) > return -ENOMEM; > q->info_flags = info_flags; > if (queue_list_add(q) < 0) { > queue_delete(q); > return -ENOMEM; > } > snd_seq_queue_use(q->queue, client, 1); /* use this queue */ > return q->queue; > } > > After queue_list_add(q) q can be deleted by another thread, so > snd_seq_queue_use(q->queue, client, 1) already potentially operates on > deleted object. A good catch! The fix patch is below. thanks, Takashi -- 8< -- From: Takashi Iwai <tiwai@suse.de> Subject: [PATCH] ALSA: seq: Fix race at creating a queue When a sequencer queue is created in snd_seq_queue_alloc(),it adds the new queue element to the public list before referencing it. Thus the queue might be deleted before the call of snd_seq_queue_use(), and it results in the use-after-free error, as spotted by syzkaller. The fix is to reference the queue object at the right time. Reported-by: Dmitry Vyukov <dvyukov@google.com> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 8d8c9ae commit 2f4c63e

File tree

1 file changed

+20
-13
lines changed

1 file changed

+20
-13
lines changed

sound/core/seq/seq_queue.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ void __exit snd_seq_queues_delete(void)
181181
}
182182
}
183183

184+
static void queue_use(struct snd_seq_queue *queue, int client, int use);
185+
184186
/* allocate a new queue -
185187
* return queue index value or negative value for error
186188
*/
@@ -192,11 +194,11 @@ int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
192194
if (q == NULL)
193195
return -ENOMEM;
194196
q->info_flags = info_flags;
197+
queue_use(q, client, 1);
195198
if (queue_list_add(q) < 0) {
196199
queue_delete(q);
197200
return -ENOMEM;
198201
}
199-
snd_seq_queue_use(q->queue, client, 1); /* use this queue */
200202
return q->queue;
201203
}
202204

@@ -502,19 +504,9 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client,
502504
return result;
503505
}
504506

505-
506-
/* use or unuse this queue -
507-
* if it is the first client, starts the timer.
508-
* if it is not longer used by any clients, stop the timer.
509-
*/
510-
int snd_seq_queue_use(int queueid, int client, int use)
507+
/* use or unuse this queue */
508+
static void queue_use(struct snd_seq_queue *queue, int client, int use)
511509
{
512-
struct snd_seq_queue *queue;
513-
514-
queue = queueptr(queueid);
515-
if (queue == NULL)
516-
return -EINVAL;
517-
mutex_lock(&queue->timer_mutex);
518510
if (use) {
519511
if (!test_and_set_bit(client, queue->clients_bitmap))
520512
queue->clients++;
@@ -529,6 +521,21 @@ int snd_seq_queue_use(int queueid, int client, int use)
529521
} else {
530522
snd_seq_timer_close(queue);
531523
}
524+
}
525+
526+
/* use or unuse this queue -
527+
* if it is the first client, starts the timer.
528+
* if it is not longer used by any clients, stop the timer.
529+
*/
530+
int snd_seq_queue_use(int queueid, int client, int use)
531+
{
532+
struct snd_seq_queue *queue;
533+
534+
queue = queueptr(queueid);
535+
if (queue == NULL)
536+
return -EINVAL;
537+
mutex_lock(&queue->timer_mutex);
538+
queue_use(queue, client, use);
532539
mutex_unlock(&queue->timer_mutex);
533540
queuefree(queue);
534541
return 0;

0 commit comments

Comments
 (0)