Skip to content

Commit 5c42715

Browse files
author
Martin KaFai Lau
committed
Merge branch 'bpf-next/skb-meta-dynptr' into 'bpf-next/master'
Merge 'skb-meta-dynptr' branch into 'master' branch. No conflict. Signed-off-by: Martin KaFai Lau <[email protected]>
2 parents dbe99ea + 7f7a958 commit 5c42715

File tree

13 files changed

+1027
-27
lines changed

13 files changed

+1027
-27
lines changed

include/linux/bpf.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,12 +767,15 @@ enum bpf_type_flag {
767767
*/
768768
MEM_WRITE = BIT(18 + BPF_BASE_TYPE_BITS),
769769

770+
/* DYNPTR points to skb_metadata_end()-skb_metadata_len() */
771+
DYNPTR_TYPE_SKB_META = BIT(19 + BPF_BASE_TYPE_BITS),
772+
770773
__BPF_TYPE_FLAG_MAX,
771774
__BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1,
772775
};
773776

774777
#define DYNPTR_TYPE_FLAG_MASK (DYNPTR_TYPE_LOCAL | DYNPTR_TYPE_RINGBUF | DYNPTR_TYPE_SKB \
775-
| DYNPTR_TYPE_XDP)
778+
| DYNPTR_TYPE_XDP | DYNPTR_TYPE_SKB_META)
776779

777780
/* Max number of base types. */
778781
#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS)
@@ -1358,6 +1361,8 @@ enum bpf_dynptr_type {
13581361
BPF_DYNPTR_TYPE_SKB,
13591362
/* Underlying data is a xdp_buff */
13601363
BPF_DYNPTR_TYPE_XDP,
1364+
/* Points to skb_metadata_end()-skb_metadata_len() */
1365+
BPF_DYNPTR_TYPE_SKB_META,
13611366
};
13621367

13631368
int bpf_dynptr_check_size(u32 size);

include/linux/filter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,6 +1784,7 @@ int __bpf_xdp_store_bytes(struct xdp_buff *xdp, u32 offset, void *buf, u32 len);
17841784
void *bpf_xdp_pointer(struct xdp_buff *xdp, u32 offset, u32 len);
17851785
void bpf_xdp_copy_buf(struct xdp_buff *xdp, unsigned long off,
17861786
void *buf, unsigned long len, bool flush);
1787+
void *bpf_skb_meta_pointer(struct sk_buff *skb, u32 offset);
17871788
#else /* CONFIG_NET */
17881789
static inline int __bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset,
17891790
void *to, u32 len)
@@ -1818,6 +1819,11 @@ static inline void bpf_xdp_copy_buf(struct xdp_buff *xdp, unsigned long off, voi
18181819
unsigned long len, bool flush)
18191820
{
18201821
}
1822+
1823+
static inline void *bpf_skb_meta_pointer(struct sk_buff *skb, u32 offset)
1824+
{
1825+
return NULL;
1826+
}
18211827
#endif /* CONFIG_NET */
18221828

18231829
#endif /* __LINUX_FILTER_H__ */

