Currently verifier thinks when sk_buff is used as kfunc's argument it is coming as pointer to context (KF_ARG_PTR_TO_CTX) but in kfuncs that are going to be introduced for sk_buff's refcount handling we want it to be interpreted as KF_ARG_PTR_TO_BTF_ID. Make it possible by calling btf_is_projection_of() conditionally. Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@xxxxxxxxx> --- include/linux/btf.h | 4 ++-- kernel/bpf/btf.c | 11 ++++++----- kernel/bpf/verifier.c | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/linux/btf.h b/include/linux/btf.h index ebc0c0c9b944..1307ea17542a 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -585,7 +585,7 @@ struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id); bool btf_is_projection_of(const char *pname, const char *tname); bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf, const struct btf_type *t, enum bpf_prog_type prog_type, - int arg); + int arg, bool check_proj); int get_kern_ctx_btf_id(struct bpf_verifier_log *log, enum bpf_prog_type prog_type); bool btf_types_are_same(const struct btf *btf1, u32 id1, const struct btf *btf2, u32 id2); @@ -661,7 +661,7 @@ static inline struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf static inline bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf, const struct btf_type *t, enum bpf_prog_type prog_type, - int arg) + int arg, bool check_proj) { return false; } diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 69f5752e880b..62bdf6980cfb 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -5909,7 +5909,7 @@ bool btf_is_projection_of(const char *pname, const char *tname) bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf, const struct btf_type *t, enum bpf_prog_type prog_type, - int arg) + int arg, bool check_proj) { const struct btf_type *ctx_type; const char *tname, *ctx_tname; @@ -5969,8 +5969,9 @@ bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf, * int socket_filter_bpf_prog(struct __sk_buff *skb) * { // no fields of skb are ever used } */ - if (btf_is_projection_of(ctx_tname, tname)) - return true; + if (check_proj) + if (btf_is_projection_of(ctx_tname, tname)) + return true; if (strcmp(ctx_tname, tname)) { /* bpf_user_pt_regs_t is a typedef, so resolve it to * underlying struct and check name again @@ -6133,7 +6134,7 @@ static int btf_translate_to_vmlinux(struct bpf_verifier_log *log, enum bpf_prog_type prog_type, int arg) { - if (!btf_is_prog_ctx_type(log, btf, t, prog_type, arg)) + if (!btf_is_prog_ctx_type(log, btf, t, prog_type, arg, true)) return -ENOENT; return find_kern_ctx_type_id(prog_type); } @@ -7739,7 +7740,7 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog) if (!btf_type_is_ptr(t)) goto skip_pointer; - if ((tags & ARG_TAG_CTX) || btf_is_prog_ctx_type(log, btf, t, prog_type, i)) { + if ((tags & ARG_TAG_CTX) || btf_is_prog_ctx_type(log, btf, t, prog_type, i, true)) { if (tags & ~ARG_TAG_CTX) { bpf_log(log, "arg#%d has invalid combination of tags\n", i); return -EINVAL; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e57b7c949860..6492bfa4bc7a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -11997,7 +11997,8 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env, * type to our caller. When a set of conditions hold in the BTF type of * arguments, we resolve it to a known kfunc_ptr_arg_type. */ - if (btf_is_prog_ctx_type(&env->log, meta->btf, t, resolve_prog_type(env->prog), argno)) + if (btf_is_prog_ctx_type(&env->log, meta->btf, t, resolve_prog_type(env->prog), + argno, false)) return KF_ARG_PTR_TO_CTX; if (is_kfunc_arg_nullable(meta->btf, &args[argno]) && register_is_null(reg)) -- 2.43.0