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 | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index b71e428ad936..b8a7dbc971b4 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -2906,6 +2906,53 @@ __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 + * @ptr_off: 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 + * at offset ptr_off with the constant byte val. + * Returns 0 on success; negative error, otherwise. + */ + __bpf_kfunc int bpf_dynptr_memset(struct bpf_dynptr *ptr, u32 ptr_off, u32 size, u8 val) + { + struct bpf_dynptr_kern *p = (struct bpf_dynptr_kern *)ptr; + char buf[256]; + u32 chunk_sz; + void* slice; + u32 offset; + int err; + + if (__bpf_dynptr_is_rdonly(p)) + return -EINVAL; + + err = bpf_dynptr_check_off_len(p, ptr_off, size); + if (err) + return err; + + slice = bpf_dynptr_slice_rdwr(ptr, ptr_off, NULL, size); + if (likely(slice)) { + memset(slice, val, size); + return 0; + } + + /* 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 (offset = ptr_off; offset < ptr_off + size; offset += chunk_sz) { + chunk_sz = min_t(u32, sizeof(buf), size - offset); + err = __bpf_dynptr_write(p, offset, buf, chunk_sz, 0); + if (err) + return err; + } + + return 0; +} + __bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj) { return obj; @@ -3364,6 +3411,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