From e370b0b1ce8e53642fe1fbef6c90548e0d7763ad Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Tue, 5 Apr 2016 14:18:36 +0300 Subject: kernel/ALSA: CVE-2016-2546 Fixes an open race in ALSA timer ioctls (in the linux-qoriq-3.12). This flaw may lead to a use-after-free of timer instance object. Upstream patch: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/ patch/?id=7210b17187111e20afca4b4e30a31fa13c71a61b References: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-2546 http://seclists.org/oss-sec/2016/q1/133 Signed-off-by: Sona Sarmadi --- .../linux-qoriq-3.12/ALSA-CVE-2016-2546.patch | 128 +++++++++++++++++++++ recipes-kernel/linux/linux-qoriq-common.inc | 1 + 2 files changed, 129 insertions(+) create mode 100644 recipes-kernel/linux/linux-qoriq-3.12/ALSA-CVE-2016-2546.patch diff --git a/recipes-kernel/linux/linux-qoriq-3.12/ALSA-CVE-2016-2546.patch b/recipes-kernel/linux/linux-qoriq-3.12/ALSA-CVE-2016-2546.patch new file mode 100644 index 0000000..a52f70f --- /dev/null +++ b/recipes-kernel/linux/linux-qoriq-3.12/ALSA-CVE-2016-2546.patch @@ -0,0 +1,128 @@ +From 7210b17187111e20afca4b4e30a31fa13c71a61b Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 13 Jan 2016 17:48:01 +0100 +Subject: ALSA: timer: Fix race among timer ioctls + +commit af368027a49a751d6ff4ee9e3f9961f35bb4fede upstream. + +ALSA timer ioctls have an open race and this may lead to a +use-after-free of timer instance object. A simplistic fix is to make +each ioctl exclusive. We have already tread_sem for controlling the +tread, and extend this as a global mutex to be applied to each ioctl. + +The downside is, of course, the worse concurrency. But these ioctls +aren't to be parallel accessible, in anyway, so it should be fine to +serialize there. + +CVE: CVE-2016-2546 +Upstream-Status: Backport + +Reported-by: Dmitry Vyukov +Tested-by: Dmitry Vyukov +Signed-off-by: Takashi Iwai +Signed-off-by: Jiri Slaby +Signed-off-by: Sona Sarmadi +--- + sound/core/timer.c | 32 +++++++++++++++++++------------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 38a137d..1d54617 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -73,7 +73,7 @@ struct snd_timer_user { + struct timespec tstamp; /* trigger tstamp */ + wait_queue_head_t qchange_sleep; + struct fasync_struct *fasync; +- struct mutex tread_sem; ++ struct mutex ioctl_lock; + }; + + /* list of timers */ +@@ -1266,7 +1266,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) + return -ENOMEM; + spin_lock_init(&tu->qlock); + init_waitqueue_head(&tu->qchange_sleep); +- mutex_init(&tu->tread_sem); ++ mutex_init(&tu->ioctl_lock); + tu->ticks = 1; + tu->queue_size = 128; + tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), +@@ -1286,8 +1286,10 @@ static int snd_timer_user_release(struct inode *inode, struct file *file) + if (file->private_data) { + tu = file->private_data; + file->private_data = NULL; ++ mutex_lock(&tu->ioctl_lock); + if (tu->timeri) + snd_timer_close(tu->timeri); ++ mutex_unlock(&tu->ioctl_lock); + kfree(tu->queue); + kfree(tu->tqueue); + kfree(tu); +@@ -1525,7 +1527,6 @@ static int snd_timer_user_tselect(struct file *file, + int err = 0; + + tu = file->private_data; +- mutex_lock(&tu->tread_sem); + if (tu->timeri) { + snd_timer_close(tu->timeri); + tu->timeri = NULL; +@@ -1569,7 +1570,6 @@ static int snd_timer_user_tselect(struct file *file, + } + + __err: +- mutex_unlock(&tu->tread_sem); + return err; + } + +@@ -1782,7 +1782,7 @@ enum { + SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), + }; + +-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, ++static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) + { + struct snd_timer_user *tu; +@@ -1799,17 +1799,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, + { + int xarg; + +- mutex_lock(&tu->tread_sem); +- if (tu->timeri) { /* too late */ +- mutex_unlock(&tu->tread_sem); ++ if (tu->timeri) /* too late */ + return -EBUSY; +- } +- if (get_user(xarg, p)) { +- mutex_unlock(&tu->tread_sem); ++ if (get_user(xarg, p)) + return -EFAULT; +- } + tu->tread = xarg ? 1 : 0; +- mutex_unlock(&tu->tread_sem); + return 0; + } + case SNDRV_TIMER_IOCTL_GINFO: +@@ -1842,6 +1836,18 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, + return -ENOTTY; + } + ++static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct snd_timer_user *tu = file->private_data; ++ long ret; ++ ++ mutex_lock(&tu->ioctl_lock); ++ ret = __snd_timer_user_ioctl(file, cmd, arg); ++ mutex_unlock(&tu->ioctl_lock); ++ return ret; ++} ++ + static int snd_timer_user_fasync(int fd, struct file * file, int on) + { + struct snd_timer_user *tu; +-- +cgit v0.12 + diff --git a/recipes-kernel/linux/linux-qoriq-common.inc b/recipes-kernel/linux/linux-qoriq-common.inc index 8b77dec..76a6ac8 100644 --- a/recipes-kernel/linux/linux-qoriq-common.inc +++ b/recipes-kernel/linux/linux-qoriq-common.inc @@ -26,6 +26,7 @@ SRC_URI += "file://b4860-hard_irq_disable-bug.patch \ file://CVE-2015-2922.patch \ file://CVE-2015-3636.patch \ file://net-unix-CVE-2013-7446.patch \ + file://ALSA-CVE-2016-2546.patch \ " SRC_URI += "file://cfg/00013-localversion.cfg \ -- cgit v1.2.3-54-g00ecf