lkml.org 
[lkml]   [2018]   [Feb]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 175/254] ALSA: aloop: Release cable upon open error path
    3.16.55-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Takashi Iwai <tiwai@suse.de>

    commit 9685347aa0a5c2869058ca6ab79fd8e93084a67f upstream.

    The aloop runtime object and its assignment in the cable are left even
    when opening a substream fails. This doesn't mean any memory leak,
    but it still keeps the invalid pointer that may be referred by the
    another side of the cable spontaneously, which is a potential Oops
    cause.

    Clean up the cable assignment and the empty cable upon the error path
    properly.

    Fixes: 597603d615d2 ("ALSA: introduce the snd-aloop module for the PCM loopback")
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    sound/drivers/aloop.c | 38 +++++++++++++++++++++++++-------------
    1 file changed, 25 insertions(+), 13 deletions(-)

    --- a/sound/drivers/aloop.c
    +++ b/sound/drivers/aloop.c
    @@ -659,12 +659,31 @@ static int rule_channels(struct snd_pcm_
    return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    }

    +static void free_cable(struct snd_pcm_substream *substream)
    +{
    + struct loopback *loopback = substream->private_data;
    + int dev = get_cable_index(substream);
    + struct loopback_cable *cable;
    +
    + cable = loopback->cables[substream->number][dev];
    + if (!cable)
    + return;
    + if (cable->streams[!substream->stream]) {
    + /* other stream is still alive */
    + cable->streams[substream->stream] = NULL;
    + } else {
    + /* free the cable */
    + loopback->cables[substream->number][dev] = NULL;
    + kfree(cable);
    + }
    +}
    +
    static int loopback_open(struct snd_pcm_substream *substream)
    {
    struct snd_pcm_runtime *runtime = substream->runtime;
    struct loopback *loopback = substream->private_data;
    struct loopback_pcm *dpcm;
    - struct loopback_cable *cable;
    + struct loopback_cable *cable = NULL;
    int err = 0;
    int dev = get_cable_index(substream);

    @@ -683,7 +702,6 @@ static int loopback_open(struct snd_pcm_
    if (!cable) {
    cable = kzalloc(sizeof(*cable), GFP_KERNEL);
    if (!cable) {
    - kfree(dpcm);
    err = -ENOMEM;
    goto unlock;
    }
    @@ -725,6 +743,10 @@ static int loopback_open(struct snd_pcm_
    else
    runtime->hw = cable->hw;
    unlock:
    + if (err < 0) {
    + free_cable(substream);
    + kfree(dpcm);
    + }
    mutex_unlock(&loopback->cable_lock);
    return err;
    }
    @@ -733,20 +755,10 @@ static int loopback_close(struct snd_pcm
    {
    struct loopback *loopback = substream->private_data;
    struct loopback_pcm *dpcm = substream->runtime->private_data;
    - struct loopback_cable *cable;
    - int dev = get_cable_index(substream);

    loopback_timer_stop(dpcm);
    mutex_lock(&loopback->cable_lock);
    - cable = loopback->cables[substream->number][dev];
    - if (cable->streams[!substream->stream]) {
    - /* other stream is still alive */
    - cable->streams[substream->stream] = NULL;
    - } else {
    - /* free the cable */
    - loopback->cables[substream->number][dev] = NULL;
    - kfree(cable);
    - }
    + free_cable(substream);
    mutex_unlock(&loopback->cable_lock);
    return 0;
    }
    \
     
     \ /
      Last update: 2018-02-28 17:44    [W:4.379 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site