lkml.org 
[lkml]   [2016]   [Feb]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 077/142] ALSA: seq: Fix double port list deletion
    Date
    From: Takashi Iwai <tiwai@suse.de>

    3.12-stable review patch. If anyone has any objections, please let me know.

    ===============

    commit 13d5e5d4725c64ec06040d636832e78453f477b7 upstream.

    The commit [7f0973e973cd: ALSA: seq: Fix lockdep warnings due to
    double mutex locks] split the management of two linked lists (source
    and destination) into two individual calls for avoiding the AB/BA
    deadlock. However, this may leave the possible double deletion of one
    of two lists when the counterpart is being deleted concurrently.
    It ends up with a list corruption, as revealed by syzkaller fuzzer.

    This patch fixes it by checking the list emptiness and skipping the
    deletion and the following process.

    BugLink: http://lkml.kernel.org/r/CACT4Y+bay9qsrz6dQu31EcGaH9XwfW7o3oBzSQUG9fMszoh=Sg@mail.gmail.com
    Fixes: 7f0973e973cd ('ALSA: seq: Fix lockdep warnings due to 'double mutex locks)
    Reported-by: Dmitry Vyukov <dvyukov@google.com>
    Tested-by: Dmitry Vyukov <dvyukov@google.com>
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Jiri Slaby <jslaby@suse.cz>
    ---
    sound/core/seq/seq_ports.c | 13 ++++++++-----
    1 file changed, 8 insertions(+), 5 deletions(-)

    diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
    index 67c91d226552..ee0522a8f730 100644
    --- a/sound/core/seq/seq_ports.c
    +++ b/sound/core/seq/seq_ports.c
    @@ -540,19 +540,22 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
    bool is_src, bool ack)
    {
    struct snd_seq_port_subs_info *grp;
    + struct list_head *list;
    + bool empty;

    grp = is_src ? &port->c_src : &port->c_dest;
    + list = is_src ? &subs->src_list : &subs->dest_list;
    down_write(&grp->list_mutex);
    write_lock_irq(&grp->list_lock);
    - if (is_src)
    - list_del(&subs->src_list);
    - else
    - list_del(&subs->dest_list);
    + empty = list_empty(list);
    + if (!empty)
    + list_del_init(list);
    grp->exclusive = 0;
    write_unlock_irq(&grp->list_lock);
    up_write(&grp->list_mutex);

    - unsubscribe_port(client, port, grp, &subs->info, ack);
    + if (!empty)
    + unsubscribe_port(client, port, grp, &subs->info, ack);
    }

    /* connect two ports */
    --
    2.7.1
    \
     
     \ /
      Last update: 2016-02-24 12:21    [W:4.054 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site