Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: Helper to move packet data and metadata after skb_push/pull

Lay groundwork for fixing BPF helpers available to TC(X) programs.

When skb_push() or skb_pull() is called in a TC(X) ingress BPF program, the
skb metadata must be kept in front of the MAC header. Otherwise, BPF
programs using the __sk_buff->data_meta pseudo-pointer lose access to it.

Introduce a helper that moves both metadata and a specified number of
packet data bytes together, suitable as a drop-in replacement for
memmove().

Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://patch.msgid.link/20251105-skb-meta-rx-path-v4-1-5ceb08a9b37b@cloudflare.com

authored by

Jakub Sitnicki and committed by
Martin KaFai Lau
8989d328 a0c3aefb

+75
+75
include/linux/skbuff.h
··· 4564 4564 skb_metadata_set(skb, 0); 4565 4565 } 4566 4566 4567 + /** 4568 + * skb_data_move - Move packet data and metadata after skb_push() or skb_pull(). 4569 + * @skb: packet to operate on 4570 + * @len: number of bytes pushed or pulled from &sk_buff->data 4571 + * @n: number of bytes to memmove() from pre-push/pull &sk_buff->data 4572 + * 4573 + * Moves @n bytes of packet data, can be zero, and all bytes of skb metadata. 4574 + * 4575 + * Assumes metadata is located immediately before &sk_buff->data prior to the 4576 + * push/pull, and that sufficient headroom exists to hold it after an 4577 + * skb_push(). Otherwise, metadata is cleared and a one-time warning is issued. 4578 + * 4579 + * Prefer skb_postpull_data_move() or skb_postpush_data_move() to calling this 4580 + * helper directly. 4581 + */ 4582 + static inline void skb_data_move(struct sk_buff *skb, const int len, 4583 + const unsigned int n) 4584 + { 4585 + const u8 meta_len = skb_metadata_len(skb); 4586 + u8 *meta, *meta_end; 4587 + 4588 + if (!len || (!n && !meta_len)) 4589 + return; 4590 + 4591 + if (!meta_len) 4592 + goto no_metadata; 4593 + 4594 + meta_end = skb_metadata_end(skb); 4595 + meta = meta_end - meta_len; 4596 + 4597 + if (WARN_ON_ONCE(meta_end + len != skb->data || 4598 + meta_len > skb_headroom(skb))) { 4599 + skb_metadata_clear(skb); 4600 + goto no_metadata; 4601 + } 4602 + 4603 + memmove(meta + len, meta, meta_len + n); 4604 + return; 4605 + 4606 + no_metadata: 4607 + memmove(skb->data, skb->data - len, n); 4608 + } 4609 + 4610 + /** 4611 + * skb_postpull_data_move - Move packet data and metadata after skb_pull(). 4612 + * @skb: packet to operate on 4613 + * @len: number of bytes pulled from &sk_buff->data 4614 + * @n: number of bytes to memmove() from pre-pull &sk_buff->data 4615 + * 4616 + * See skb_data_move() for details. 4617 + */ 4618 + static inline void skb_postpull_data_move(struct sk_buff *skb, 4619 + const unsigned int len, 4620 + const unsigned int n) 4621 + { 4622 + DEBUG_NET_WARN_ON_ONCE(len > INT_MAX); 4623 + skb_data_move(skb, len, n); 4624 + } 4625 + 4626 + /** 4627 + * skb_postpush_data_move - Move packet data and metadata after skb_push(). 4628 + * @skb: packet to operate on 4629 + * @len: number of bytes pushed onto &sk_buff->data 4630 + * @n: number of bytes to memmove() from pre-push &sk_buff->data 4631 + * 4632 + * See skb_data_move() for details. 4633 + */ 4634 + static inline void skb_postpush_data_move(struct sk_buff *skb, 4635 + const unsigned int len, 4636 + const unsigned int n) 4637 + { 4638 + DEBUG_NET_WARN_ON_ONCE(len > INT_MAX); 4639 + skb_data_move(skb, -len, n); 4640 + } 4641 + 4567 4642 struct sk_buff *skb_clone_sk(struct sk_buff *skb); 4568 4643 4569 4644 #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING