bpf_dynptr_slice_rdwr(9)
π bpf_dynptr_slice_rdwr β like, the Kernel API Manual (section 9) page you actually want to read π«Ά
okay bestie, sit down, grab a strawberry π, because this one is LOWKEY important. We're talking about bpf_dynptr_slice_rdwr β it's a kernel API function, it lives in the 9 section of the manual, and it's the one that hands you a writable pointer into your dynptr data. Yes, writable. As in, you can actually touch it. Main character energy fr fr β¨
π NAME π
bpf_dynptr_slice_rdwr β obtain a writable pointer to the dynptr data. That's it, that's the whole vibe. π
β¨ SYNOPSIS β¨
__bpf_kfunc void * bpf_dynptr_slice_rdwr (const struct bpf_dynptr *p ,
u64 offset , void *buffer__nullable , u64 buffer__szk );
Look at that signature. Four args. Not one of them is optional to understand. Let's go π
πΈ ARGUMENTS πΈ
pβ the dynptr whose data slice you're trying to retrieve. Your little data baddie. π¦offsetβ offset into the dynptr. i.e. where inside it you're pointing. πbuffer__nullableβ a user-provided buffer that the contents get copied into. It may beNULL. Yes, nullable means nullable, she's allowed to be absent. πbuffer__szkβ size (in bytes) of the buffer, if present. This is also, importantly, the length of the requested slice. And heads up: this must be a constant. Not a variable. Not vibes. A constant. π₯
π DESCRIPTION π
So for non-skb and non-xdp type dynptrs, there is literally no difference between bpf_dynptr_slice and bpf_dynptr_data. Same function, different font, as far as those are concerned. Not kidding. π
If buffer__nullable is NULL, the call will fail if buffer_opt was needed. (Yes, buffer_opt β that's what the page says, don't @ me.) π
Now the juicy part: the returned pointer is writable, and it may point to either:
- directly the dynptr data at the requested offset, or
- the buffer, if it's unable to obtain a direct data pointer to (example: the requested slice is to the paged area of an skb packet).
And in case number two β the one where the returned pointer is to the buffer β you are responsible for persisting writes through calling bpf_dynptr_write. Like, that's on you bestie. Nobody's doing it for you. π«Ά
It usually looks something like this pattern:
struct eth_hdr *eth = bpf_dynptr_slice_rdwr(dynptr, 0, buffer, sizeof(buffer)); if (!eth) return TC_ACT_SHOT;
// mutate eth header //
if (eth == buffer) bpf_dynptr_write(ptr, 0, buffer, sizeof(buffer), 0);
β οΈ Please note that, as in the example above, the user must check that the returned pointer is not null before using it. Like, actually check. Touch the null pointer and it's over for you ππ΄
Also please note β and this one's iconic β in the case of skb and xdp dynptrs, bpf_dynptr_slice_rdwr does not change the underlying packet data pointers, so a call to bpf_dynptr_slice_rdwr will not invalidate any ctx->data/data_end pointers in the bpf program. Your pointers stay valid. She's considerate like that. π
π RETURN π
NULLif the call failed (eg invalid dynptr) π- otherwise: a pointer to a data slice β which can be either a direct pointer to the data, or a pointer to the user provided buffer with its contents containing the data, if it was unable to obtain a direct pointer. Two possible outfits, same function. π
π SEE ALSO π
Kernel file ./kernel/bpf/helpers.c and, like, the whole friend group:
bpf_obj_new(9)bpf_percpu_obj_new(9)bpf_obj_drop(9)bpf_percpu_obj_drop(9)bpf_refcount_acquire(9)bpf_list_push_front(9)bpf_list_push_back(9)bpf_rbtree_add(9)bpf_task_acquire(9)bpf_task_release(9)bpf_cgroup_acquire(9)bpf_cgroup_release(9)bpf_cgroup_ancestor(9)bpf_cgroup_from_id(9)bpf_task_under_cgroup(9)bpf_task_get_cgroup1(9)bpf_task_from_pid(9)bpf_task_from_vpid(9)bpf_dynptr_slice(9)bpf_dynptr_copy(9)bpf_dynptr_memset(9)bpf_iter_bits_new(9)bpf_iter_bits_next(9)bpf_iter_bits_destroy(9)bpf_copy_from_user_str(9)bpf_copy_from_user_task_str(9)bpf_strcmp(9)bpf_strcasecmp(9)bpf_strnchr(9)bpf_strchr(9)bpf_strchrnul(9)bpf_strrchr(9)bpf_strnlen(9)bpf_strlen(9)bpf_strspn(9)bpf_strcspn(9)bpf_strstr(9)bpf_strcasestr(9)bpf_strnstr(9)bpf_strncasestr(9)bpf_lookup_user_key(9)bpf_lookup_system_key(9)bpf_key_put(9)bpf_verify_pkcs7_signature(9)bpf_task_work_schedule_signal(9)bpf_task_work_schedule_resume(9)bpf_timer_cancel_async(9)
okay that's the whole page, you ate that ππ this gem is from ./kernel/bpf, dated October 2026, and yes it's bpf_dynptr_slice_rdwr(9) β go forth and mutate responsibly, bestie π§ββοΈβ¨
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms