Skip to content

Commit e88d13e

Browse files
tiwaigregkh
authored andcommitted
ALSA: aloop: Sync stale timer before release
commit 67a01afaf3d34893cf7d2ea19b34555d6abb7cb0 upstream. The aloop driver tries to stop the pending timer via timer_del() in the trigger callback and in the close callback. The former is correct, as it's an atomic operation, while the latter expects that the timer gets really removed and proceeds the resource releases after that. But timer_del() doesn't synchronize, hence the running timer may still access the released resources. A similar situation can be also seen in the prepare callback after trigger(STOP) where the prepare tries to re-initialize the things while a timer is still running. The problems like the above are seen indirectly in some syzkaller reports (although it's not 100% clear whether this is the only cause, as the race condition is quite narrow and not always easy to trigger). For addressing these issues, this patch adds the explicit alls of timer_del_sync() in some places, so that the pending timer is properly killed / synced. Cc: <[email protected]> Signed-off-by: Takashi Iwai <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 02dd987 commit e88d13e

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

sound/drivers/aloop.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
193193
dpcm->timer.expires = 0;
194194
}
195195

196+
static inline void loopback_timer_stop_sync(struct loopback_pcm *dpcm)
197+
{
198+
del_timer_sync(&dpcm->timer);
199+
}
200+
196201
#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
197202
#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE)
198203
#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE)
@@ -327,6 +332,8 @@ static int loopback_prepare(struct snd_pcm_substream *substream)
327332
struct loopback_cable *cable = dpcm->cable;
328333
int bps, salign;
329334

335+
loopback_timer_stop_sync(dpcm);
336+
330337
salign = (snd_pcm_format_width(runtime->format) *
331338
runtime->channels) / 8;
332339
bps = salign * runtime->rate;
@@ -746,7 +753,7 @@ static int loopback_close(struct snd_pcm_substream *substream)
746753
struct loopback *loopback = substream->private_data;
747754
struct loopback_pcm *dpcm = substream->runtime->private_data;
748755

749-
loopback_timer_stop(dpcm);
756+
loopback_timer_stop_sync(dpcm);
750757
mutex_lock(&loopback->cable_lock);
751758
free_cable(substream);
752759
mutex_unlock(&loopback->cable_lock);

0 commit comments

Comments
 (0)