kernel/bpf/helpers.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,9 @@ static int __bpf_dynptr_read(void *dst, u32 len, const struct bpf_dynptr_kern *s
17801780
return __bpf_skb_load_bytes(src->data, src->offset + offset, dst, len);
17811781
case BPF_DYNPTR_TYPE_XDP:
17821782
return __bpf_xdp_load_bytes(src->data, src->offset + offset, dst, len);
1783+
case BPF_DYNPTR_TYPE_SKB_META:
1784+
memmove(dst, bpf_skb_meta_pointer(src->data, src->offset + offset), len);
1785+
return 0;
17831786
default:
17841787
WARN_ONCE(true, "bpf_dynptr_read: unknown dynptr type %d\n", type);
17851788
return -EFAULT;
@@ -1836,6 +1839,11 @@ int __bpf_dynptr_write(const struct bpf_dynptr_kern *dst, u32 offset, void *src,
18361839
if (flags)
18371840
return -EINVAL;
18381841
return __bpf_xdp_store_bytes(dst->data, dst->offset + offset, src, len);
1842+
case BPF_DYNPTR_TYPE_SKB_META:
1843+
if (flags)
1844+
return -EINVAL;
1845+
memmove(bpf_skb_meta_pointer(dst->data, dst->offset + offset), src, len);
1846+
return 0;
18391847
default:
18401848
WARN_ONCE(true, "bpf_dynptr_write: unknown dynptr type %d\n", type);
18411849
return -EFAULT;
@@ -1882,6 +1890,7 @@ BPF_CALL_3(bpf_dynptr_data, const struct bpf_dynptr_kern *, ptr, u32, offset, u3
18821890
return (unsigned long)(ptr->data + ptr->offset + offset);
18831891
case BPF_DYNPTR_TYPE_SKB:
18841892
case BPF_DYNPTR_TYPE_XDP:
1893+
case BPF_DYNPTR_TYPE_SKB_META:
18851894
/* skb and xdp dynptrs should use bpf_dynptr_slice / bpf_dynptr_slice_rdwr */
18861895
return 0;
18871896
default:
@@ -2710,6 +2719,8 @@ __bpf_kfunc void *bpf_dynptr_slice(const struct bpf_dynptr *p, u32 offset,
27102719
bpf_xdp_copy_buf(ptr->data, ptr->offset + offset, buffer__opt, len, false);
27112720
return buffer__opt;
27122721
}
2722+
case BPF_DYNPTR_TYPE_SKB_META:
2723+
return bpf_skb_meta_pointer(ptr->data, ptr->offset + offset);
27132724
default:
27142725
WARN_ONCE(true, "unknown dynptr type %d\n", type);
27152726
return NULL;

kernel/bpf/log.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ const char *dynptr_type_str(enum bpf_dynptr_type type)
498498
return "skb";
499499
case BPF_DYNPTR_TYPE_XDP:
500500
return "xdp";
501+
case BPF_DYNPTR_TYPE_SKB_META:
502+
return "skb_meta";
501503
case BPF_DYNPTR_TYPE_INVALID:
502504
return "<invalid>";
503505
default:

kernel/bpf/verifier.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,8 @@ static enum bpf_dynptr_type arg_to_dynptr_type(enum bpf_arg_type arg_type)
674674
return BPF_DYNPTR_TYPE_SKB;
675675
case DYNPTR_TYPE_XDP:
676676
return BPF_DYNPTR_TYPE_XDP;
677+
case DYNPTR_TYPE_SKB_META:
678+
return BPF_DYNPTR_TYPE_SKB_META;
677679
default:
678680
return BPF_DYNPTR_TYPE_INVALID;
679681
}
@@ -690,6 +692,8 @@ static enum bpf_type_flag get_dynptr_type_flag(enum bpf_dynptr_type type)
690692
return DYNPTR_TYPE_SKB;
691693
case BPF_DYNPTR_TYPE_XDP:
692694
return DYNPTR_TYPE_XDP;
695+
case BPF_DYNPTR_TYPE_SKB_META:
696+
return DYNPTR_TYPE_SKB_META;
693697
default:
694698
return 0;
695699
}
@@ -2274,7 +2278,8 @@ static bool reg_is_pkt_pointer_any(const struct bpf_reg_state *reg)
22742278
static bool reg_is_dynptr_slice_pkt(const struct bpf_reg_state *reg)
22752279
{
22762280
return base_type(reg->type) == PTR_TO_MEM &&
2277-
(reg->type & DYNPTR_TYPE_SKB || reg->type & DYNPTR_TYPE_XDP);
2281+
(reg->type &
2282+
(DYNPTR_TYPE_SKB | DYNPTR_TYPE_XDP | DYNPTR_TYPE_SKB_META));
22782283
}
22792284

22802285
/* Unmodified PTR_TO_PACKET[_META,_END] register from ctx access. */
@@ -11641,7 +11646,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1164111646
if (dynptr_type == BPF_DYNPTR_TYPE_INVALID)
1164211647
return -EFAULT;
1164311648

11644-
if (dynptr_type == BPF_DYNPTR_TYPE_SKB)
11649+
if (dynptr_type == BPF_DYNPTR_TYPE_SKB ||
11650+
dynptr_type == BPF_DYNPTR_TYPE_SKB_META)
1164511651
/* this will trigger clear_all_pkt_pointers(), which will
1164611652
* invalidate all dynptr slices associated with the skb
1164711653
*/
@@ -12228,6 +12234,7 @@ enum special_kfunc_type {
1222812234
KF_bpf_rbtree_right,
1222912235
KF_bpf_dynptr_from_skb,
1223012236
KF_bpf_dynptr_from_xdp,
12237+
KF_bpf_dynptr_from_skb_meta,
1223112238
KF_bpf_dynptr_slice,
1223212239
KF_bpf_dynptr_slice_rdwr,
1223312240
KF_bpf_dynptr_clone,
@@ -12277,9 +12284,11 @@ BTF_ID(func, bpf_rbtree_right)
1227712284
#ifdef CONFIG_NET
1227812285
BTF_ID(func, bpf_dynptr_from_skb)
1227912286
BTF_ID(func, bpf_dynptr_from_xdp)
12287+
BTF_ID(func, bpf_dynptr_from_skb_meta)
1228012288
#else
1228112289
BTF_ID_UNUSED
1228212290
BTF_ID_UNUSED
12291+
BTF_ID_UNUSED
1228312292
#endif
1228412293
BTF_ID(func, bpf_dynptr_slice)
1228512294
BTF_ID(func, bpf_dynptr_slice_rdwr)
@@ -13253,6 +13262,8 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
1325313262
dynptr_arg_type |= DYNPTR_TYPE_SKB;
1325413263
} else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_xdp]) {
1325513264
dynptr_arg_type |= DYNPTR_TYPE_XDP;
13265+
} else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb_meta]) {
13266+
dynptr_arg_type |= DYNPTR_TYPE_SKB_META;
1325613267
} else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_clone] &&
1325713268
(dynptr_arg_type & MEM_UNINIT)) {
1325813269
enum bpf_dynptr_type parent_type = meta->initialized_dynptr.type;

net/core/filter.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11990,6 +11990,16 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
1199011990
return func;
1199111991
}
1199211992

