From: Alexei Starovoitov When a kfunc takes a pointer to a struct that has only scalar members, the verifier also accepts memory of the prog. Then resolve_func_arg_type() changes ARG_PTR_TO_BTF_ID to ARG_PTR_TO_MEM. This is correct for a struct of parameters. But struct bpf_cpumask also has only scalar members, and the kernel allocates and frees it. Thus bpf_cpumask_acquire() returns memory of the prog as a referenced object, and bpf_cpumask_release() can free it. The verifier does not change the argument that a kfunc releases. KF_ACQUIRE does not say which argument is the object. Thus do not change any argument of a KF_ACQUIRE kfunc. Then the verifier rejects memory there. No other KF_ACQUIRE kfunc takes memory in an ARG_PTR_TO_BTF_ID argument. Add to kfuncs.rst that a KF_ACQUIRE kfunc must pair a struct of parameters with a __sz argument. The first commit below added the bug. Later the struct had pointers in an rcu_head, so the verifier rejected memory. The second commit removed them. Fixes: 516f4d3397c9 ("bpf: Enable cpumasks to be queried and used as kptrs") Fixes: 8e07bb9ebcd9 ("bpf: Convert bpf_cpumask to bpf_mem_cache_free_rcu.") Signed-off-by: Alexei Starovoitov --- Documentation/bpf/kfuncs.rst | 7 +++++++ kernel/bpf/verifier.c | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst index 73578a4c3b1f..329d1510b02a 100644 --- a/Documentation/bpf/kfuncs.rst +++ b/Documentation/bpf/kfuncs.rst @@ -407,6 +407,13 @@ referenced kptr (by invoking bpf_kptr_xchg). If not, the verifier fails the loading of the BPF program until no lingering references remain in all possible explored states of the program. +A pointer to a struct in the arguments of a KF_ACQUIRE kfunc accepts only an +object of that type. The same applies to the argument that a KF_RELEASE kfunc +releases. For other arguments a kfunc also accepts memory of the program, if the +struct has only scalar members. struct __sk_buff and struct xdp_md never accept +memory. A KF_ACQUIRE kfunc which wants such memory has to pair the pointer with +a __sz argument. + 2.5.2 KF_RET_NULL flag ---------------------- diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 53272f50226a..cc2ba4dc9da3 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -13574,7 +13574,12 @@ static int resolve_func_arg_type(struct bpf_verifier_env *env, if (base_type(*arg_type) != ARG_PTR_TO_BTF_ID) return 0; + /* + * A kfunc that releases an object, or that takes a reference to one, + * needs the object itself: memory of the program cannot stand in for it. + */ if (!is_kfunc(meta) || arg_type_is_release(*arg_type) || + is_kfunc_acquire(meta) || base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)]) return 0; -- 2.55.0