Re: [RFC PATCH bpf-next/net v1 06/13] bpf: Introduce bpf_dynptr_from_mem_slice

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

 



On Mon, Apr 14, 2025 at 9:14 AM Kumar Kartikeya Dwivedi
<memxor@xxxxxxxxx> wrote:
>
> Add a new bpf_dynptr_from_mem_slice kfunc to create a dynptr from a
> PTR_TO_BTF_ID exposing a variable-length slice of memory, represented by
> the new bpf_mem_slice type. This slice is read-only, for a read-write
> slice we can expose a distinct type in the future.
>
> We rely on the previous commits ensuring source objects underpinning
> dynptr memory are tracked correctly for invalidation to ensure when a
> PTR_TO_BTF_ID holding a memory slice goes away, it's corresponding
> dynptrs get invalidated.
>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx>
> ---
>  include/linux/bpf.h   |  5 +++++
>  kernel/bpf/helpers.c  | 32 ++++++++++++++++++++++++++++++++
>  kernel/bpf/verifier.c |  6 +++++-
>  3 files changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 3f0cc89c0622..9feaa9bbf0a4 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1344,6 +1344,11 @@ enum bpf_dynptr_type {
>         BPF_DYNPTR_TYPE_XDP,
>  };
>
> +struct bpf_mem_slice {
> +       void *ptr;
> +       size_t len;

for better future extensibility and to avoid big-endian issues, let's have

u32 len;
u32 __reserved; /* or flags */

?

> +};
> +
>  int bpf_dynptr_check_size(u32 size);
>  u32 __bpf_dynptr_size(const struct bpf_dynptr_kern *ptr);
>  const void *__bpf_dynptr_data(const struct bpf_dynptr_kern *ptr, u32 len);
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index e3a2662f4e33..95e9c9df6062 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -2826,6 +2826,37 @@ __bpf_kfunc int bpf_dynptr_copy(struct bpf_dynptr *dst_ptr, u32 dst_off,
>         return 0;
>  }
>
> +/**
> + * XXX
> + */
> +__bpf_kfunc int bpf_dynptr_from_mem_slice(struct bpf_mem_slice *mem_slice, u64 flags, struct bpf_dynptr *dptr__uninit)
> +{
> +       struct bpf_dynptr_kern *dptr = (struct bpf_dynptr_kern *)dptr__uninit;
> +       int err;
> +
> +       if (!mem_slice)
> +               return -EINVAL;

you have to initialize dynptr regardless of errors, just like
bpf_dynptr_from_mem() does, so

err = -EINVAL;
goto error;


> +
> +       err = bpf_dynptr_check_size(mem_slice->len);
> +       if (err)
> +               goto error;
> +
> +       /* flags is currently unsupported */
> +       if (flags) {
> +               err = -EINVAL;
> +               goto error;
> +       }
> +
> +       bpf_dynptr_init(dptr, mem_slice->ptr, BPF_DYNPTR_TYPE_LOCAL, 0, mem_slice->len);
> +       bpf_dynptr_set_rdonly(dptr);
> +
> +       return 0;
> +
> +error:
> +       bpf_dynptr_set_null(dptr);
> +       return err;
> +}
> +
>  __bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj)
>  {
>         return obj;
> @@ -3275,6 +3306,7 @@ BTF_ID_FLAGS(func, bpf_dynptr_is_rdonly)
>  BTF_ID_FLAGS(func, bpf_dynptr_size)
>  BTF_ID_FLAGS(func, bpf_dynptr_clone)
>  BTF_ID_FLAGS(func, bpf_dynptr_copy)
> +BTF_ID_FLAGS(func, bpf_dynptr_from_mem_slice, KF_TRUSTED_ARGS)
>  #ifdef CONFIG_NET
>  BTF_ID_FLAGS(func, bpf_modify_return_test_tp)
>  #endif
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 7e09c4592038..26aa70cd5734 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -12125,6 +12125,7 @@ enum special_kfunc_type {
>         KF_bpf_res_spin_unlock,
>         KF_bpf_res_spin_lock_irqsave,
>         KF_bpf_res_spin_unlock_irqrestore,
> +       KF_bpf_dynptr_from_mem_slice,
>  };
>
>  BTF_SET_START(special_kfunc_set)
> @@ -12218,6 +12219,7 @@ BTF_ID(func, bpf_res_spin_lock)
>  BTF_ID(func, bpf_res_spin_unlock)
>  BTF_ID(func, bpf_res_spin_lock_irqsave)
>  BTF_ID(func, bpf_res_spin_unlock_irqrestore)
> +BTF_ID(func, bpf_dynptr_from_mem_slice)
>
>  static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta)
>  {
> @@ -13139,7 +13141,9 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
>                                 }
>                         }
>
> -                       if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
> +                       if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_mem_slice]) {
> +                               dynptr_arg_type |= DYNPTR_TYPE_LOCAL;
> +                       } else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
>                                 dynptr_arg_type |= DYNPTR_TYPE_SKB;
>                         } else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_xdp]) {
>                                 dynptr_arg_type |= DYNPTR_TYPE_XDP;
> --
> 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