summaryrefslogtreecommitdiff
path: root/kernel/bpf
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2026-10-17 23:09:44 +0000
committerAlexei Starovoitov <ast@kernel.org>2026-10-18 00:36:43 +0000
commitb7f97db88948aa511bcd989978f181e1367e0e8b (patch)
tree007087b61f35bf44a9f2889097bd644b6fde0c3d /kernel/bpf
parent589998616e0f9190ba6f6644a19532c5b2ba66d0 (diff)
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 <josef@toxicpanda.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261017230950.802052-11-alexei.starovoitov@gmail.com
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/verifier.c8
1 files 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 &