lkml.org 
[lkml]   [2017]   [Nov]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 084/147] packet: hold bind lock when rebinding to fanout hook
    3.2.95-rc1 review patch.  If anyone has any objections, please let me know.

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

    From: Willem de Bruijn <willemb@google.com>

    commit 008ba2a13f2d04c947adc536d19debb8fe66f110 upstream.

    Packet socket bind operations must hold the po->bind_lock. This keeps
    po->running consistent with whether the socket is actually on a ptype
    list to receive packets.

    fanout_add unbinds a socket and its packet_rcv/tpacket_rcv call, then
    binds the fanout object to receive through packet_rcv_fanout.

    Make it hold the po->bind_lock when testing po->running and rebinding.
    Else, it can race with other rebind operations, such as that in
    packet_set_ring from packet_rcv to tpacket_rcv. Concurrent updates
    can result in a socket being added to a fanout group twice, causing
    use-after-free KASAN bug reports, among others.

    Reported independently by both trinity and syzkaller.
    Verified that the syzkaller reproducer passes after this patch.

    Fixes: dc99f600698d ("packet: Add fanout support.")
    Reported-by: nixioaming <nixiaoming@huawei.com>
    Signed-off-by: Willem de Bruijn <willemb@google.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    [bwh: Backported to 3.2: use atomic_read() not refcount_read()]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    net/packet/af_packet.c | 16 +++++++++++-----
    1 file changed, 11 insertions(+), 5 deletions(-)

    --- a/net/packet/af_packet.c
    +++ b/net/packet/af_packet.c
    @@ -1294,10 +1294,6 @@ static int fanout_add(struct sock *sk, u

    mutex_lock(&fanout_mutex);

    - err = -EINVAL;
    - if (!po->running)
    - goto out;
    -
    err = -EALREADY;
    if (po->fanout)
    goto out;
    @@ -1334,7 +1330,10 @@ static int fanout_add(struct sock *sk, u
    list_add(&match->list, &fanout_list);
    }
    err = -EINVAL;
    - if (match->type == type &&
    +
    + spin_lock(&po->bind_lock);
    + if (po->running &&
    + match->type == type &&
    match->prot_hook.type == po->prot_hook.type &&
    match->prot_hook.dev == po->prot_hook.dev) {
    err = -ENOSPC;
    @@ -1346,6 +1345,13 @@ static int fanout_add(struct sock *sk, u
    err = 0;
    }
    }
    + spin_unlock(&po->bind_lock);
    +
    + if (err && !atomic_read(&match->sk_ref)) {
    + list_del(&match->list);
    + kfree(match);
    + }
    +
    out:
    mutex_unlock(&fanout_mutex);
    return err;
    \
     
     \ /
      Last update: 2017-11-08 20:57    [W:4.642 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site