lkml.org 
[lkml]   [2022]   [Mar]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 12/39] ALSA: pcm: Fix races among concurrent read/write and buffer changes
    Date
    From: Takashi Iwai <tiwai@suse.de>

    commit dca947d4d26dbf925a64a6cfb2ddbc035e831a3d 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>
    ---
    sound/core/pcm_lib.c | 4 ++++
    1 file changed, 4 insertions(+)

    --- a/sound/core/pcm_lib.c
    +++ b/sound/core/pcm_lib.c
    @@ -1906,9 +1906,11 @@ static int wait_for_avail(struct snd_pcm
    if (avail >= runtime->twake)
    break;
    snd_pcm_stream_unlock_irq(substream);
    + mutex_unlock(&runtime->buffer_mutex);

    tout = schedule_timeout(wait_time);

    + mutex_lock(&runtime->buffer_mutex);
    snd_pcm_stream_lock_irq(substream);
    set_current_state(TASK_INTERRUPTIBLE);
    switch (runtime->status->state) {
    @@ -2219,6 +2221,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str

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

    + mutex_lock(&runtime->buffer_mutex);
    snd_pcm_stream_lock_irq(substream);
    err = pcm_accessible_state(runtime);
    if (err < 0)
    @@ -2310,6 +2313,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str
    if (xfer > 0 && err >= 0)
    snd_pcm_update_state(substream, runtime);
    snd_pcm_stream_unlock_irq(substream);
    + mutex_unlock(&runtime->buffer_mutex);
    return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
    }
    EXPORT_SYMBOL(__snd_pcm_lib_xfer);

    \
     
     \ /
      Last update: 2022-03-25 16:36    [W:6.162 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site