diff options
author | Takashi Iwai <tiwai@suse.de> | 2017-10-29 06:02:04 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2017-10-31 03:28:16 -0400 |
commit | 79fb0518fec8c8b4ea7f1729f54f293724b3dbb0 (patch) | |
tree | 18d39bf1e0f6241a4ec148415b423e1f3f940251 /sound/core | |
parent | f265788c336979090ac80b9ae173aa817c4fe40d (diff) |
ALSA: timer: Add missing mutex lock for compat ioctls
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>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/timer_compat.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 6a437eb66115..59127b6ef39e 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c | |||
@@ -133,7 +133,8 @@ enum { | |||
133 | #endif /* CONFIG_X86_X32 */ | 133 | #endif /* CONFIG_X86_X32 */ |
134 | }; | 134 | }; |
135 | 135 | ||
136 | static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 136 | static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, |
137 | unsigned long arg) | ||
137 | { | 138 | { |
138 | void __user *argp = compat_ptr(arg); | 139 | void __user *argp = compat_ptr(arg); |
139 | 140 | ||
@@ -153,7 +154,7 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns | |||
153 | case SNDRV_TIMER_IOCTL_PAUSE: | 154 | case SNDRV_TIMER_IOCTL_PAUSE: |
154 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: | 155 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: |
155 | case SNDRV_TIMER_IOCTL_NEXT_DEVICE: | 156 | case SNDRV_TIMER_IOCTL_NEXT_DEVICE: |
156 | return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); | 157 | return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp); |
157 | case SNDRV_TIMER_IOCTL_GPARAMS32: | 158 | case SNDRV_TIMER_IOCTL_GPARAMS32: |
158 | return snd_timer_user_gparams_compat(file, argp); | 159 | return snd_timer_user_gparams_compat(file, argp); |
159 | case SNDRV_TIMER_IOCTL_INFO32: | 160 | case SNDRV_TIMER_IOCTL_INFO32: |
@@ -167,3 +168,15 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns | |||
167 | } | 168 | } |
168 | return -ENOIOCTLCMD; | 169 | return -ENOIOCTLCMD; |
169 | } | 170 | } |
171 | |||
172 | static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, | ||
173 | unsigned long arg) | ||
174 | { | ||
175 | struct snd_timer_user *tu = file->private_data; | ||
176 | long ret; | ||
177 | |||
178 | mutex_lock(&tu->ioctl_lock); | ||
179 | ret = __snd_timer_user_ioctl_compat(file, cmd, arg); | ||
180 | mutex_unlock(&tu->ioctl_lock); | ||
181 | return ret; | ||
182 | } | ||