Re: [PATCH bpf-next v3 1/2] bpf: add bpf_dynptr_memset() kfunc

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

 



On Mon, Jun 30, 2025 at 2:21 PM Ihor Solodrai <isolodrai@xxxxxxxx> wrote:
>
> Currently there is no straightforward way to fill dynptr memory with a
> value (most commonly zero). One can do it with bpf_dynptr_write(), but
> a temporary buffer is necessary for that.
>
> Implement bpf_dynptr_memset() - an analogue of memset() from libc.
>
> Signed-off-by: Ihor Solodrai <isolodrai@xxxxxxxx>
> ---
>  kernel/bpf/helpers.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
>
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index f48fa3fe8dec..415b50415598 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -2907,6 +2907,52 @@ __bpf_kfunc int bpf_dynptr_copy(struct bpf_dynptr *dst_ptr, u32 dst_off,
>         return 0;
>  }
>
> +/**
> + * bpf_dynptr_memset() - Fill dynptr memory with a constant byte.
> + * @ptr: Destination dynptr - where data will be filled
> + * @offset: Offset into the dynptr to start filling from
> + * @size: Number of bytes to fill
> + * @val: Constant byte to fill the memory with
> + *
> + * Fills the size bytes of the memory area pointed to by ptr

nit: looking at other doc comments, you should use @size when
referring to parameter (same for @ptr, though nit-within-nit: we seem
to be using "p" for similar functions)

> + * at offset with the constant byte val.
> + * Returns 0 on success; negative error, otherwise.
> + */
> + __bpf_kfunc int bpf_dynptr_memset(struct bpf_dynptr *ptr, u32 offset, u32 size, u8 val)
> + {
> +       struct bpf_dynptr_kern *p = (struct bpf_dynptr_kern *)ptr;
> +       u32 chunk_sz, write_off;
> +       char buf[256];
> +       void* slice;
> +       int err;
> +
> +       if (__bpf_dynptr_is_rdonly(p))
> +               return -EINVAL;
> +
> +       err = bpf_dynptr_check_off_len(p, offset, size);
> +       if (err)
> +               return err;
> +
> +       slice = bpf_dynptr_slice_rdwr(ptr, offset, NULL, size);
> +       if (likely(slice)) {
> +               memset(slice, val, size);
> +               return 0;
> +       }

I think what (I believe, Mykyta) was saying is that by doing

slice = bpf_dynptr_slice_rdwr(...);
if (likely(slice)) {
    memset(...);
    return 0;
}

if (__bpf_dynptr_is_rdonly(p))
    return -EINVAL;

err = bpf_dynptr_check_off_len(...);
if (err)
    return err;


we have the fastest possible expected happy case, and we'll do all the
sanity checking if happy path fails either due to non-contiguity of
memory or due to invalid size/offset/read-write permission

pw-bot: cr



> +
> +       /* Non-linear data under the dynptr, write from a local buffer */
> +       chunk_sz = min_t(u32, sizeof(buf), size);
> +       memset(buf, val, chunk_sz);
> +
> +       for (write_off = 0; write_off < size; write_off += chunk_sz) {
> +               chunk_sz = min_t(u32, sizeof(buf), size - write_off);
> +               err = __bpf_dynptr_write(p, offset + write_off, buf, chunk_sz, 0);
> +               if (err)
> +                       return err;
> +       }
> +
> +       return 0;
> +}
> +
>  __bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj)
>  {
>         return obj;
> @@ -3735,6 +3781,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_memset)
>  #ifdef CONFIG_NET
>  BTF_ID_FLAGS(func, bpf_modify_return_test_tp)
>  #endif
> --
> 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