Skip to content

Commit dca947d

Browse files
committed
ALSA: pcm: Fix races among concurrent read/write and buffer changes
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: <[email protected]> Reviewed-by: Jaroslav Kysela <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 92ee3c6 commit dca947d

File tree

1 file changed

+4
-0
lines changed

1 file changed

+4
-0
lines changed

sound/core/pcm_lib.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,9 +1906,11 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
19061906
if (avail >= runtime->twake)
19071907
break;
19081908
snd_pcm_stream_unlock_irq(substream);
1909+
mutex_unlock(&runtime->buffer_mutex);
19091910

19101911
tout = schedule_timeout(wait_time);
19111912

1913+
mutex_lock(&runtime->buffer_mutex);
19121914
snd_pcm_stream_lock_irq(substream);
19131915
set_current_state(TASK_INTERRUPTIBLE);
19141916
switch (runtime->status->state) {
@@ -2219,6 +2221,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
22192221

22202222
nonblock = !!(substream->f_flags & O_NONBLOCK);
22212223

2224+
mutex_lock(&runtime->buffer_mutex);
22222225
snd_pcm_stream_lock_irq(substream);
22232226
err = pcm_accessible_state(runtime);
22242227
if (err < 0)
@@ -2310,6 +2313,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
23102313
if (xfer > 0 && err >= 0)
23112314
snd_pcm_update_state(substream, runtime);
23122315
snd_pcm_stream_unlock_irq(substream);
2316+
mutex_unlock(&runtime->buffer_mutex);
23132317
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
23142318
}
23152319
EXPORT_SYMBOL(__snd_pcm_lib_xfer);

0 commit comments

Comments
 (0)