On Thu, 3 Jul 2025 at 00:42, Eduard Zingerman <eddyz87@xxxxxxxxx> wrote: > > Add support for PTR_TO_BTF_ID | PTR_UNTRUSTED global function > parameters. Anything is allowed to pass to such parameters, as these > are read-only and probe read instructions would protect against > invalid memory access. > > Suggested-by: Alexei Starovoitov <alexei.starovoitov@xxxxxxxxx> > Signed-off-by: Eduard Zingerman <eddyz87@xxxxxxxxx> > --- Some comments below, but logic looks correct. Acked-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> > kernel/bpf/btf.c | 29 ++++++++++++++++++++++++----- > kernel/bpf/verifier.c | 7 +++++++ > 2 files changed, 31 insertions(+), 5 deletions(-) > > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c > index b3c8a95d38fb..28cb0a2a5402 100644 > --- a/kernel/bpf/btf.c > +++ b/kernel/bpf/btf.c > @@ -7646,11 +7646,12 @@ static int btf_get_ptr_to_btf_id(struct bpf_verifier_log *log, int arg_idx, > } > > enum btf_arg_tag { > - ARG_TAG_CTX = BIT_ULL(0), > - ARG_TAG_NONNULL = BIT_ULL(1), > - ARG_TAG_TRUSTED = BIT_ULL(2), > - ARG_TAG_NULLABLE = BIT_ULL(3), > - ARG_TAG_ARENA = BIT_ULL(4), > + ARG_TAG_CTX = BIT_ULL(0), > + ARG_TAG_NONNULL = BIT_ULL(1), > + ARG_TAG_TRUSTED = BIT_ULL(2), > + ARG_TAG_UNTRUSTED = BIT_ULL(3), > + ARG_TAG_NULLABLE = BIT_ULL(4), > + ARG_TAG_ARENA = BIT_ULL(5), > }; > > /* Process BTF of a function to produce high-level expectation of function > @@ -7758,6 +7759,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog) > tags |= ARG_TAG_CTX; > } else if (strcmp(tag, "trusted") == 0) { > tags |= ARG_TAG_TRUSTED; > + } else if (strcmp(tag, "untrusted") == 0) { > + tags |= ARG_TAG_UNTRUSTED; > } else if (strcmp(tag, "nonnull") == 0) { > tags |= ARG_TAG_NONNULL; > } else if (strcmp(tag, "nullable") == 0) { > @@ -7818,6 +7821,22 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog) > sub->args[i].btf_id = kern_type_id; > continue; > } > + if (tags & ARG_TAG_UNTRUSTED) { > + int kern_type_id; > + > + if (tags & ~ARG_TAG_UNTRUSTED) { > + bpf_log(log, "arg#%d untrusted cannot be combined with any other tags\n", i); > + return -EINVAL; > + } > + > + kern_type_id = btf_get_ptr_to_btf_id(log, i, btf, t); So while this makes sense for trusted, I think for untrusted, we should allow types in program BTF as well. This is one of the things I think lacks in bpf_rdonly_cast as well, to be able to cast to types in program BTF. Say you want to reinterpret some kernel memory into your own type and access it using a struct in the program which is a different type. I think it makes sense to make this work. When I needed it in the past I just added a local new bpf_rdonly_cast_local variant that uses prog->btf for btf_id and moved on. Supporting bpf_core_cast for both prog BTF and kernel BTF types is not trivial because we cannot disambiguate local vs kernel types. IIRC module BTF types probably don't work either but that's a different story. > + if (kern_type_id < 0) > + return kern_type_id; > + > + sub->args[i].arg_type = ARG_PTR_TO_BTF_ID | PTR_UNTRUSTED; > + sub->args[i].btf_id = kern_type_id; > + continue; > + } > if (tags & ARG_TAG_ARENA) { > if (tags & ~ARG_TAG_ARENA) { > bpf_log(log, "arg#%d arena cannot be combined with any other tags\n", i); > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index cd2344e50db8..dfb5a2f8e58f 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -10436,6 +10436,13 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog, > bpf_log(log, "R%d is not a scalar\n", regno); > return -EINVAL; > } > + } else if (arg->arg_type & PTR_UNTRUSTED) { > + /* > + * Anything is allowed for untrusted arguments, as these are > + * read-only and probe read instructions would protect against > + * invalid memory access. > + */ > + continue; > } else if (arg->arg_type == ARG_PTR_TO_CTX) { > ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE); > if (ret < 0) > -- > 2.47.1 > >