From: Josef Bacik <josef@toxicpanda.com>
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.
Report such a dynptr as that of an skb to whoever asks for the type of the
argument of a call. The type in the register stays as it is, nothing
becomes forbidden for the dynptr itself. A clone inherits the caution.
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>
---
kernel/bpf/verifier.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e002728abd04..03b19829f27a 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8416,6 +8416,7 @@ static int process_dynptr_func(struct bpf_verifier_env *env, struct bpf_reg_stat
argno_t argno, int insn_idx, enum bpf_arg_type arg_type,
struct bpf_call_arg_meta *meta)
{
+ bool is_arg = reg->type == CONST_PTR_TO_DYNPTR;
int spi, err = 0;
/* MEM_UNINIT - Points to memory that is an appropriate candidate for@@ -8502,7 +8503,12 @@ static int process_dynptr_func(struct bpf_verifier_env *env, struct bpf_reg_stat
reg = &bpf_stack_slot(state, spi)->spilled_ptr;
}
- meta->dynptr.type = reg->dynptr.type;
+ /*
+ * The callers of a global function 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.
+ */
+ meta->dynptr.type = is_arg ? BPF_DYNPTR_TYPE_SKB : reg->dynptr.type;
meta->dynptr.id = reg->id;
meta->dynptr.parent_id = reg->parent_id;
}
--
2.55.0