11993+
/**
11994+
* bpf_skb_meta_pointer() - Gets a mutable pointer within the skb metadata area.
11995+
* @skb: socket buffer carrying the metadata
11996+
* @offset: offset into the metadata area, must be <= skb_metadata_len()
11997+
*/
11998+
void *bpf_skb_meta_pointer(struct sk_buff *skb, u32 offset)
11999+
{
12000+
return skb_metadata_end(skb) - skb_metadata_len(skb) + offset;
12001+
}
12002+
1199312003
__bpf_kfunc_start_defs();
1199412004
__bpf_kfunc int bpf_dynptr_from_skb(struct __sk_buff *s, u64 flags,
1199512005
struct bpf_dynptr *ptr__uninit)
@@ -12007,6 +12017,42 @@ __bpf_kfunc int bpf_dynptr_from_skb(struct __sk_buff *s, u64 flags,
1200712017
return 0;
1200812018
}
1200912019

12020+
/**
12021+
* bpf_dynptr_from_skb_meta() - Initialize a dynptr to the skb metadata area.
12022+
* @skb_: socket buffer carrying the metadata
12023+
* @flags: future use, must be zero
12024+
* @ptr__uninit: dynptr to initialize
12025+
*
12026+
* Set up a dynptr for access to the metadata area earlier allocated from the
12027+
* XDP context with bpf_xdp_adjust_meta(). Serves as an alternative to
12028+
* &__sk_buff->data_meta.
12029+
*
12030+
* If passed @skb_ is a clone which shares the data with the original, the
12031+
* dynptr will be read-only. This limitation may be lifted in the future.
12032+
*
12033+
* Return:
12034+
* * %0 - dynptr ready to use
12035+
* * %-EINVAL - invalid flags, dynptr set to null
12036+
*/
12037+
__bpf_kfunc int bpf_dynptr_from_skb_meta(struct __sk_buff *skb_, u64 flags,
12038+
struct bpf_dynptr *ptr__uninit)
12039+
{
12040+
struct bpf_dynptr_kern *ptr = (struct bpf_dynptr_kern *)ptr__uninit;
12041+
struct sk_buff *skb = (struct sk_buff *)skb_;
12042+
12043+
if (flags) {
12044+
bpf_dynptr_set_null(ptr);
12045+
return -EINVAL;
12046+
}
12047+
12048+
bpf_dynptr_init(ptr, skb, BPF_DYNPTR_TYPE_SKB_META, 0, skb_metadata_len(skb));
12049+
12050+
if (skb_cloned(skb))
12051+
bpf_dynptr_set_rdonly(ptr);
12052+
12053+
return 0;
12054+
}
12055+
1201012056
__bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_md *x, u64 flags,
1201112057
struct bpf_dynptr *ptr__uninit)
1201212058
{
@@ -12181,6 +12227,10 @@ BTF_KFUNCS_START(bpf_kfunc_check_set_skb)
1218112227
BTF_ID_FLAGS(func, bpf_dynptr_from_skb, KF_TRUSTED_ARGS)
1218212228
BTF_KFUNCS_END(bpf_kfunc_check_set_skb)
1218312229

12230+
BTF_KFUNCS_START(bpf_kfunc_check_set_skb_meta)
12231+
BTF_ID_FLAGS(func, bpf_dynptr_from_skb_meta, KF_TRUSTED_ARGS)
12232+
BTF_KFUNCS_END(bpf_kfunc_check_set_skb_meta)
12233+
1218412234
BTF_KFUNCS_START(bpf_kfunc_check_set_xdp)
1218512235
BTF_ID_FLAGS(func, bpf_dynptr_from_xdp)
1218612236
BTF_KFUNCS_END(bpf_kfunc_check_set_xdp)
@@ -12202,6 +12252,11 @@ static const struct btf_kfunc_id_set bpf_kfunc_set_skb = {
1220212252
.set = &bpf_kfunc_check_set_skb,
1220312253
};
1220412254

12255+
static const struct btf_kfunc_id_set bpf_kfunc_set_skb_meta = {
12256+
.owner = THIS_MODULE,
12257+
.set = &bpf_kfunc_check_set_skb_meta,
12258+
};
12259+
1220512260
static const struct btf_kfunc_id_set bpf_kfunc_set_xdp = {
1220612261
.owner = THIS_MODULE,
1220712262
.set = &bpf_kfunc_check_set_xdp,
@@ -12237,6 +12292,8 @@ static int __init bpf_kfunc_init(void)
1223712292
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_SEG6LOCAL, &bpf_kfunc_set_skb);
1223812293
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_NETFILTER, &bpf_kfunc_set_skb);
1223912294
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_kfunc_set_skb);
12295+
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &bpf_kfunc_set_skb_meta);
12296+
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT, &bpf_kfunc_set_skb_meta);
1224012297
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_kfunc_set_xdp);
1224112298
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
1224212299
&bpf_kfunc_set_sock_addr);

