[PATCH bpf-next v4 00/16] Make TC BPF helpers preserve skb metadata
From: Jakub Sitnicki <jakub@cloudflare.com>
Date: 2025-11-05 20:19:51
Also in:
bpf
Changes in v4: - Fix copy-paste bug in check_metadata() test helper (AI review) - Add "out of scope" section (at the bottom) - Link to v3: https://lore.kernel.org/r/20251026-skb-meta-rx-path-v3-0-37cceebb95d3@cloudflare.com (local) Changes in v3: - Use the already existing BPF_STREAM_STDERR const in tests (Martin) - Unclone skb head on bpf_dynptr_write to skb metadata (patch 3) (Martin) - Swap order of patches 1 & 2 to refer to skb_postpush_data_move() in docs - Mention in skb_data_move() docs how to move just the metadata - Note in pskb_expand_head() docs to move metadata after skb_push() (Jakub) - Link to v2: https://lore.kernel.org/r/20251019-skb-meta-rx-path-v2-0-f9a58f3eb6d6@cloudflare.com (local) Changes in v2: - Tweak WARN_ON_ONCE check in skb_data_move() (patch 2) - Convert all tests to verify skb metadata in BPF (patches 9-10) - Add test coverage for modified BPF helpers (patches 12-15) - Link to RFCv1: https://lore.kernel.org/r/20250929-skb-meta-rx-path-v1-0-de700a7ab1cb@cloudflare.com (local) This patch set continues our work [1] to allow BPF programs and user-space applications to attach multiple bytes of metadata to packets via the XDP/skb metadata area. The focus of this patch set it to ensure that skb metadata remains intact when packets pass through a chain of TC BPF programs that call helpers which operate on skb head. Currently, several helpers that either adjust the skb->data pointer or reallocate skb->head do not preserve metadata at its expected location, that is immediately in front of the MAC header. These are: - bpf_skb_adjust_room - bpf_skb_change_head - bpf_skb_change_proto - bpf_skb_change_tail - bpf_skb_vlan_pop - bpf_skb_vlan_push In TC BPF context, metadata must be moved whenever skb->data changes to keep the skb->data_meta pointer valid. I don't see any way around it. Creative ideas how to avoid that would be very welcome. With that in mind, we can patch the helpers in at least two different ways: 1. Integrate metadata move into header move Replace the existing memmove, which follows skb_push/pull, with a helper that moves both headers and metadata in a single call. This avoids an extra memmove but reduces transparency. skb_pull(skb, len); - memmove(skb->data, skb->data - len, n); + skb_postpull_data_move(skb, len, n); skb->mac_header += len; skb_push(skb, len) - memmove(skb->data, skb->data + len, n); + skb_postpush_data_move(skb, len, n); skb->mac_header -= len; 2. Move metadata separately Add a dedicated metadata move after the header move. This is more explicit but costs an additional memmove. skb_pull(skb, len); memmove(skb->data, skb->data - len, n); + skb_metadata_postpull_move(skb, len); skb->mac_header += len; skb_push(skb, len) + skb_metadata_postpush_move(skb, len); memmove(skb->data, skb->data + len, n); skb->mac_header -= len; This patch set implements option (1), expecting that "you can have just one memmove" will be the most obvious feedback, while readability is a, somewhat subjective, matter of taste, which I don't claim to have ;-) The structure of the patch set is as follows: - patches 1-4 prepare ground for safe-proofing the BPF helpers - patches 5-9 modify the BPF helpers to preserve skb metadata - patches 10-11 prepare ground for metadata tests with BPF helper calls - patches 12-16 adapt and expand tests to cover the made changes Out of scope for this series: - safe-proofing tunnel & tagging devices - VLAN, GRE, ... (next in line, in development preview at [2]) - metadata access after packet foward (to do after Rx path - once metadata reliably reaches sk_filter) Thanks, -jkbs [1] https://lore.kernel.org/all/20250814-skb-metadata-thru-dynptr-v7-0-8a39e636e0fb@cloudflare.com/ (local) [2] https://github.com/jsitnicki/linux/commits/skb-meta/safeproof-netdevs/ --- Jakub Sitnicki (16): net: Helper to move packet data and metadata after skb_push/pull net: Preserve metadata on pskb_expand_head bpf: Unclone skb head on bpf_dynptr_write to skb metadata vlan: Make vlan_remove_tag return nothing bpf: Make bpf_skb_vlan_pop helper metadata-safe bpf: Make bpf_skb_vlan_push helper metadata-safe bpf: Make bpf_skb_adjust_room metadata-safe bpf: Make bpf_skb_change_proto helper metadata-safe bpf: Make bpf_skb_change_head helper metadata-safe selftests/bpf: Verify skb metadata in BPF instead of userspace selftests/bpf: Dump skb metadata on verification failure selftests/bpf: Expect unclone to preserve skb metadata selftests/bpf: Cover skb metadata access after vlan push/pop helper selftests/bpf: Cover skb metadata access after bpf_skb_adjust_room selftests/bpf: Cover skb metadata access after change_head/tail helper selftests/bpf: Cover skb metadata access after bpf_skb_change_proto include/linux/filter.h | 9 + include/linux/if_vlan.h | 13 +- include/linux/skbuff.h | 75 ++++ kernel/bpf/helpers.c | 6 +- net/core/filter.c | 34 +- net/core/skbuff.c | 6 +- .../bpf/prog_tests/xdp_context_test_run.c | 129 ++++--- tools/testing/selftests/bpf/progs/test_xdp_meta.c | 386 +++++++++++++++------ 8 files changed, 475 insertions(+), 183 deletions(-)