Skip to content

Commit c0bbbdc

Browse files
Boris Sukholitkodavem330
authored andcommitted
__netif_receive_skb_core: pass skb by reference
__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: 88eb194 ("net: core: propagate SKB lists through packet_type lookup") Signed-off-by: Boris Sukholitko <[email protected]> Acked-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 88d7fcf commit c0bbbdc

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

net/core/dev.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4988,11 +4988,12 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,
49884988
return 0;
49894989
}
49904990

4991-
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
4991+
static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
49924992
struct packet_type **ppt_prev)
49934993
{
49944994
struct packet_type *ptype, *pt_prev;
49954995
rx_handler_func_t *rx_handler;
4996+
struct sk_buff *skb = *pskb;
49964997
struct net_device *orig_dev;
49974998
bool deliver_exact = false;
49984999
int ret = NET_RX_DROP;
@@ -5023,8 +5024,10 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
50235024
ret2 = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog), skb);
50245025
preempt_enable();
50255026

5026-
if (ret2 != XDP_PASS)
5027-
return NET_RX_DROP;
5027+
if (ret2 != XDP_PASS) {
5028+
ret = NET_RX_DROP;
5029+
goto out;
5030+
}
50285031
skb_reset_mac_len(skb);
50295032
}
50305033

@@ -5174,6 +5177,13 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
51745177
}
51755178

51765179
out:
5180+
/* The invariant here is that if *ppt_prev is not NULL
5181+
* then skb should also be non-NULL.
5182+
*
5183+
* Apparently *ppt_prev assignment above holds this invariant due to
5184+
* skb dereferencing near it.
5185+
*/
5186+
*pskb = skb;
51775187
return ret;
51785188
}
51795189

@@ -5183,7 +5193,7 @@ static int __netif_receive_skb_one_core(struct sk_buff *skb, bool pfmemalloc)
51835193
struct packet_type *pt_prev = NULL;
51845194
int ret;
51855195

5186-
ret = __netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
5196+
ret = __netif_receive_skb_core(&skb, pfmemalloc, &pt_prev);
51875197
if (pt_prev)
51885198
ret = INDIRECT_CALL_INET(pt_prev->func, ipv6_rcv, ip_rcv, skb,
51895199
skb->dev, pt_prev, orig_dev);
@@ -5261,7 +5271,7 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo
52615271
struct packet_type *pt_prev = NULL;
52625272

52635273
skb_list_del_init(skb);
5264-
__netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
5274+
__netif_receive_skb_core(&skb, pfmemalloc, &pt_prev);
52655275
if (!pt_prev)
52665276
continue;
52675277
if (pt_curr != pt_prev || od_curr != orig_dev) {

0 commit comments

Comments
 (0)