tools/testing/selftests/bpf/bpf_kfuncs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ extern int bpf_dynptr_from_skb(struct __sk_buff *skb, __u64 flags,
1919
extern int bpf_dynptr_from_xdp(struct xdp_md *xdp, __u64 flags,
2020
struct bpf_dynptr *ptr__uninit) __ksym __weak;
2121

22+
extern int bpf_dynptr_from_skb_meta(struct __sk_buff *skb, __u64 flags,
23+
struct bpf_dynptr *ptr__uninit) __ksym __weak;
24+
2225
/* Description
2326
* Obtain a read-only pointer to the dynptr's data
2427
* Returns

tools/testing/selftests/bpf/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ CONFIG_MPLS_IPTUNNEL=y
6161
CONFIG_MPLS_ROUTING=y
6262
CONFIG_MPTCP=y
6363
CONFIG_NET_ACT_GACT=y
64+
CONFIG_NET_ACT_MIRRED=y
6465
CONFIG_NET_ACT_SKBMOD=y
6566
CONFIG_NET_CLS=y
6667
CONFIG_NET_CLS_ACT=y

tools/testing/selftests/bpf/prog_tests/dynptr.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ static struct {
3232
{"test_ringbuf", SETUP_SYSCALL_SLEEP},
3333
{"test_skb_readonly", SETUP_SKB_PROG},
3434
{"test_dynptr_skb_data", SETUP_SKB_PROG},
35+
{"test_dynptr_skb_meta_data", SETUP_SKB_PROG},
36+
{"test_dynptr_skb_meta_flags", SETUP_SKB_PROG},
3537
{"test_adjust", SETUP_SYSCALL_SLEEP},
3638
{"test_adjust_err", SETUP_SYSCALL_SLEEP},
3739
{"test_zero_size_dynptr", SETUP_SYSCALL_SLEEP},

0 commit comments

Comments
 (0)