lkml.org 
[lkml]   [2020]   [Jun]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 006/142] __netif_receive_skb_core: pass skb by reference
    Date
    From: Boris Sukholitko <boris.sukholitko@broadcom.com>

    [ Upstream commit c0bbbdc32febd4f034ecbf3ea17865785b2c0652 ]

    __netif_receive_skb_core may change the skb pointer passed into it (e.g.
    in rx_handler). The original skb may be freed as a result of this
    operation.

    The callers of __netif_receive_skb_core may further process original skb
    by using pt_prev pointer returned by __netif_receive_skb_core thus
    leading to unpleasant effects.

    The solution is to pass skb by reference into __netif_receive_skb_core.

    v2: Added Fixes tag and comment regarding ppt_prev and skb invariant.

    Fixes: 88eb1944e18c ("net: core: propagate SKB lists through packet_type lookup")
    Signed-off-by: Boris Sukholitko <boris.sukholitko@broadcom.com>
    Acked-by: Edward Cree <ecree@solarflare.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/core/dev.c | 20 +++++++++++++++-----
    1 file changed, 15 insertions(+), 5 deletions(-)

    --- a/net/core/dev.c
    +++ b/net/core/dev.c
    @@ -4713,11 +4713,12 @@ static inline int nf_ingress(struct sk_b
    return 0;
    }

    -static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
    +static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
    struct packet_type **ppt_prev)
    {
    struct packet_type *ptype, *pt_prev;
    rx_handler_func_t *rx_handler;
    + struct sk_buff *skb = *pskb;
    struct net_device *orig_dev;
    bool deliver_exact = false;
    int ret = NET_RX_DROP;
    @@ -4748,8 +4749,10 @@ another_round:
    ret2 = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog), skb);
    preempt_enable();

    - if (ret2 != XDP_PASS)
    - return NET_RX_DROP;
    + if (ret2 != XDP_PASS) {
    + ret = NET_RX_DROP;
    + goto out;
    + }
    skb_reset_mac_len(skb);
    }

    @@ -4899,6 +4902,13 @@ drop:
    }

    out:
    + /* The invariant here is that if *ppt_prev is not NULL
    + * then skb should also be non-NULL.
    + *
    + * Apparently *ppt_prev assignment above holds this invariant due to
    + * skb dereferencing near it.
    + */
    + *pskb = skb;
    return ret;
    }

    @@ -4908,7 +4918,7 @@ static int __netif_receive_skb_one_core(
    struct packet_type *pt_prev = NULL;
    int ret;

    - ret = __netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
    + ret = __netif_receive_skb_core(&skb, pfmemalloc, &pt_prev);
    if (pt_prev)
    ret = INDIRECT_CALL_INET(pt_prev->func, ipv6_rcv, ip_rcv, skb,
    skb->dev, pt_prev, orig_dev);
    @@ -4986,7 +4996,7 @@ static void __netif_receive_skb_list_cor
    struct packet_type *pt_prev = NULL;

    skb_list_del_init(skb);
    - __netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
    + __netif_receive_skb_core(&skb, pfmemalloc, &pt_prev);
    if (!pt_prev)
    continue;
    if (pt_curr != pt_prev || od_curr != orig_dev) {

    \
     
     \ /
      Last update: 2020-06-01 20:51    [W:3.170 / U:0.772 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site