]>
Commit | Line | Data |
---|---|---|
d513484f TL |
1 | From 425e11483546f928109e5871a2c8b0fba3ddb3b4 Mon Sep 17 00:00:00 2001 |
2 | From: Takashi Iwai <tiwai@suse.de> | |
3 | Date: Wed, 21 Jun 2017 18:56:01 +0200 | |
4 | Subject: [PATCH 1/5] ALSA: timer: Fix race between read and ioctl | |
5 | ||
6 | The read from ALSA timer device, the function snd_timer_user_tread(), | |
7 | may access to an uninitialized struct snd_timer_user fields when the | |
8 | read is concurrently performed while the ioctl like | |
9 | snd_timer_user_tselect() is invoked. We have already fixed the races | |
10 | among ioctls via a mutex, but we seem to have forgotten the race | |
11 | between read vs ioctl. | |
12 | ||
13 | This patch simply applies (more exactly extends the already applied | |
14 | range of) tu->ioctl_lock in snd_timer_user_tread() for closing the | |
15 | race window. | |
16 | ||
17 | Reported-by: Alexander Potapenko <glider@google.com> | |
18 | Tested-by: Alexander Potapenko <glider@google.com> | |
19 | Cc: <stable@vger.kernel.org> | |
20 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | |
21 | ||
22 | CVE-2017-1000380 | |
23 | ||
24 | (cherry-picked from commit d11662f4f798b50d8c8743f433842c3e40fe3378) | |
25 | Signed-off-by: Stefan Bader <stefan.bader@canonical.com> | |
26 | Acked-by: Seth Forshee <seth.forshee@canonical.com> | |
27 | Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> | |
28 | Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> | |
29 | ||
30 | Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com> | |
31 | --- | |
32 | sound/core/timer.c | 6 ++++-- | |
33 | 1 file changed, 4 insertions(+), 2 deletions(-) | |
34 | ||
35 | diff --git a/sound/core/timer.c b/sound/core/timer.c | |
36 | index ad153149b231..3c11a6983f54 100644 | |
37 | --- a/sound/core/timer.c | |
38 | +++ b/sound/core/timer.c | |
39 | @@ -1963,6 +1963,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |
40 | ||
41 | tu = file->private_data; | |
42 | unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); | |
43 | + mutex_lock(&tu->ioctl_lock); | |
44 | spin_lock_irq(&tu->qlock); | |
45 | while ((long)count - result >= unit) { | |
46 | while (!tu->qused) { | |
47 | @@ -1978,7 +1979,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |
48 | add_wait_queue(&tu->qchange_sleep, &wait); | |
49 | ||
50 | spin_unlock_irq(&tu->qlock); | |
51 | + mutex_unlock(&tu->ioctl_lock); | |
52 | schedule(); | |
53 | + mutex_lock(&tu->ioctl_lock); | |
54 | spin_lock_irq(&tu->qlock); | |
55 | ||
56 | remove_wait_queue(&tu->qchange_sleep, &wait); | |
57 | @@ -1998,7 +2001,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |
58 | tu->qused--; | |
59 | spin_unlock_irq(&tu->qlock); | |
60 | ||
61 | - mutex_lock(&tu->ioctl_lock); | |
62 | if (tu->tread) { | |
63 | if (copy_to_user(buffer, &tu->tqueue[qhead], | |
64 | sizeof(struct snd_timer_tread))) | |
65 | @@ -2008,7 +2010,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |
66 | sizeof(struct snd_timer_read))) | |
67 | err = -EFAULT; | |
68 | } | |
69 | - mutex_unlock(&tu->ioctl_lock); | |
70 | ||
71 | spin_lock_irq(&tu->qlock); | |
72 | if (err < 0) | |
73 | @@ -2018,6 +2019,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |
74 | } | |
75 | _error: | |
76 | spin_unlock_irq(&tu->qlock); | |
77 | + mutex_unlock(&tu->ioctl_lock); | |
78 | return result > 0 ? result : err; | |
79 | } | |
80 | ||
81 | -- | |
82 | 2.11.0 | |
83 |