case XDP_PASS:
                        /* Recalculate length in case bpf program changed it */
                        delta = orig_data - xdp.data;
+                       len = xdp.data_end - xdp.data;
                        break;
                case XDP_TX:
                        xdpf = convert_to_xdp_frame(&xdp);
                goto err;
        }
        skb_reserve(skb, headroom - delta);
-       skb_put(skb, len + delta);
+       skb_put(skb, len);
        if (!delta) {
                buf += header_offset;
                memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len);
                        offset = xdp.data -
                                        page_address(xdp_page) - vi->hdr_len;
 
+                       /* recalculate len if xdp.data or xdp.data_end were
+                        * adjusted
+                        */
+                       len = xdp.data_end - xdp.data;
                        /* We can only create skb based on xdp_page. */
                        if (unlikely(xdp_page != page)) {
                                rcu_read_unlock();