Re: [PATCH bpf-next v1 4/8] bpf: attribute __arg_untrusted for global function parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
>





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux