netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] xsk: respect the offsets when copying frags
@ 2025-04-23 10:10 Bui Quang Minh
  2025-04-23 14:41 ` Stanislav Fomichev
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Bui Quang Minh @ 2025-04-23 10:10 UTC (permalink / raw)
  To: netdev
  Cc: Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Eric Dumazet, Paolo Abeni, Simon Horman, Maciej Fijalkowski,
	Alexander Lobakin, bpf, linux-kernel, Bui Quang Minh

Add the missing offsets when copying frags in xdp_copy_frags_from_zc().

Fixes: 560d958c6c68 ("xsk: add generic XSk &xdp_buff -> skb conversion")
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
---
 net/core/xdp.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/core/xdp.c b/net/core/xdp.c
index f86eedad586a..a723dc301f94 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -697,7 +697,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
 	nr_frags = xinfo->nr_frags;
 
 	for (u32 i = 0; i < nr_frags; i++) {
-		u32 len = skb_frag_size(&xinfo->frags[i]);
+		const skb_frag_t *frag = &xinfo->frags[i];
+		u32 len = skb_frag_size(frag);
 		u32 offset, truesize = len;
 		netmem_ref netmem;
 
@@ -707,8 +708,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
 			return false;
 		}
 
-		memcpy(__netmem_address(netmem),
-		       __netmem_address(xinfo->frags[i].netmem),
+		memcpy(__netmem_address(netmem) + offset,
+		       __netmem_address(frag->netmem) + skb_frag_off(frag),
 		       LARGEST_ALIGN(len));
 		__skb_fill_netmem_desc_noacc(sinfo, i, netmem, offset, len);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-23 10:10 [PATCH net] xsk: respect the offsets when copying frags Bui Quang Minh
@ 2025-04-23 14:41 ` Stanislav Fomichev
  2025-04-23 14:58   ` Bui Quang Minh
  2025-04-24 14:02 ` Alexander Lobakin
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Stanislav Fomichev @ 2025-04-23 14:41 UTC (permalink / raw)
  To: Bui Quang Minh
  Cc: netdev, Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Eric Dumazet, Paolo Abeni, Simon Horman, Maciej Fijalkowski,
	Alexander Lobakin, bpf, linux-kernel

On 04/23, Bui Quang Minh wrote:
> Add the missing offsets when copying frags in xdp_copy_frags_from_zc().

Can you please share more about how you've hit this problem?
I don't see the caller of this function (xdp_build_skb_from_zc)
being used at all.

Alexander, do you have plans to use it? Or should we remove it for now?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-23 14:41 ` Stanislav Fomichev
@ 2025-04-23 14:58   ` Bui Quang Minh
  2025-04-23 18:01     ` Maciej Fijalkowski
  0 siblings, 1 reply; 9+ messages in thread
From: Bui Quang Minh @ 2025-04-23 14:58 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: netdev, Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Eric Dumazet, Paolo Abeni, Simon Horman, Maciej Fijalkowski,
	Alexander Lobakin, bpf, linux-kernel

On 4/23/25 21:41, Stanislav Fomichev wrote:
> On 04/23, Bui Quang Minh wrote:
>> Add the missing offsets when copying frags in xdp_copy_frags_from_zc().
> Can you please share more about how you've hit this problem?
> I don't see the caller of this function (xdp_build_skb_from_zc)
> being used at all.
>
> Alexander, do you have plans to use it? Or should we remove it for now?
Hi,

I've been playing around to add support for zerocopy XDP socket with 
multi buffer mergeable buffer in virtio-net (this TODO: 
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/drivers/net/virtio_net.c#n1312). 
In that case, I'll have a XDP buff with frags. When we have XDP_PASS 
return, I need to convert the XDP buff with frags to skb with frags, so 
I think the helper is quite helpful. I used it and got packet dropped 
due to checksum error. Debugging the problem, I've found out this issue 
which makes the skb's frag data incorrect.

Thanks,
Quang Minh.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-23 14:58   ` Bui Quang Minh
@ 2025-04-23 18:01     ` Maciej Fijalkowski
  0 siblings, 0 replies; 9+ messages in thread
From: Maciej Fijalkowski @ 2025-04-23 18:01 UTC (permalink / raw)
  To: Bui Quang Minh
  Cc: Stanislav Fomichev, netdev, Alexei Starovoitov, Daniel Borkmann,
	David S. Miller, Jakub Kicinski, Jesper Dangaard Brouer,
	John Fastabend, Eric Dumazet, Paolo Abeni, Simon Horman,
	Alexander Lobakin, bpf, linux-kernel

On Wed, Apr 23, 2025 at 09:58:16PM +0700, Bui Quang Minh wrote:
> On 4/23/25 21:41, Stanislav Fomichev wrote:
> > On 04/23, Bui Quang Minh wrote:
> > > Add the missing offsets when copying frags in xdp_copy_frags_from_zc().
> > Can you please share more about how you've hit this problem?
> > I don't see the caller of this function (xdp_build_skb_from_zc)
> > being used at all.
> > 
> > Alexander, do you have plans to use it? Or should we remove it for now?

libeth xdp support uses this:
https://lore.kernel.org/netdev/20250415172825.3731091-15-aleksander.lobakin@intel.com/

> Hi,
> 
> I've been playing around to add support for zerocopy XDP socket with multi
> buffer mergeable buffer in virtio-net (this TODO: https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/drivers/net/virtio_net.c#n1312).
> In that case, I'll have a XDP buff with frags. When we have XDP_PASS return,
> I need to convert the XDP buff with frags to skb with frags, so I think the
> helper is quite helpful. I used it and got packet dropped due to checksum
> error. Debugging the problem, I've found out this issue which makes the
> skb's frag data incorrect.

Nice! I'll take a look at patch content tomorrow and probably ack it.

> 
> Thanks,
> Quang Minh.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-23 10:10 [PATCH net] xsk: respect the offsets when copying frags Bui Quang Minh
  2025-04-23 14:41 ` Stanislav Fomichev
