diff options
| author | Josef Bacik <josef@toxicpanda.com> | 2026-10-17 23:09:44 +0000 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-10-18 00:36:43 +0000 |
| commit | b7f97db88948aa511bcd989978f181e1367e0e8b (patch) | |
| tree | 007087b61f35bf44a9f2889097bd644b6fde0c3d /kernel/bpf | |
| parent | 589998616e0f9190ba6f6644a19532c5b2ba66d0 (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.c | 8 |
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 & |
