Skip to content

Commit 89d912e

Browse files
jsitnickiMartin KaFai Lau
authored andcommitted
bpf: Add dynptr type for skb metadata
Add a dynptr type, similar to skb dynptr, but for the skb metadata access. The dynptr provides an alternative to __sk_buff->data_meta for accessing the custom metadata area allocated using the bpf_xdp_adjust_meta() helper. More importantly, it abstracts away the fact where the storage for the custom metadata lives, which opens up the way to persist the metadata by relocating it as the skb travels through the network stack layers. Writes to skb metadata invalidate any existing skb payload and metadata slices. While this is more restrictive that needed at the moment, it leaves the door open to reallocating the metadata on writes, and should be only a minor inconvenience to the users. Only the program types which can access __sk_buff->data_meta today are allowed to create a dynptr for skb metadata at the moment. We need to modify the network stack to persist the metadata across layers before opening up access to other BPF hooks. Once more BPF hooks gain access to skb_meta dynptr, we will also need to add a read-only variant of the helper similar to bpf_dynptr_from_skb_rdonly. skb_meta dynptr ops are stubbed out and implemented by subsequent changes. Signed-off-by: Jakub Sitnicki <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Reviewed-by: Jesse Brandeburg <[email protected]> Link: https://patch.msgid.link/20250814-skb-metadata-thru-dynptr-v7-1-8a39e636e0fb@cloudflare.com
1 parent 8f5ae30 commit 89d912e

File tree

5 files changed

+69
-3
lines changed

5 files changed

+69
-3
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);

kernel/bpf/helpers.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,8 @@ 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+
return -EOPNOTSUPP; /* not implemented */
17831785
default:
17841786
WARN_ONCE(true, "bpf_dynptr_read: unknown dynptr type %d\n", type);
17851787
return -EFAULT;
@@ -1836,6 +1838,8 @@ int __bpf_dynptr_write(const struct bpf_dynptr_kern *dst, u32 offset, void *src,
18361838
if (flags)
18371839
return -EINVAL;
18381840
return __bpf_xdp_store_bytes(dst->data, dst->offset + offset, src, len);
1841+
case BPF_DYNPTR_TYPE_SKB_META:
1842+
return -EOPNOTSUPP; /* not implemented */
18391843
default:
18401844
WARN_ONCE(true, "bpf_dynptr_write: unknown dynptr type %d\n", type);
18411845
return -EFAULT;
@@ -1882,6 +1886,7 @@ BPF_CALL_3(bpf_dynptr_data, const struct bpf_dynptr_kern *, ptr, u32, offset, u3
18821886
return (unsigned long)(ptr->data + ptr->offset + offset);
18831887
case BPF_DYNPTR_TYPE_SKB:
18841888
case BPF_DYNPTR_TYPE_XDP:
1889+
case BPF_DYNPTR_TYPE_SKB_META:
18851890
/* skb and xdp dynptrs should use bpf_dynptr_slice / bpf_dynptr_slice_rdwr */
18861891
return 0;
18871892
default:
@@ -2710,6 +2715,8 @@ __bpf_kfunc void *bpf_dynptr_slice(const struct bpf_dynptr *p, u32 offset,
27102715
bpf_xdp_copy_buf(ptr->data, ptr->offset + offset, buffer__opt, len, false);
27112716
return buffer__opt;
27122717
}
2718+
case BPF_DYNPTR_TYPE_SKB_META:
2719+
return NULL; /* not implemented */
27132720
default:
27142721
WARN_ONCE(true, "unknown dynptr type %d\n", type);
27152722
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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12007,6 +12007,36 @@ __bpf_kfunc int bpf_dynptr_from_skb(struct __sk_buff *s, u64 flags,
1200712007
return 0;
1200812008
}
1200912009

12010+
/**
12011+
* bpf_dynptr_from_skb_meta() - Initialize a dynptr to the skb metadata area.
12012+
* @skb_: socket buffer carrying the metadata
12013+
* @flags: future use, must be zero
12014+
* @ptr__uninit: dynptr to initialize
12015+
*
12016+
* Set up a dynptr for access to the metadata area earlier allocated from the
12017+
* XDP context with bpf_xdp_adjust_meta(). Serves as an alternative to
12018+
* &__sk_buff->data_meta.
12019+
*
12020+
* Return:
12021+
* * %0 - dynptr ready to use
12022+
* * %-EINVAL - invalid flags, dynptr set to null
12023+
*/
12024+
__bpf_kfunc int bpf_dynptr_from_skb_meta(struct __sk_buff *skb_, u64 flags,
12025+
struct bpf_dynptr *ptr__uninit)
12026+
{
12027+
struct bpf_dynptr_kern *ptr = (struct bpf_dynptr_kern *)ptr__uninit;
12028+
struct sk_buff *skb = (struct sk_buff *)skb_;
12029+
12030+
if (flags) {
12031+
bpf_dynptr_set_null(ptr);
12032+
return -EINVAL;
12033+
}
12034+
12035+
bpf_dynptr_init(ptr, skb, BPF_DYNPTR_TYPE_SKB_META, 0, skb_metadata_len(skb));
12036+
12037+
return 0;
12038+
}
12039+
1201012040
__bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_md *x, u64 flags,
1201112041
struct bpf_dynptr *ptr__uninit)
1201212042
{
@@ -12181,6 +12211,10 @@ BTF_KFUNCS_START(bpf_kfunc_check_set_skb)
1218112211
BTF_ID_FLAGS(func, bpf_dynptr_from_skb, KF_TRUSTED_ARGS)
1218212212
BTF_KFUNCS_END(bpf_kfunc_check_set_skb)
1218312213

12214+
BTF_KFUNCS_START(bpf_kfunc_check_set_skb_meta)
12215+
BTF_ID_FLAGS(func, bpf_dynptr_from_skb_meta, KF_TRUSTED_ARGS)
12216+
BTF_KFUNCS_END(bpf_kfunc_check_set_skb_meta)
12217+
1218412218
BTF_KFUNCS_START(bpf_kfunc_check_set_xdp)
1218512219
BTF_ID_FLAGS(func, bpf_dynptr_from_xdp)
1218612220
BTF_KFUNCS_END(bpf_kfunc_check_set_xdp)
@@ -12202,6 +12236,11 @@ static const struct btf_kfunc_id_set bpf_kfunc_set_skb = {
1220212236
.set = &bpf_kfunc_check_set_skb,
1220312237
};
1220412238

12239+
static const struct btf_kfunc_id_set bpf_kfunc_set_skb_meta = {
12240+
.owner = THIS_MODULE,
12241+
.set = &bpf_kfunc_check_set_skb_meta,
12242+
};
12243+
1220512244
static const struct btf_kfunc_id_set bpf_kfunc_set_xdp = {
1220612245
.owner = THIS_MODULE,
1220712246
.set = &bpf_kfunc_check_set_xdp,
@@ -12237,6 +12276,8 @@ static int __init bpf_kfunc_init(void)
1223712276
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_SEG6LOCAL, &bpf_kfunc_set_skb);
1223812277
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_NETFILTER, &bpf_kfunc_set_skb);
1223912278
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_kfunc_set_skb);
12279+
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &bpf_kfunc_set_skb_meta);
12280+
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT, &bpf_kfunc_set_skb_meta);
1224012281
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_kfunc_set_xdp);
1224112282
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
1224212283
&bpf_kfunc_set_sock_addr);

0 commit comments

Comments
 (0)