* [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
@ 2025-06-18 22:33 Ihor Solodrai
2025-06-18 22:33 ` [PATCH bpf-next 2/2] selftests/bpf: add test cases for bpf_dynptr_memset() Ihor Solodrai
2025-06-18 23:44 ` [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc Mykyta Yatsenko
0 siblings, 2 replies; 14+ messages in thread
From: Ihor Solodrai @ 2025-06-18 22:33 UTC (permalink / raw)
To: andrii; +Cc: bpf, ast, daniel, eddyz87, mykolal, kernel-team
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@meta.com>
---
kernel/bpf/helpers.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index b71e428ad936..dfd04628a522 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -2906,6 +2906,33 @@ __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
+ * @val: Constant byte to fill the memory with
+ * @n: Number of bytes to fill
+ *
+ * Fills the first n bytes of the memory area pointed to by ptr
+ * with the constant byte val.
+ * Returns 0 on success; negative error, otherwise.
+ */
+ __bpf_kfunc int bpf_dynptr_memset(struct bpf_dynptr *ptr, u8 val, u32 n)
+ {
+ struct bpf_dynptr_kern *p = (struct bpf_dynptr_kern *)ptr;
+ int err;
+
+ if (__bpf_dynptr_is_rdonly(p))
+ return -EINVAL;
+
+ err = bpf_dynptr_check_off_len(p, 0, n);
+ if (err)
+ return err;
+
+ memset(p->data + p->offset, val, n);
+
+ return 0;
+}
+
__bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj)
{
return obj;
@@ -3364,6 +3391,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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH bpf-next 2/2] selftests/bpf: add test cases for bpf_dynptr_memset()
2025-06-18 22:33 [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc Ihor Solodrai
@ 2025-06-18 22:33 ` Ihor Solodrai
2025-06-18 23:44 ` [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc Mykyta Yatsenko
1 sibling, 0 replies; 14+ messages in thread
From: Ihor Solodrai @ 2025-06-18 22:33 UTC (permalink / raw)
To: andrii; +Cc: bpf, ast, daniel, eddyz87, mykolal, kernel-team
Add tests to verify the behavior of bpf_dynptr_memset():
* normal memset 0
* memset in dynptr that was adjusted
* error: size overflow
* error: readonly dynptr
Signed-off-by: Ihor Solodrai <isolodrai@meta.com>
---
.../testing/selftests/bpf/prog_tests/dynptr.c | 4 ++
.../selftests/bpf/progs/dynptr_success.c | 66 +++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/dynptr.c b/tools/testing/selftests/bpf/prog_tests/dynptr.c
index 62e7ec775f24..423e95755aa0 100644
--- a/tools/testing/selftests/bpf/prog_tests/dynptr.c
+++ b/tools/testing/selftests/bpf/prog_tests/dynptr.c
@@ -21,6 +21,10 @@ static struct {
{"test_dynptr_data", SETUP_SYSCALL_SLEEP},
{"test_dynptr_copy", SETUP_SYSCALL_SLEEP},
{"test_dynptr_copy_xdp", SETUP_XDP_PROG},
+ {"test_dynptr_memset_zero", SETUP_SYSCALL_SLEEP},
+ {"test_dynptr_memset_zero_offset", SETUP_SYSCALL_SLEEP},
+ {"test_dynptr_memset_overflow", SETUP_SYSCALL_SLEEP},
+ {"test_dynptr_memset_readonly", SETUP_SKB_PROG},
{"test_ringbuf", SETUP_SYSCALL_SLEEP},
{"test_skb_readonly", SETUP_SKB_PROG},
{"test_dynptr_skb_data", SETUP_SKB_PROG},
diff --git a/tools/testing/selftests/bpf/progs/dynptr_success.c b/tools/testing/selftests/bpf/progs/dynptr_success.c
index a0391f9da2d4..204e02816947 100644
--- a/tools/testing/selftests/bpf/progs/dynptr_success.c
+++ b/tools/testing/selftests/bpf/progs/dynptr_success.c
@@ -681,6 +681,72 @@ int test_dynptr_copy_xdp(struct xdp_md *xdp)
return XDP_DROP;
}
+char memset_zero_data[] = "data to be zeroed";
+
+SEC("?tp/syscalls/sys_enter_nanosleep")
+int test_dynptr_memset_zero(void *ctx)
+{
+ __u32 data_sz = sizeof(memset_zero_data);
+ char zeroes[32] = {'\0'};
+ struct bpf_dynptr ptr;
+
+ err = bpf_dynptr_from_mem(memset_zero_data, data_sz, 0, &ptr);
+ err = err ?: bpf_dynptr_memset(&ptr, 0, data_sz);
+ err = err ?: bpf_memcmp(zeroes, memset_zero_data, data_sz);
+
+ return 0;
+}
+
+char memset_zero_offset_data[] = "data to be zeroed partially";
+
+SEC("?tp/syscalls/sys_enter_nanosleep")
+int test_dynptr_memset_zero_offset(void *ctx)
+{
+ char expected[] = "data\0\0\0\0be zeroed partially";
+ __u32 data_sz = sizeof(memset_zero_offset_data);
+ struct bpf_dynptr ptr;
+
+ err = bpf_dynptr_from_mem(memset_zero_offset_data, data_sz, 0, &ptr);
+ err = err ?: bpf_dynptr_adjust(&ptr, 4, 8);
+ err = err ?: bpf_dynptr_memset(&ptr, 0, bpf_dynptr_size(&ptr));
+ err = err ?: bpf_memcmp(expected, memset_zero_offset_data, data_sz);
+
+ return 0;
+}
+
+char memset_overflow_data[] = "memset overflow data";
+
+SEC("?tp/syscalls/sys_enter_nanosleep")
+int test_dynptr_memset_overflow(void *ctx)
+{
+ __u32 data_sz = sizeof(memset_overflow_data);
+ struct bpf_dynptr ptr;
+ int ret;
+
+ err = bpf_dynptr_from_mem(memset_overflow_data, data_sz, 0, &ptr);
+ ret = bpf_dynptr_memset(&ptr, 0, data_sz + 1);
+ if (ret != -E2BIG)
+ err = 1;
+
+ return 0;
+}
+
+SEC("?cgroup_skb/egress")
+int test_dynptr_memset_readonly(struct __sk_buff *skb)
+{
+ struct bpf_dynptr ptr;
+ int ret;
+
+ err = bpf_dynptr_from_skb(skb, 0, &ptr);
+
+ /* cgroup skbs are read only, memset should fail */
+ ret = bpf_dynptr_memset(&ptr, 0, bpf_dynptr_size(&ptr));
+ if (ret != -EINVAL)
+ err = 1;
+
+ return 0;
+}
+
void *user_ptr;
/* Contains the copy of the data pointed by user_ptr.
* Size 384 to make it not fit into a single kernel chunk when copying
--
2.47.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-18 22:33 [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc Ihor Solodrai
2025-06-18 22:33 ` [PATCH bpf-next 2/2] selftests/bpf: add test cases for bpf_dynptr_memset() Ihor Solodrai
@ 2025-06-18 23:44 ` Mykyta Yatsenko
2025-06-19 17:09 ` Ihor Solodrai
1 sibling, 1 reply; 14+ messages in thread
From: Mykyta Yatsenko @ 2025-06-18 23:44 UTC (permalink / raw)
To: ihor.solodrai, andrii; +Cc: bpf, ast, daniel, eddyz87, mykolal, kernel-team
On 6/18/25 23:33, Ihor Solodrai 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@meta.com>
> ---
> kernel/bpf/helpers.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index b71e428ad936..dfd04628a522 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -2906,6 +2906,33 @@ __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
> + * @val: Constant byte to fill the memory with
> + * @n: Number of bytes to fill
> + *
> + * Fills the first n bytes of the memory area pointed to by ptr
> + * with the constant byte val.
> + * Returns 0 on success; negative error, otherwise.
> + */
> + __bpf_kfunc int bpf_dynptr_memset(struct bpf_dynptr *ptr, u8 val, u32 n)
> + {
> + struct bpf_dynptr_kern *p = (struct bpf_dynptr_kern *)ptr;
> + int err;
> +
> + if (__bpf_dynptr_is_rdonly(p))
> + return -EINVAL;
> +
> + err = bpf_dynptr_check_off_len(p, 0, n);
> + if (err)
> + return err;
> +
> + memset(p->data + p->offset, val, n);
Do we need to handle non-contiguous buffers, similarly to
bpf_dynptr_write (BPF_DYNPTR_TYPE_XDP case)?
> +
> + return 0;
> +}
> +
> __bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj)
> {
> return obj;
> @@ -3364,6 +3391,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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-18 23:44 ` [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc Mykyta Yatsenko
@ 2025-06-19 17:09 ` Ihor Solodrai
2025-06-19 17:19 ` Eduard Zingerman
0 siblings, 1 reply; 14+ messages in thread
From: Ihor Solodrai @ 2025-06-19 17:09 UTC (permalink / raw)
To: Mykyta Yatsenko, andrii; +Cc: bpf, ast, daniel, eddyz87, mykolal, kernel-team
On 6/18/25 4:44 PM, Mykyta Yatsenko wrote:
> On 6/18/25 23:33, Ihor Solodrai 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@meta.com>
>> ---
>> kernel/bpf/helpers.c | 28 ++++++++++++++++++++++++++++
>> 1 file changed, 28 insertions(+)
>>
>> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
>> index b71e428ad936..dfd04628a522 100644
>> --- a/kernel/bpf/helpers.c
>> +++ b/kernel/bpf/helpers.c
>> @@ -2906,6 +2906,33 @@ __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
>> + * @val: Constant byte to fill the memory with
>> + * @n: Number of bytes to fill
>> + *
>> + * Fills the first n bytes of the memory area pointed to by ptr
>> + * with the constant byte val.
>> + * Returns 0 on success; negative error, otherwise.
>> + */
>> + __bpf_kfunc int bpf_dynptr_memset(struct bpf_dynptr *ptr, u8 val,
>> u32 n)
>> + {
>> + struct bpf_dynptr_kern *p = (struct bpf_dynptr_kern *)ptr;
>> + int err;
>> +
>> + if (__bpf_dynptr_is_rdonly(p))
>> + return -EINVAL;
>> +
>> + err = bpf_dynptr_check_off_len(p, 0, n);
>> + if (err)
>> + return err;
>> +
>> + memset(p->data + p->offset, val, n);
> Do we need to handle non-contiguous buffers, similarly to
> bpf_dynptr_write (BPF_DYNPTR_TYPE_XDP case)?
It appears so, yes. I am a little lost on how exactly to do it though.
Looking at bpf_xdp_store_bytes [1]:
BPF_CALL_4(bpf_xdp_store_bytes, struct xdp_buff *, xdp, u32, offset,
void *, buf, u32, len)
{
void *ptr;
ptr = bpf_xdp_pointer(xdp, offset, len);
if (IS_ERR(ptr))
return PTR_ERR(ptr);
if (!ptr)
bpf_xdp_copy_buf(xdp, offset, buf, len, true);
else
memcpy(ptr, buf, len);
return 0;
}
...
int __bpf_xdp_store_bytes(struct xdp_buff *xdp, u32 offset, void
*buf, u32 len)
{
return ____bpf_xdp_store_bytes(xdp, offset, buf, len);
}
It looks like I'd need to implement similar logic for memset.
But then, does memset even make sense for xdp/skb buffers?
Maybe -ENOTSUPP is more appropriate?
I'd appreciate any hints.
[1]
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/tree/net/core/filter.c#n4084
>> +
>> + return 0;
>> +}
>> +
>> __bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj)
>> {
>> return obj;
>> @@ -3364,6 +3391,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
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 17:09 ` Ihor Solodrai
@ 2025-06-19 17:19 ` Eduard Zingerman
2025-06-19 17:55 ` Ihor Solodrai
2025-06-20 15:09 ` Mykyta Yatsenko
0 siblings, 2 replies; 14+ messages in thread
From: Eduard Zingerman @ 2025-06-19 17:19 UTC (permalink / raw)
To: Ihor Solodrai, Mykyta Yatsenko, andrii
Cc: bpf, ast, daniel, mykolal, kernel-team
On Thu, 2025-06-19 at 10:09 -0700, Ihor Solodrai wrote:
[...]
> But then, does memset even make sense for xdp/skb buffers?
Why not?
> Maybe -ENOTSUPP is more appropriate?
>
> I'd appreciate any hints.
I think Mykyta has kernel/trace/bpf_trace.c:__bpf_dynptr_copy_str() in mind.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 17:19 ` Eduard Zingerman
@ 2025-06-19 17:55 ` Ihor Solodrai
2025-06-19 17:57 ` Eduard Zingerman
2025-06-20 15:09 ` Mykyta Yatsenko
1 sibling, 1 reply; 14+ messages in thread
From: Ihor Solodrai @ 2025-06-19 17:55 UTC (permalink / raw)
To: Eduard Zingerman, Mykyta Yatsenko, andrii
Cc: bpf, ast, daniel, mykolal, kernel-team
On 6/19/25 10:19 AM, Eduard Zingerman wrote:
> On Thu, 2025-06-19 at 10:09 -0700, Ihor Solodrai wrote:
>
> [...]
>
>> But then, does memset even make sense for xdp/skb buffers?
>
> Why not?
I was thinking that in a BPF program you'd usually be reading xdp/skb
and not writing to it, especially not via memset. But never mind, I am
likely wrong.
>
>> Maybe -ENOTSUPP is more appropriate?
>>
>> I'd appreciate any hints.
>
> I think Mykyta has kernel/trace/bpf_trace.c:__bpf_dynptr_copy_str() in mind.
Thanks for the pointer. So it looks like memset can use
bpf_dynptr_slice_rdwr() to handle xdp/skb cases. Something like:
void *ptr = bpf_dynptr_slice_rdwr(&dynptr, 0, buffer, sizeof(buffer));
if (!ptr)
return -EINVAL;
memset(ptr, val, n);
if (ptr == buffer)
bpf_dynptr_write(&dynptr, 0, buffer, sizeof(buffer), 0);
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 17:55 ` Ihor Solodrai
@ 2025-06-19 17:57 ` Eduard Zingerman
2025-06-19 18:04 ` Ihor Solodrai
0 siblings, 1 reply; 14+ messages in thread
From: Eduard Zingerman @ 2025-06-19 17:57 UTC (permalink / raw)
To: Ihor Solodrai, Mykyta Yatsenko, andrii
Cc: bpf, ast, daniel, mykolal, kernel-team
On Thu, 2025-06-19 at 10:55 -0700, Ihor Solodrai wrote:
[...]
> > I think Mykyta has kernel/trace/bpf_trace.c:__bpf_dynptr_copy_str() in mind.
>
> Thanks for the pointer. So it looks like memset can use
> bpf_dynptr_slice_rdwr() to handle xdp/skb cases. Something like:
>
> void *ptr = bpf_dynptr_slice_rdwr(&dynptr, 0, buffer, sizeof(buffer));
> if (!ptr)
> return -EINVAL;
>
> memset(ptr, val, n);
>
> if (ptr == buffer)
> bpf_dynptr_write(&dynptr, 0, buffer, sizeof(buffer), 0);
>
>
I think so. In a loop.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 17:57 ` Eduard Zingerman
@ 2025-06-19 18:04 ` Ihor Solodrai
2025-06-19 18:13 ` Eduard Zingerman
0 siblings, 1 reply; 14+ messages in thread
From: Ihor Solodrai @ 2025-06-19 18:04 UTC (permalink / raw)
To: Eduard Zingerman, Mykyta Yatsenko, andrii
Cc: bpf, ast, daniel, mykolal, kernel-team
On 6/19/25 10:57 AM, Eduard Zingerman wrote:
> On Thu, 2025-06-19 at 10:55 -0700, Ihor Solodrai wrote:
>
> [...]
>
>>> I think Mykyta has kernel/trace/bpf_trace.c:__bpf_dynptr_copy_str() in mind.
>>
>> Thanks for the pointer. So it looks like memset can use
>> bpf_dynptr_slice_rdwr() to handle xdp/skb cases. Something like:
>>
>> void *ptr = bpf_dynptr_slice_rdwr(&dynptr, 0, buffer, sizeof(buffer));
>> if (!ptr)
>> return -EINVAL;
>>
>> memset(ptr, val, n);
>>
>> if (ptr == buffer)
>> bpf_dynptr_write(&dynptr, 0, buffer, sizeof(buffer), 0);
>>
>>
>
> I think so. In a loop.
But allocating and copying buffers for memset...
It should be possible to walk through fragments like
net/core/filter.c:bpf_xdp_copy_buf does.
Any reasons it's a bad idea?
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 18:04 ` Ihor Solodrai
@ 2025-06-19 18:13 ` Eduard Zingerman
2025-06-19 18:17 ` Eduard Zingerman
0 siblings, 1 reply; 14+ messages in thread
From: Eduard Zingerman @ 2025-06-19 18:13 UTC (permalink / raw)
To: Ihor Solodrai, Mykyta Yatsenko, andrii
Cc: bpf, ast, daniel, mykolal, kernel-team
On Thu, 2025-06-19 at 11:04 -0700, Ihor Solodrai wrote:
[...]
> It should be possible to walk through fragments like
> net/core/filter.c:bpf_xdp_copy_buf does.
>
> Any reasons it's a bad idea?
>
You can do that as well.
Also, what's the plan if you'd like to memset only a fragment of the
memory pointed-to by dynptr?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 18:13 ` Eduard Zingerman
@ 2025-06-19 18:17 ` Eduard Zingerman
2025-06-23 21:38 ` Andrii Nakryiko
0 siblings, 1 reply; 14+ messages in thread
From: Eduard Zingerman @ 2025-06-19 18:17 UTC (permalink / raw)
To: Ihor Solodrai, Mykyta Yatsenko, andrii
Cc: bpf, ast, daniel, mykolal, kernel-team
On Thu, 2025-06-19 at 11:13 -0700, Eduard Zingerman wrote:
[...]
> Also, what's the plan if you'd like to memset only a fragment of the
> memory pointed-to by dynptr?
Oh, I see, there is bpf_dynptr_adjust(), sorry for the noise.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 17:19 ` Eduard Zingerman
2025-06-19 17:55 ` Ihor Solodrai
@ 2025-06-20 15:09 ` Mykyta Yatsenko
1 sibling, 0 replies; 14+ messages in thread
From: Mykyta Yatsenko @ 2025-06-20 15:09 UTC (permalink / raw)
To: Eduard Zingerman, Ihor Solodrai, andrii
Cc: bpf, ast, daniel, mykolal, kernel-team
On 6/19/25 18:19, Eduard Zingerman wrote:
> On Thu, 2025-06-19 at 10:09 -0700, Ihor Solodrai wrote:
>
> [...]
>
>> But then, does memset even make sense for xdp/skb buffers?
> Why not?
>
>> Maybe -ENOTSUPP is more appropriate?
>>
>> I'd appreciate any hints.
> I think Mykyta has kernel/trace/bpf_trace.c:__bpf_dynptr_copy_str() in mind.
>
Right, similarly to `__bpf_dynptr_copy` from bpf_trace.c: fast path if
destination has enough contiguous memory,
just call memset.
Slow path - use temp buffer, that you can memset once and then
__bpf_dynptr_write it in a loop. __bpf_dynptr_write
handles the trickiness of the non-contiguous buffers.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-19 18:17 ` Eduard Zingerman
@ 2025-06-23 21:38 ` Andrii Nakryiko
2025-06-23 21:45 ` Eduard Zingerman
0 siblings, 1 reply; 14+ messages in thread
From: Andrii Nakryiko @ 2025-06-23 21:38 UTC (permalink / raw)
To: Eduard Zingerman
Cc: Ihor Solodrai, Mykyta Yatsenko, andrii, bpf, ast, daniel, mykolal,
kernel-team
On Thu, Jun 19, 2025 at 11:17 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
>
> On Thu, 2025-06-19 at 11:13 -0700, Eduard Zingerman wrote:
>
> [...]
>
> > Also, what's the plan if you'd like to memset only a fragment of the
> > memory pointed-to by dynptr?
>
> Oh, I see, there is bpf_dynptr_adjust(), sorry for the noise.
>
Even though we do have bpf_dynptr_adjust() for maximum generality and
flexibility, for most dynptr-based APIs we try to pass also additional
offset into dynptr to avoid unnecessary overhead. So it's not a bad
idea to add this to bpf_memset(), IMO.
bpf_memset(struct bpf_dynptr *dptr, u32 off, u8 val, u32 n) ?
a bit unfortunate that we have 3 integers that you need to be careful
to not swap accidentally, but even with just val and n you'd have to
be careful. For other APIs we normally have offset to follow dynptr
pointer, so hopefully this arrangement won't that surprising.
Thoughts?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-23 21:38 ` Andrii Nakryiko
@ 2025-06-23 21:45 ` Eduard Zingerman
2025-06-23 22:12 ` Andrii Nakryiko
0 siblings, 1 reply; 14+ messages in thread
From: Eduard Zingerman @ 2025-06-23 21:45 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Ihor Solodrai, Mykyta Yatsenko, andrii, bpf, ast, daniel, mykolal,
kernel-team
On Mon, 2025-06-23 at 14:38 -0700, Andrii Nakryiko wrote:
> On Thu, Jun 19, 2025 at 11:17 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
> >
> > On Thu, 2025-06-19 at 11:13 -0700, Eduard Zingerman wrote:
> >
> > [...]
> >
> > > Also, what's the plan if you'd like to memset only a fragment of the
> > > memory pointed-to by dynptr?
> >
> > Oh, I see, there is bpf_dynptr_adjust(), sorry for the noise.
> >
>
> Even though we do have bpf_dynptr_adjust() for maximum generality and
> flexibility, for most dynptr-based APIs we try to pass also additional
> offset into dynptr to avoid unnecessary overhead. So it's not a bad
> idea to add this to bpf_memset(), IMO.
>
> bpf_memset(struct bpf_dynptr *dptr, u32 off, u8 val, u32 n) ?
>
> a bit unfortunate that we have 3 integers that you need to be careful
> to not swap accidentally, but even with just val and n you'd have to
> be careful. For other APIs we normally have offset to follow dynptr
> pointer, so hopefully this arrangement won't that surprising.
>
> Thoughts?
Unfortunate indeed.
The off and n being separated looks weird, tbh.
For dynptr funcs we actually have "dptr, off, size" everywhere, maybe
do the same here?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc
2025-06-23 21:45 ` Eduard Zingerman
@ 2025-06-23 22:12 ` Andrii Nakryiko
0 siblings, 0 replies; 14+ messages in thread
From: Andrii Nakryiko @ 2025-06-23 22:12 UTC (permalink / raw)
To: Eduard Zingerman
Cc: Ihor Solodrai, Mykyta Yatsenko, andrii, bpf, ast, daniel, mykolal,
kernel-team
On Mon, Jun 23, 2025 at 2:45 PM Eduard Zingerman <eddyz87@gmail.com> wrote:
>
> On Mon, 2025-06-23 at 14:38 -0700, Andrii Nakryiko wrote:
> > On Thu, Jun 19, 2025 at 11:17 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
> > >
> > > On Thu, 2025-06-19 at 11:13 -0700, Eduard Zingerman wrote:
> > >
> > > [...]
> > >
> > > > Also, what's the plan if you'd like to memset only a fragment of the
> > > > memory pointed-to by dynptr?
> > >
> > > Oh, I see, there is bpf_dynptr_adjust(), sorry for the noise.
> > >
> >
> > Even though we do have bpf_dynptr_adjust() for maximum generality and
> > flexibility, for most dynptr-based APIs we try to pass also additional
> > offset into dynptr to avoid unnecessary overhead. So it's not a bad
> > idea to add this to bpf_memset(), IMO.
> >
> > bpf_memset(struct bpf_dynptr *dptr, u32 off, u8 val, u32 n) ?
> >
> > a bit unfortunate that we have 3 integers that you need to be careful
> > to not swap accidentally, but even with just val and n you'd have to
> > be careful. For other APIs we normally have offset to follow dynptr
> > pointer, so hopefully this arrangement won't that surprising.
> >
> > Thoughts?
>
> Unfortunate indeed.
> The off and n being separated looks weird, tbh.
> For dynptr funcs we actually have "dptr, off, size" everywhere, maybe
> do the same here?
yep, fine by me. I never liked libc's memset() order anyways :)
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-06-23 22:12 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-18 22:33 [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc Ihor Solodrai
2025-06-18 22:33 ` [PATCH bpf-next 2/2] selftests/bpf: add test cases for bpf_dynptr_memset() Ihor Solodrai
2025-06-18 23:44 ` [PATCH bpf-next 1/2] bpf: add bpf_dynptr_memset() kfunc Mykyta Yatsenko
2025-06-19 17:09 ` Ihor Solodrai
2025-06-19 17:19 ` Eduard Zingerman
2025-06-19 17:55 ` Ihor Solodrai
2025-06-19 17:57 ` Eduard Zingerman
2025-06-19 18:04 ` Ihor Solodrai
2025-06-19 18:13 ` Eduard Zingerman
2025-06-19 18:17 ` Eduard Zingerman
2025-06-23 21:38 ` Andrii Nakryiko
2025-06-23 21:45 ` Eduard Zingerman
2025-06-23 22:12 ` Andrii Nakryiko
2025-06-20 15:09 ` Mykyta Yatsenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).