From: Takashi Iwai Date: Fri, 2 Jun 2017 13:03:38 +0000 (+0200) Subject: ALSA: timer: Fix race between read and ioctl X-Git-Tag: v4.1.12-106.0.20170720_1900~26 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=a2c76c21c9f66577b9b5e9131f46c9e700b846dc;p=users%2Fjedix%2Flinux-maple.git ALSA: timer: Fix race between read and ioctl The read from ALSA timer device, the function snd_timer_user_tread(), may access to an uninitialized struct snd_timer_user fields when the read is concurrently performed while the ioctl like snd_timer_user_tselect() is invoked. We have already fixed the races among ioctls via a mutex, but we seem to have forgotten the race between read vs ioctl. This patch simply applies (more exactly extends the already applied range of) tu->ioctl_lock in snd_timer_user_tread() for closing the race window. Reported-by: Alexander Potapenko Tested-by: Alexander Potapenko Cc: Signed-off-by: Takashi Iwai (cherry picked from commit d11662f4f798b50d8c8743f433842c3e40fe3378) Orabug: 26267070 CVE-2017-1000380 Signed-off-by: Kirtikar Kashyap Reviewed-by: Jack Vogel --- diff --git a/sound/core/timer.c b/sound/core/timer.c index 215d13e59853..c5261b0f8c2f 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1932,6 +1932,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, tu = file->private_data; unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); + mutex_lock(&tu->ioctl_lock); spin_lock_irq(&tu->qlock); while ((long)count - result >= unit) { while (!tu->qused) { @@ -1947,7 +1948,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, add_wait_queue(&tu->qchange_sleep, &wait); spin_unlock_irq(&tu->qlock); + mutex_unlock(&tu->ioctl_lock); schedule(); + mutex_lock(&tu->ioctl_lock); spin_lock_irq(&tu->qlock); remove_wait_queue(&tu->qchange_sleep, &wait); @@ -1985,6 +1988,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, } _error: spin_unlock_irq(&tu->qlock); + mutex_unlock(&tu->ioctl_lock); return result > 0 ? result : err; }