summaryrefslogtreecommitdiff
path: root/kernel/bpf
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2026-10-17 23:09:46 +0000
committerAlexei Starovoitov <ast@kernel.org>2026-10-18 00:36:43 +0000
commitbb72c2866831b571249929714d118ccea1ecb747 (patch)
tree343088a4112afb1bac5aee537bd8dd392582b7e6 /kernel/bpf
parentaa486cff4964d0cd566954cec2b01b484641f7d5 (diff)
bpf: Unclone the skb for kfuncs that write through a dynptr
bpf_dynptr_copy(), bpf_dynptr_memset() and the kfuncs that read user or kernel memory into a dynptr ask bpf_dynptr_slice_rdwr() for a slice and write to it. For the linear part of an skb that is a pointer into its head. bpf_dynptr_slice_rdwr() counts on the verifier to have uncloned the skb, see bpf_unclone_prologue(). The verifier does so if the program itself calls bpf_dynptr_slice_rdwr() or writes to the packet. A program that only uses these kfuncs gets no prologue, and changes the data of all the clones of the skb. A packet socket, whose clone is taken before tc ingress runs, sees what bpf_dynptr_memset() has written there. Treat a call that may write to an skb like a direct write. Fixes: daec295a7094 ("bpf/helpers: Introduce bpf_dynptr_copy kfunc") Fixes: a498ee7576de ("bpf: Implement dynptr copy kfuncs") Fixes: 5fc5d8fded57 ("bpf: Add bpf_dynptr_memset() kfunc") Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261017230950.802052-13-alexei.starovoitov@gmail.com
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/verifier.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 338376492647..3bc1df7aabe2 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -15683,6 +15683,14 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
bpf_is_kfunc_pkt_changing(&meta))
clear_all_pkt_pointers(env);
+ /*
+ * These kfuncs write to the head of the skb in place if what they write
+ * to is linear. Like a direct write that takes bpf_unclone_prologue().
+ */
+ if (is_kfunc_dynptr_write(&meta) &&
+ dynptr_write_changes_pkt_data(meta.dynptr_write_type))
+ may_access_direct_pkt_data(env, NULL, BPF_WRITE);
+
proto_slots = kfunc_abi_slots(&desc->func_model);
if (proto_slots > MAX_BPF_FUNC_REG_ARGS) {
struct bpf_func_state *caller = cur_func(env);