@ 2025-04-24 14:02 ` Alexander Lobakin
  2025-04-24 14:45   ` Bui Quang Minh
  2025-04-25  0:29 ` Jakub Kicinski
  2025-04-25 15:46 ` Bui Quang Minh
  3 siblings, 1 reply; 9+ messages in thread
From: Alexander Lobakin @ 2025-04-24 14:02 UTC (permalink / raw)
  To: Bui Quang Minh
  Cc: netdev, Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Eric Dumazet, Paolo Abeni, Simon Horman, Maciej Fijalkowski, bpf,
	linux-kernel

From: Bui Quang Minh <minhquangbui99@gmail.com>
Date: Wed, 23 Apr 2025 17:10:47 +0700

> Add the missing offsets when copying frags in xdp_copy_frags_from_zc().
> 
> Fixes: 560d958c6c68 ("xsk: add generic XSk &xdp_buff -> skb conversion")
> Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
> ---
>  net/core/xdp.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/net/core/xdp.c b/net/core/xdp.c
> index f86eedad586a..a723dc301f94 100644
> --- a/net/core/xdp.c
> +++ b/net/core/xdp.c
> @@ -697,7 +697,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
>  	nr_frags = xinfo->nr_frags;
>  
>  	for (u32 i = 0; i < nr_frags; i++) {
> -		u32 len = skb_frag_size(&xinfo->frags[i]);
> +		const skb_frag_t *frag = &xinfo->frags[i];
> +		u32 len = skb_frag_size(frag);
>  		u32 offset, truesize = len;
>  		netmem_ref netmem;
>  
> @@ -707,8 +708,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
>  			return false;
>  		}
>  
> -		memcpy(__netmem_address(netmem),
> -		       __netmem_address(xinfo->frags[i].netmem),
> +		memcpy(__netmem_address(netmem) + offset,
> +		       __netmem_address(frag->netmem) + skb_frag_off(frag),
>  		       LARGEST_ALIGN(len));
>  		__skb_fill_netmem_desc_noacc(sinfo, i, netmem, offset, len);

Incorrect fix.

page_pool_dev_alloc_netmem() allocates a buffer of skb_frag_size() len,
but then you pass offset when copying, which may lead to access beyond
the end of the buffer.

I know that my code here is incorrect as well, but the idea was to
allocate only skb_frag_size() and copy the actual payload without any
offset to the new buffer. So, you need to pass the offset only to the
second argument of memcpy() and then pass 0 as @offset to
__skb_fill_netmem_desc_noacc().

Thanks,
Olek

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-24 14:02 ` Alexander Lobakin
@ 2025-04-24 14:45   ` Bui Quang Minh
  0 siblings, 0 replies; 9+ messages in thread
From: Bui Quang Minh @ 2025-04-24 14:45 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: netdev, Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Eric Dumazet, Paolo Abeni, Simon Horman, Maciej Fijalkowski, bpf,
	linux-kernel

On 4/24/25 21:02, Alexander Lobakin wrote:
> From: Bui Quang Minh <minhquangbui99@gmail.com>
> Date: Wed, 23 Apr 2025 17:10:47 +0700
>
>> Add the missing offsets when copying frags in xdp_copy_frags_from_zc().
>>
>> Fixes: 560d958c6c68 ("xsk: add generic XSk &xdp_buff -> skb conversion")
>> Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
>> ---
>>   net/core/xdp.c | 7 ++++---
>>   1 file changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/net/core/xdp.c b/net/core/xdp.c
>> index f86eedad586a..a723dc301f94 100644
>> --- a/net/core/xdp.c
>> +++ b/net/core/xdp.c
>> @@ -697,7 +697,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
>>   	nr_frags = xinfo->nr_frags;
>>   
>>   	for (u32 i = 0; i < nr_frags; i++) {
>> -		u32 len = skb_frag_size(&xinfo->frags[i]);
>> +		const skb_frag_t *frag = &xinfo->frags[i];
>> +		u32 len = skb_frag_size(frag);
>>   		u32 offset, truesize = len;
>>   		netmem_ref netmem;
>>   
>> @@ -707,8 +708,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
>>   			return false;
>>   		}
>>   
>> -		memcpy(__netmem_address(netmem),
>> -		       __netmem_address(xinfo->frags[i].netmem),
>> +		memcpy(__netmem_address(netmem) + offset,
>> +		       __netmem_address(frag->netmem) + skb_frag_off(frag),
>>   		       LARGEST_ALIGN(len));
>>   		__skb_fill_netmem_desc_noacc(sinfo, i, netmem, offset, len);
> Incorrect fix.
>
> page_pool_dev_alloc_netmem() allocates a buffer of skb_frag_size() len,
> but then you pass offset when copying, which may lead to access beyond
> the end of the buffer.
>
> I know that my code here is incorrect as well, but the idea was to
> allocate only skb_frag_size() and copy the actual payload without any
> offset to the new buffer. So, you need to pass the offset only to the
> second argument of memcpy() and then pass 0 as @offset to
> __skb_fill_netmem_desc_noacc().

I'm not quite familiar with the page_pool API so I might be wrong. 
AFAICS, the netmem_ref is just a wrapper around struct page now. 
page_pool_dev_alloc_netmem(pp, &offset, &truesize) returns the allocated 
page for our request but we must use the returned offset to access our 
allocated space. The start of page may be currently used by other user.

That's my understanding when looking at this code path

page_pool_dev_alloc_netmem
-> page_pool_alloc_netmem
     -> page_pool_alloc_frag_netmem <- specifically this function

Thanks,
Quang Minh.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-23 10:10 [PATCH net] xsk: respect the offsets when copying frags Bui Quang Minh
  2025-04-23 14:41 ` Stanislav Fomichev
  2025-04-24 14:02 ` Alexander Lobakin
@ 2025-04-25  0:29 ` Jakub Kicinski
  2025-04-25 15:46 ` Bui Quang Minh
  3 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2025-04-25  0:29 UTC (permalink / raw)
  To: Bui Quang Minh
  Cc: netdev, Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jesper Dangaard Brouer, John Fastabend, Eric Dumazet, Paolo Abeni,
	Simon Horman, Maciej Fijalkowski, Alexander Lobakin, bpf,
	linux-kernel

On Wed, 23 Apr 2025 17:10:47 +0700 Bui Quang Minh wrote:
> Add the missing offsets when copying frags in xdp_copy_frags_from_zc().
> 
> Fixes: 560d958c6c68 ("xsk: add generic XSk &xdp_buff -> skb conversion")
> Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>

I think the fix is right but I dislike the use of netmem here :(
Could we switch back to page_pool_dev_alloc() ?
Allocating a netmem to immediately call __netmem_address() is strange.
At least to me. Because netmem is supposed to be potentially unreadable.
And using normal page allocation will avoid the confusion and bug we're
dealing with now.

As Stanislav pointed out this function is not used anywhere today,
so let's target the rewrite to net-next and explain in the commit 
message where the bug comes from and why it doesn't need to be
backported (and drop the Fixes tag)?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-23 10:10 [PATCH net] xsk: respect the offsets when copying frags Bui Quang Minh
                   ` (2 preceding siblings ...)
  2025-04-25  0:29 ` Jakub Kicinski
@ 2025-04-25 15:46 ` Bui Quang Minh
  2025-04-26  0:23   ` Jakub Kicinski
  3 siblings, 1 reply; 9+ messages in thread
From: Bui Quang Minh @ 2025-04-25 15:46 UTC (permalink / raw)
  To: netdev
  Cc: Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Eric Dumazet, Paolo Abeni, Simon Horman, Maciej Fijalkowski,
	Alexander Lobakin, bpf, linux-kernel

On 4/23/25 17:10, Bui Quang Minh wrote:
> Add the missing offsets when copying frags in xdp_copy_frags_from_zc().
>
> Fixes: 560d958c6c68 ("xsk: add generic XSk &xdp_buff -> skb conversion")
> Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
> ---
>   net/core/xdp.c | 7 ++++---
>   1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/net/core/xdp.c b/net/core/xdp.c
> index f86eedad586a..a723dc301f94 100644
> --- a/net/core/xdp.c
> +++ b/net/core/xdp.c
> @@ -697,7 +697,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
>   	nr_frags = xinfo->nr_frags;
>   
>   	for (u32 i = 0; i < nr_frags; i++) {
> -		u32 len = skb_frag_size(&xinfo->frags[i]);
> +		const skb_frag_t *frag = &xinfo->frags[i];
> +		u32 len = skb_frag_size(frag);
>   		u32 offset, truesize = len;
>   		netmem_ref netmem;
>   
> @@ -707,8 +708,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
>   			return false;
>   		}
>   
> -		memcpy(__netmem_address(netmem),
> -		       __netmem_address(xinfo->frags[i].netmem),
> +		memcpy(__netmem_address(netmem) + offset,
> +		       __netmem_address(frag->netmem) + skb_frag_off(frag),
>   		       LARGEST_ALIGN(len));
>   		__skb_fill_netmem_desc_noacc(sinfo, i, netmem, offset, len);
>   

I know it's very unlikely but do we need to 
kmap_local_page(skb_frag_page(frag) before using 
__netmem_address(frag->netmem) to make sure the frag's page is mapped? 
Or it is impossible that the frag's page to be highmem and unmapped? Thanks,
Quang Minh.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net] xsk: respect the offsets when copying frags
  2025-04-25 15:46 ` Bui Quang Minh
@ 2025-04-26  0:23   ` Jakub Kicinski
  0 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2025-04-26  0:23 UTC (permalink / raw)
  To: Bui Quang Minh
  Cc: netdev, Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jesper Dangaard Brouer, John Fastabend, Eric Dumazet, Paolo Abeni,
	Simon Horman, Maciej Fijalkowski, Alexander Lobakin, bpf,
	linux-kernel

On Fri, 25 Apr 2025 22:46:35 +0700 Bui Quang Minh wrote:
> On 4/23/25 17:10, Bui Quang Minh wrote:
> > Add the missing offsets when copying frags in xdp_copy_frags_from_zc().
> >
> > Fixes: 560d958c6c68 ("xsk: add generic XSk &xdp_buff -> skb conversion")
> > Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
> > ---
> >   net/core/xdp.c | 7 ++++---
> >   1 file changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/net/core/xdp.c b/net/core/xdp.c
> > index f86eedad586a..a723dc301f94 100644
> > --- a/net/core/xdp.c
> > +++ b/net/core/xdp.c
> > @@ -697,7 +697,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
> >   	nr_frags = xinfo->nr_frags;
> >   
> >   	for (u32 i = 0; i < nr_frags; i++) {
> > -		u32 len = skb_frag_size(&xinfo->frags[i]);
> > +		const skb_frag_t *frag = &xinfo->frags[i];
> > +		u32 len = skb_frag_size(frag);
> >   		u32 offset, truesize = len;
> >   		netmem_ref netmem;
> >   
> > @@ -707,8 +708,8 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
> >   			return false;
> >   		}
> >   
> > -		memcpy(__netmem_address(netmem),
> > -		       __netmem_address(xinfo->frags[i].netmem),
> > +		memcpy(__netmem_address(netmem) + offset,
> > +		       __netmem_address(frag->netmem) + skb_frag_off(frag),
> >   		       LARGEST_ALIGN(len));
> >   		__skb_fill_netmem_desc_noacc(sinfo, i, netmem, offset, len);
> >     
> 
> I know it's very unlikely but do we need to 
> kmap_local_page(skb_frag_page(frag) before using 
> __netmem_address(frag->netmem) to make sure the frag's page is mapped? 
> Or it is impossible that the frag's page to be highmem and unmapped?

AFAIU these frags come from a AF_XDP umem so they should be mapped
already.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-04-26  0:23 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-23 10:10 [PATCH net] xsk: respect the offsets when copying frags Bui Quang Minh
2025-04-23 14:41 ` Stanislav Fomichev
2025-04-23 14:58   ` Bui Quang Minh
2025-04-23 18:01     ` Maciej Fijalkowski
2025-04-24 14:02 ` Alexander Lobakin
2025-04-24 14:45   ` Bui Quang Minh
2025-04-25  0:29 ` Jakub Kicinski
2025-04-25 15:46 ` Bui Quang Minh
2025-04-26  0:23   ` Jakub Kicinski

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).