Skip to content

Commit 8527c8f

Browse files
tiwaigregkh
authored andcommitted
ALSA: pcm: Fix races among concurrent read/write and buffer changes
commit dca947d upstream. In the current PCM design, the read/write syscalls (as well as the equivalent ioctls) are allowed before the PCM stream is running, that is, at PCM PREPARED state. Meanwhile, we also allow to re-issue hw_params and hw_free ioctl calls at the PREPARED state that may change or free the buffers, too. The problem is that there is no protection against those mix-ups. This patch applies the previously introduced runtime->buffer_mutex to the read/write operations so that the concurrent hw_params or hw_free call can no longer interfere during the operation. The mutex is unlocked before scheduling, so we don't take it too long. Cc: <stable@vger.kernel.org> Reviewed-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20220322170720.3529-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 0f6947f commit 8527c8f

1 file changed

Lines changed: 4 additions & 0 deletions

File tree

sound/core/pcm_lib.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,9 +1871,11 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
18711871
if (avail >= runtime->twake)
18721872
break;
18731873
snd_pcm_stream_unlock_irq(substream);
1874+
mutex_unlock(&runtime->buffer_mutex);
18741875

18751876
tout = schedule_timeout(wait_time);
18761877

1878+
mutex_lock(&runtime->buffer_mutex);
18771879
snd_pcm_stream_lock_irq(substream);
18781880
set_current_state(TASK_INTERRUPTIBLE);
18791881
switch (runtime->status->state) {
@@ -2167,6 +2169,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
21672169

21682170
nonblock = !!(substream->f_flags & O_NONBLOCK);
21692171

2172+
mutex_lock(&runtime->buffer_mutex);
21702173
snd_pcm_stream_lock_irq(substream);
21712174
err = pcm_accessible_state(runtime);
21722175
if (err < 0)
@@ -2254,6 +2257,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
22542257
if (xfer > 0 && err >= 0)
22552258
snd_pcm_update_state(substream, runtime);
22562259
snd_pcm_stream_unlock_irq(substream);
2260+
mutex_unlock(&runtime->buffer_mutex);
22572261
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
22582262
}
22592263
EXPORT_SYMBOL(__snd_pcm_lib_xfer);

0 commit comments

Comments
 (0)