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.

bpf: Unclone skb head on bpf_dynptr_write to skb metadata

Currently bpf_dynptr_from_skb_meta() marks the dynptr as read-only when
the skb is cloned, preventing writes to metadata.

Remove this restriction and unclone the skb head on bpf_dynptr_write() to
metadata, now that the metadata is preserved during uncloning. This makes
metadata dynptr consistent with skb dynptr, allowing writes regardless of
whether the skb is cloned.

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-3-5ceb08a9b37b@cloudflare.com

authored by

Jakub Sitnicki and committed by
Martin KaFai Lau
f38499ff 290fc0be

+23 -10
+9
include/linux/filter.h
··· 1781 1781 void *bpf_xdp_pointer(struct xdp_buff *xdp, u32 offset, u32 len); 1782 1782 void bpf_xdp_copy_buf(struct xdp_buff *xdp, unsigned long off, 1783 1783 void *buf, unsigned long len, bool flush); 1784 + int __bpf_skb_meta_store_bytes(struct sk_buff *skb, u32 offset, 1785 + const void *from, u32 len, u64 flags); 1784 1786 void *bpf_skb_meta_pointer(struct sk_buff *skb, u32 offset); 1785 1787 #else /* CONFIG_NET */ 1786 1788 static inline int __bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset, ··· 1817 1815 static inline void bpf_xdp_copy_buf(struct xdp_buff *xdp, unsigned long off, void *buf, 1818 1816 unsigned long len, bool flush) 1819 1817 { 1818 + } 1819 + 1820 + static inline int __bpf_skb_meta_store_bytes(struct sk_buff *skb, u32 offset, 1821 + const void *from, u32 len, 1822 + u64 flags) 1823 + { 1824 + return -EOPNOTSUPP; 1820 1825 } 1821 1826 1822 1827 static inline void *bpf_skb_meta_pointer(struct sk_buff *skb, u32 offset)
+2 -4
kernel/bpf/helpers.c
··· 1842 1842 return -EINVAL; 1843 1843 return __bpf_xdp_store_bytes(dst->data, dst->offset + offset, src, len); 1844 1844 case BPF_DYNPTR_TYPE_SKB_META: 1845 - if (flags) 1846 - return -EINVAL; 1847 - memmove(bpf_skb_meta_pointer(dst->data, dst->offset + offset), src, len); 1848 - return 0; 1845 + return __bpf_skb_meta_store_bytes(dst->data, dst->offset + offset, src, 1846 + len, flags); 1849 1847 default: 1850 1848 WARN_ONCE(true, "bpf_dynptr_write: unknown dynptr type %d\n", type); 1851 1849 return -EFAULT;
+12 -6
net/core/filter.c
··· 12102 12102 return skb_metadata_end(skb) - skb_metadata_len(skb) + offset; 12103 12103 } 12104 12104 12105 + int __bpf_skb_meta_store_bytes(struct sk_buff *skb, u32 offset, 12106 + const void *from, u32 len, u64 flags) 12107 + { 12108 + if (unlikely(flags)) 12109 + return -EINVAL; 12110 + if (unlikely(bpf_try_make_writable(skb, 0))) 12111 + return -EFAULT; 12112 + 12113 + memmove(bpf_skb_meta_pointer(skb, offset), from, len); 12114 + return 0; 12115 + } 12116 + 12105 12117 __bpf_kfunc_start_defs(); 12106 12118 __bpf_kfunc int bpf_dynptr_from_skb(struct __sk_buff *s, u64 flags, 12107 12119 struct bpf_dynptr *ptr__uninit) ··· 12141 12129 * XDP context with bpf_xdp_adjust_meta(). Serves as an alternative to 12142 12130 * &__sk_buff->data_meta. 12143 12131 * 12144 - * If passed @skb_ is a clone which shares the data with the original, the 12145 - * dynptr will be read-only. This limitation may be lifted in the future. 12146 - * 12147 12132 * Return: 12148 12133 * * %0 - dynptr ready to use 12149 12134 * * %-EINVAL - invalid flags, dynptr set to null ··· 12157 12148 } 12158 12149 12159 12150 bpf_dynptr_init(ptr, skb, BPF_DYNPTR_TYPE_SKB_META, 0, skb_metadata_len(skb)); 12160 - 12161 - if (skb_cloned(skb)) 12162 - bpf_dynptr_set_rdonly(ptr); 12163 12151 12164 12152 return 0; 12165 12153 }