lkml.org 
[lkml]   [2019]   [Mar]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 18/34] vxlan: test dev->flags & IFF_UP before calling gro_cells_receive()
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

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

    From: Eric Dumazet <edumazet@google.com>

    [ Upstream commit 59cbf56fcd98ba2a715b6e97c4e43f773f956393 ]

    Same reasons than the ones explained in commit 4179cb5a4c92
    ("vxlan: test dev->flags & IFF_UP before calling netif_rx()")

    netif_rx() or gro_cells_receive() must be called under a strict contract.

    At device dismantle phase, core networking clears IFF_UP
    and flush_all_backlogs() is called after rcu grace period
    to make sure no incoming packet might be in a cpu backlog
    and still referencing the device.

    A similar protocol is used for gro_cells infrastructure, as
    gro_cells_destroy() will be called only after a full rcu
    grace period is observed after IFF_UP has been cleared.

    Most drivers call netif_rx() from their interrupt handler,
    and since the interrupts are disabled at device dismantle,
    netif_rx() does not have to check dev->flags & IFF_UP

    Virtual drivers do not have this guarantee, and must
    therefore make the check themselves.

    Otherwise we risk use-after-free and/or crashes.

    Fixes: d342894c5d2f ("vxlan: virtual extensible lan")
    Signed-off-by: Eric Dumazet <edumazet@google.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/net/vxlan.c | 11 +++++++++++
    1 file changed, 11 insertions(+)

    --- a/drivers/net/vxlan.c
    +++ b/drivers/net/vxlan.c
    @@ -1468,6 +1468,14 @@ static int vxlan_rcv(struct sock *sk, st
    goto drop;
    }

    + rcu_read_lock();
    +
    + if (unlikely(!(vxlan->dev->flags & IFF_UP))) {
    + rcu_read_unlock();
    + atomic_long_inc(&vxlan->dev->rx_dropped);
    + goto drop;
    + }
    +
    stats = this_cpu_ptr(vxlan->dev->tstats);
    u64_stats_update_begin(&stats->syncp);
    stats->rx_packets++;
    @@ -1475,6 +1483,9 @@ static int vxlan_rcv(struct sock *sk, st
    u64_stats_update_end(&stats->syncp);

    gro_cells_receive(&vxlan->gro_cells, skb);
    +
    + rcu_read_unlock();
    +
    return 0;

    drop:

    \
     
     \ /
      Last update: 2019-03-18 10:35    [W:4.897 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site