The XDP Program and the eBPF Verifier's Packet Access Rules: Why Reading Byte 1500 Requires Proving You Checked the Length First

2026-07-24

XDP (eXpress Data Path) runs your eBPF program on the NIC driver's receive path before Linux allocates an skb. You get raw packet bytes, and you return XDP_PASS, XDP_DROP, XDP_TX, or XDP_REDIRECT. At 10 Gbps line rate that's ~14.88 million packets/second per core, so this path lives or dies on avoiding overhead. The catch: the eBPF verifier will refuse to load your program unless it can statically prove that every packet-byte access is in bounds.

The context struct struct xdp_md gives you two pointers: data and data_end. Both are __u32 in the UAPI but the verifier tracks them as tagged pointer types (PTR_TO_PACKET and PTR_TO_PACKET_END). When you write:

...the verifier walks both branches of the if. On the false branch, it narrows the range known about data: it now knows data + 14 <= end, so accessing 14 bytes at data is safe. Skip the check, and the load fails with invalid access to packet, off=0 size=14, R1(id=0,off=0,r=0) — the r=0 means "range proven safe is zero bytes."

Concrete example — parsing an IPv4 header: after checking the Ethernet header, you must re-check before touching struct iphdr. The verifier does not carry range info across an assignment to a new pointer without a fresh comparison:

That last check is the subtle one: ip->ihl is a 4-bit field, so the verifier knows it's 0–15, and combined with the >= 5 check it proves the multiplication won't overflow. Without the < 5 check first, some kernels reject the arithmetic entirely.

Rule of thumb: every N-byte packet read needs a ptr + N > data_end check in the same basic block, or in a dominating block whose bound the verifier can still see. Function calls, loops, and helper returns can invalidate your proven range — after bpf_xdp_adjust_head(), all prior PTR_TO_PACKET pointers become SCALAR_VALUE and you must re-derive them from ctx->data.

Key Takeaway: XDP's speed comes from skipping the sk_buff, but the price is that the eBPF verifier makes you write explicit bounds checks in a form it can prove — every packet byte you touch must be dominated by a ptr + N > data_end comparison in the same control-flow region.

All newsletters