On Thu, Feb 16, 2023 at 2:56 PM Joanne Koong <joannelkoong@xxxxxxxxx> wrote: > > Add skb dynptrs, which are dynptrs whose underlying pointer points > to a skb. The dynptr acts on skb data. skb dynptrs have two main > benefits. One is that they allow operations on sizes that are not > statically known at compile-time (eg variable-sized accesses). > Another is that parsing the packet data through dynptrs (instead of > through direct access of skb->data and skb->data_end) can be more > ergonomic and less brittle (eg does not need manual if checking for > being within bounds of data_end). > > For bpf prog types that don't support writes on skb data, the dynptr is > read-only (bpf_dynptr_write() will return an error) > > For reads and writes through the bpf_dynptr_read() and bpf_dynptr_write() > interfaces, reading and writing from/to data in the head as well as from/to > non-linear paged buffers is supported. Data slices through the > bpf_dynptr_data API are not supported; instead bpf_dynptr_slice() and > bpf_dynptr_slice_rdwr() (added in subsequent commit) should be used. > > For examples of how skb dynptrs can be used, please see the attached > selftests. > > Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> > --- > include/linux/bpf.h | 14 ++++++- > include/linux/filter.h | 18 ++++++++ > include/uapi/linux/bpf.h | 14 ++++++- > kernel/bpf/btf.c | 18 ++++++++ > kernel/bpf/helpers.c | 76 +++++++++++++++++++++++++++------- > kernel/bpf/verifier.c | 70 ++++++++++++++++++++++++++++++- > net/core/filter.c | 67 ++++++++++++++++++++++++++++++ > tools/include/uapi/linux/bpf.h | 14 ++++++- > 8 files changed, 270 insertions(+), 21 deletions(-) > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index 296841a31749..3d18be35a5e6 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -607,11 +607,14 @@ enum bpf_type_flag { > */ > NON_OWN_REF = BIT(14 + BPF_BASE_TYPE_BITS), > > + /* DYNPTR points to sk_buff */ > + DYNPTR_TYPE_SKB = BIT(15 + BPF_BASE_TYPE_BITS), > + > __BPF_TYPE_FLAG_MAX, > __BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1, > }; > > -#define DYNPTR_TYPE_FLAG_MASK (DYNPTR_TYPE_LOCAL | DYNPTR_TYPE_RINGBUF) > +#define DYNPTR_TYPE_FLAG_MASK (DYNPTR_TYPE_LOCAL | DYNPTR_TYPE_RINGBUF | DYNPTR_TYPE_SKB) > > /* Max number of base types. */ > #define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS) > @@ -1146,6 +1149,8 @@ enum bpf_dynptr_type { > BPF_DYNPTR_TYPE_LOCAL, > /* Underlying data is a ringbuf record */ > BPF_DYNPTR_TYPE_RINGBUF, > + /* Underlying data is a sk_buff */ > + BPF_DYNPTR_TYPE_SKB, > }; > > int bpf_dynptr_check_size(u32 size); > @@ -2846,6 +2851,8 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, > struct bpf_insn *insn_buf, > struct bpf_prog *prog, > u32 *target_size); > +int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags, > + struct bpf_dynptr_kern *ptr); > #else > static inline bool bpf_sock_common_is_valid_access(int off, int size, > enum bpf_access_type type, > @@ -2867,6 +2874,11 @@ static inline u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, > { > return 0; > } > +static inline int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags, > + struct bpf_dynptr_kern *ptr) > +{ > + return 0; should this return -EOPNOTSUPP instead? > +} > #endif > > #ifdef CONFIG_INET [...]