Skip to content
Snippets Groups Projects
Commit be2fd6bf authored by jay_chuang's avatar jay_chuang Committed by Carol_Jiang
Browse files

anthias: audio: security patch for CVE-2016-2544, CVE-2016-2546 and CVE-2014-9904


ALSA: seq: Fix race at timer setup and close

ALSA sequencer code has an open race between the timer setup ioctl and
the close of the client.  This was triggered by syzkaller fuzzer, and
a use-after-free was caught there as a result.

This patch papers over it by adding a proper queue->timer_mutex lock
around the timer-related calls in the relevant code path.

Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
Tested-by: default avatarDmitry Vyukov <dvyukov@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>

ALSA: timer: Fix race among timer ioctls

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.

Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
Tested-by: default avatarDmitry Vyukov <dvyukov@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>

ALSA: compress: fix an integer overflow check

I previously added an integer overflow check here but looking at it now,
it's still buggy.

The bug happens in snd_compr_allocate_buffer().  We multiply
".fragments" and ".fragment_size" and that doesn't overflow but then we
save it in an unsigned int so it truncates the high bits away and we
allocate a smaller than expected size.

Change-Id: I39d409a8f737c83880bc7f1383dc066c3afb1beb
Reviewed-on: http://mcrd1-22-pc.corpnet.asus/code-review/master/248049


Reviewed-by: default avatarCarol_Jiang <carol_jiang@asus.com>
Tested-by: default avatarCarol_Jiang <carol_jiang@asus.com>
parent 11949c61
No related merge requests found
......@@ -496,7 +496,7 @@ static int snd_compress_check_input(struct snd_compr_params *params)
{
/* first let's check the buffer parameter's */
if (params->buffer.fragment_size == 0 ||
params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size)
params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
return -EINVAL;
/* now codec parameters */
......
......@@ -144,8 +144,10 @@ static struct snd_seq_queue *queue_new(int owner, int locked)
static void queue_delete(struct snd_seq_queue *q)
{
/* stop and release the timer */
mutex_lock(&q->timer_mutex);
snd_seq_timer_stop(q->timer);
snd_seq_timer_close(q);
mutex_unlock(&q->timer_mutex);
/* wait until access free */
snd_use_lock_sync(&q->use_lock);
/* release resources... */
......
......@@ -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;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment