From b7f97db88948aa511bcd989978f181e1367e0e8b Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Sat, 17 Oct 2026 23:09:44 +0000 Subject: [PATCH] bpf: Don't take a dynptr argument for a local dynptr A global function is verified on its own. A dynptr which it gets as an argument is assumed to be of type BPF_DYNPTR_TYPE_LOCAL, but the callers may pass one of any type, that of an skb for example. The type decides whether a write through the dynptr invalidates packet pointers, and whether a slice of it is invalidated together with them. Inside of the function neither happens. It can take a packet pointer from its context argument, or a slice from the dynptr, write through the dynptr and go on using the pointer, although the write may have reallocated the head of the skb. Assume the type of an skb dynptr instead. Nothing becomes forbidden for the dynptr itself, and a clone inherits the caution. The dynptr which the callback of bpf_user_ringbuf_drain() gets is known to be local, and stays so. Fixes: a64bfe618665 ("bpf: add support for passing dynptr pointer to global subprog") Signed-off-by: Josef Bacik Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20261017230950.802052-11-alexei.starovoitov@gmail.com --- kernel/bpf/verifier.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 597302cf7086..338376492647 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -21589,8 +21589,12 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog, reg->type = SCALAR_VALUE; mark_reg_unknown(env, regs, i); } else if (arg->arg_type == ARG_PTR_TO_DYNPTR) { - /* assume unspecial LOCAL dynptr type */ - __mark_dynptr_reg(reg, BPF_DYNPTR_TYPE_LOCAL, true, ++env->id_gen, 0); + /* + * The callers may hand in a dynptr of any type. + * Take it for that of an skb, so that a write + * through it and its slices are treated with care. + */ + __mark_dynptr_reg(reg, BPF_DYNPTR_TYPE_SKB, true, ++env->id_gen, 0); } else if (base_type(arg->arg_type) == ARG_PTR_TO_MEM) { reg->type = PTR_TO_MEM; reg->type |= arg->arg_type &