| From 79fb0518fec8c8b4ea7f1729f54f293724b3dbb0 Mon Sep 17 00:00:00 2001 |
| From: Takashi Iwai <tiwai@suse.de> |
| Date: Sun, 29 Oct 2017 11:02:04 +0100 |
| Subject: ALSA: timer: Add missing mutex lock for compat ioctls |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| commit 79fb0518fec8c8b4ea7f1729f54f293724b3dbb0 upstream. |
| |
| The races among ioctl and other operations were protected by the |
| commit af368027a49a ("ALSA: timer: Fix race among timer ioctls") and |
| later fixes, but one code path was forgotten in the scenario: the |
| 32bit compat ioctl. As syzkaller recently spotted, a very similar |
| use-after-free may happen with the combination of compat ioctls. |
| |
| The fix is simply to apply the same ioctl_lock to the compat_ioctl |
| callback, too. |
| |
| Fixes: af368027a49a ("ALSA: timer: Fix race among timer ioctls") |
| Reference: http://lkml.kernel.org/r/089e082686ac9b482e055c832617@google.com |
| Reported-by: syzbot <bot+e5f3c9783e7048a74233054febbe9f1bdf54b6da@syzkaller.appspotmail.com> |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| sound/core/timer_compat.c | 17 +++++++++++++++-- |
| 1 file changed, 15 insertions(+), 2 deletions(-) |
| |
| --- a/sound/core/timer_compat.c |
| +++ b/sound/core/timer_compat.c |
| @@ -106,7 +106,8 @@ enum { |
| #endif /* CONFIG_X86_X32 */ |
| }; |
| |
| -static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
| +static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, |
| + unsigned long arg) |
| { |
| void __user *argp = compat_ptr(arg); |
| |
| @@ -127,7 +128,7 @@ static long snd_timer_user_ioctl_compat( |
| case SNDRV_TIMER_IOCTL_PAUSE: |
| case SNDRV_TIMER_IOCTL_PAUSE_OLD: |
| case SNDRV_TIMER_IOCTL_NEXT_DEVICE: |
| - return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); |
| + return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp); |
| case SNDRV_TIMER_IOCTL_INFO32: |
| return snd_timer_user_info_compat(file, argp); |
| case SNDRV_TIMER_IOCTL_STATUS32: |
| @@ -139,3 +140,15 @@ static long snd_timer_user_ioctl_compat( |
| } |
| return -ENOIOCTLCMD; |
| } |
| + |
| +static long snd_timer_user_ioctl_compat(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_compat(file, cmd, arg); |
| + mutex_unlock(&tu->ioctl_lock); |
| + return ret; |
| +} |