On Wed, Jul 2, 2025 at 3:42 PM 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> > --- > 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); > + 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; > + } Looking at this hunk standalone (without patch 7) one might get an impression that odd ptr_to_btf_id is allowed that points to non-struct type, but patch 7 sort-of fixes it by handling primitive types first. Still, I think it would be good to add a check here that kern_type_id is a struct kind. > 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; nit: All except one 'else if' in this loop don't do explicit 'continue'. I think the above comment would be enough. > } 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 >