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;
                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);
        }
 
        }
 
 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;
 }
 
        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);
                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) {