]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.18.103/alsa-aloop-sync-stale-timer-before-release.patch
Linux 4.14.95
[thirdparty/kernel/stable-queue.git] / releases / 3.18.103 / alsa-aloop-sync-stale-timer-before-release.patch
1 From 67a01afaf3d34893cf7d2ea19b34555d6abb7cb0 Mon Sep 17 00:00:00 2001
2 From: Takashi Iwai <tiwai@suse.de>
3 Date: Thu, 22 Mar 2018 08:56:06 +0100
4 Subject: ALSA: aloop: Sync stale timer before release
5
6 From: Takashi Iwai <tiwai@suse.de>
7
8 commit 67a01afaf3d34893cf7d2ea19b34555d6abb7cb0 upstream.
9
10 The aloop driver tries to stop the pending timer via timer_del() in
11 the trigger callback and in the close callback. The former is
12 correct, as it's an atomic operation, while the latter expects that
13 the timer gets really removed and proceeds the resource releases after
14 that. But timer_del() doesn't synchronize, hence the running timer
15 may still access the released resources.
16
17 A similar situation can be also seen in the prepare callback after
18 trigger(STOP) where the prepare tries to re-initialize the things
19 while a timer is still running.
20
21 The problems like the above are seen indirectly in some syzkaller
22 reports (although it's not 100% clear whether this is the only cause,
23 as the race condition is quite narrow and not always easy to
24 trigger).
25
26 For addressing these issues, this patch adds the explicit alls of
27 timer_del_sync() in some places, so that the pending timer is properly
28 killed / synced.
29
30 Cc: <stable@vger.kernel.org>
31 Signed-off-by: Takashi Iwai <tiwai@suse.de>
32 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
33
34 ---
35 sound/drivers/aloop.c | 9 ++++++++-
36 1 file changed, 8 insertions(+), 1 deletion(-)
37
38 --- a/sound/drivers/aloop.c
39 +++ b/sound/drivers/aloop.c
40 @@ -193,6 +193,11 @@ static inline void loopback_timer_stop(s
41 dpcm->timer.expires = 0;
42 }
43
44 +static inline void loopback_timer_stop_sync(struct loopback_pcm *dpcm)
45 +{
46 + del_timer_sync(&dpcm->timer);
47 +}
48 +
49 #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
50 #define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE)
51 #define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE)
52 @@ -327,6 +332,8 @@ static int loopback_prepare(struct snd_p
53 struct loopback_cable *cable = dpcm->cable;
54 int bps, salign;
55
56 + loopback_timer_stop_sync(dpcm);
57 +
58 salign = (snd_pcm_format_width(runtime->format) *
59 runtime->channels) / 8;
60 bps = salign * runtime->rate;
61 @@ -746,7 +753,7 @@ static int loopback_close(struct snd_pcm
62 struct loopback *loopback = substream->private_data;
63 struct loopback_pcm *dpcm = substream->runtime->private_data;
64
65 - loopback_timer_stop(dpcm);
66 + loopback_timer_stop_sync(dpcm);
67 mutex_lock(&loopback->cable_lock);
68 free_cable(substream);
69 mutex_unlock(&loopback->cable_lock);