Skip to content

Commit 5fc5d8f

Browse files
theihoranakryiko
authored andcommitted
bpf: Add bpf_dynptr_memset() kfunc
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 <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 38d95be commit 5fc5d8f

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

kernel/bpf/helpers.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2907,6 +2907,52 @@ __bpf_kfunc int bpf_dynptr_copy(struct bpf_dynptr *dst_ptr, u32 dst_off,
29072907
return 0;
29082908
}
29092909

2910+
/**
2911+
* bpf_dynptr_memset() - Fill dynptr memory with a constant byte.
2912+
* @p: Destination dynptr - where data will be filled
2913+
* @offset: Offset into the dynptr to start filling from
2914+
* @size: Number of bytes to fill
2915+
* @val: Constant byte to fill the memory with
2916+
*
2917+
* Fills the @size bytes of the memory area pointed to by @p
2918+
* at @offset with the constant byte @val.
2919+
* Returns 0 on success; negative error, otherwise.
2920+
*/
2921+
__bpf_kfunc int bpf_dynptr_memset(struct bpf_dynptr *p, u32 offset, u32 size, u8 val)
2922+
{
2923+
struct bpf_dynptr_kern *ptr = (struct bpf_dynptr_kern *)p;
2924+
u32 chunk_sz, write_off;
2925+
char buf[256];
2926+
void* slice;
2927+
int err;
2928+
2929+
slice = bpf_dynptr_slice_rdwr(p, offset, NULL, size);
2930+
if (likely(slice)) {
2931+
memset(slice, val, size);
2932+
return 0;
2933+
}
2934+
2935+
if (__bpf_dynptr_is_rdonly(ptr))
2936+
return -EINVAL;
2937+
2938+
err = bpf_dynptr_check_off_len(ptr, offset, size);
2939+
if (err)
2940+
return err;
2941+
2942+
/* Non-linear data under the dynptr, write from a local buffer */
2943+
chunk_sz = min_t(u32, sizeof(buf), size);
2944+
memset(buf, val, chunk_sz);
2945+
2946+
for (write_off = 0; write_off < size; write_off += chunk_sz) {
2947+
chunk_sz = min_t(u32, sizeof(buf), size - write_off);
2948+
err = __bpf_dynptr_write(ptr, offset + write_off, buf, chunk_sz, 0);
2949+
if (err)
2950+
return err;
2951+
}
2952+
2953+
return 0;
2954+
}
2955+
29102956
__bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj)
29112957
{
29122958
return obj;
@@ -3735,6 +3781,7 @@ BTF_ID_FLAGS(func, bpf_dynptr_is_rdonly)
37353781
BTF_ID_FLAGS(func, bpf_dynptr_size)
37363782
BTF_ID_FLAGS(func, bpf_dynptr_clone)
37373783
BTF_ID_FLAGS(func, bpf_dynptr_copy)
3784+
BTF_ID_FLAGS(func, bpf_dynptr_memset)
37383785
#ifdef CONFIG_NET
37393786
BTF_ID_FLAGS(func, bpf_modify_return_test_tp)
37403787
#endif

0 commit comments

Comments
 (0)