All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
@ 2018-07-20 16:04 Taehee Yoo
  2018-07-20 17:18 ` Martin KaFai Lau
  0 siblings, 1 reply; 14+ messages in thread
From: Taehee Yoo @ 2018-07-20 16:04 UTC (permalink / raw)
  To: daniel, ast; +Cc: bjorn.topel, brouer, netdev, Taehee Yoo

rhashtable_lookup() can return NULL. so that NULL pointer
check routine should be added.

Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
 net/core/xdp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/xdp.c b/net/core/xdp.c
index 9d1f220..1c12bc7 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
 		rcu_read_lock();
 		/* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
 		xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
-		xa->zc_alloc->free(xa->zc_alloc, handle);
+		if (xa)
+			xa->zc_alloc->free(xa->zc_alloc, handle);
 		rcu_read_unlock();
 	default:
 		/* Not possible, checked in xdp_rxq_info_reg_mem_model() */
-- 
2.9.3

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-20 16:04 [PATCH bpf] xdp: add NULL pointer check in __xdp_return() Taehee Yoo
@ 2018-07-20 17:18 ` Martin KaFai Lau
  2018-07-20 20:05   ` Jakub Kicinski
  2018-07-21 12:56   ` Taehee Yoo
  0 siblings, 2 replies; 14+ messages in thread
From: Martin KaFai Lau @ 2018-07-20 17:18 UTC (permalink / raw)
  To: Taehee Yoo; +Cc: daniel, ast, bjorn.topel, brouer, netdev

On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:
> rhashtable_lookup() can return NULL. so that NULL pointer
> check routine should be added.
> 
> Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
> Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> ---
>  net/core/xdp.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/net/core/xdp.c b/net/core/xdp.c
> index 9d1f220..1c12bc7 100644
> --- a/net/core/xdp.c
> +++ b/net/core/xdp.c
> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
>  		rcu_read_lock();
>  		/* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
>  		xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> -		xa->zc_alloc->free(xa->zc_alloc, handle);
> +		if (xa)
> +			xa->zc_alloc->free(xa->zc_alloc, handle);
hmm...It is not clear to me the "!xa" case don't have to be handled?

>  		rcu_read_unlock();
>  	default:
>  		/* Not possible, checked in xdp_rxq_info_reg_mem_model() */
> -- 
> 2.9.3
> 

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-20 17:18 ` Martin KaFai Lau
@ 2018-07-20 20:05   ` Jakub Kicinski
  2018-07-23  9:39     ` Björn Töpel
  2018-07-21 12:56   ` Taehee Yoo
  1 sibling, 1 reply; 14+ messages in thread
From: Jakub Kicinski @ 2018-07-20 20:05 UTC (permalink / raw)
  To: daniel, bjorn.topel, brouer
  Cc: Martin KaFai Lau, Taehee Yoo, ast, netdev, Karlsson, Magnus

On Fri, 20 Jul 2018 10:18:21 -0700, Martin KaFai Lau wrote:
> On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:
> > rhashtable_lookup() can return NULL. so that NULL pointer
> > check routine should be added.
> > 
> > Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
> > Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> > ---
> >  net/core/xdp.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/net/core/xdp.c b/net/core/xdp.c
> > index 9d1f220..1c12bc7 100644
> > --- a/net/core/xdp.c
> > +++ b/net/core/xdp.c
> > @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> >  		rcu_read_lock();
> >  		/* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> >  		xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> > -		xa->zc_alloc->free(xa->zc_alloc, handle);
> > +		if (xa)
> > +			xa->zc_alloc->free(xa->zc_alloc, handle);  
> hmm...It is not clear to me the "!xa" case don't have to be handled?

Actually I have a more fundamental question about this interface I've
been meaning to ask.  

IIUC free() can happen on any CPU at any time, when whatever device,
socket or CPU this got redirected to completed the TX.  IOW there may
be multiple producers.  Drivers would need to create spin lock a'la the
a9744f7ca200 ("xsk: fix potential race in SKB TX completion code") fix?

We need some form of internal kernel circulation which would be MPSC.
I'm currently hacking up the XSK code to tell me whether the frame was
consumed by the correct XSK, and always clone the frame otherwise
(claiming to be the "traditional" MEM_TYPE_PAGE_ORDER0).

I feel like I'm missing something about the code.  Is redirect of
ZC/UMEM frame outside the xsk not possible and the only returns we will
see are from net/xdp/xsk.c?  That would work, but I don't see such a
check.  Help would be appreciated.

Also the fact that XSK bufs can't be freed, only completed, adds to the
pain of implementing AF_XDP, we'd certainly need some form of "give
back the frame, but I may need it later" SPSC mechanism, otherwise
driver writers will have tough time.  Unless, again, I'm missing
something about the code :)

> >  		rcu_read_unlock();
> >  	default:
> >  		/* Not possible, checked in xdp_rxq_info_reg_mem_model() */

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-20 17:18 ` Martin KaFai Lau
  2018-07-20 20:05   ` Jakub Kicinski
@ 2018-07-21 12:56   ` Taehee Yoo
  2018-07-23  9:41     ` Björn Töpel
  1 sibling, 1 reply; 14+ messages in thread
From: Taehee Yoo @ 2018-07-21 12:56 UTC (permalink / raw)
  To: Martin KaFai Lau; +Cc: daniel, ast, bjorn.topel, brouer, netdev

2018-07-21 2:18 GMT+09:00 Martin KaFai Lau <kafai@fb.com>:
> On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:
>> rhashtable_lookup() can return NULL. so that NULL pointer
>> check routine should be added.
>>
>> Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
>> Signed-off-by: Taehee Yoo <ap420073@gmail.com>
>> ---
>>  net/core/xdp.c | 3 ++-
>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/core/xdp.c b/net/core/xdp.c
>> index 9d1f220..1c12bc7 100644
>> --- a/net/core/xdp.c
>> +++ b/net/core/xdp.c
>> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
>>               rcu_read_lock();
>>               /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
>>               xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
>> -             xa->zc_alloc->free(xa->zc_alloc, handle);
>> +             if (xa)
>> +                     xa->zc_alloc->free(xa->zc_alloc, handle);
> hmm...It is not clear to me the "!xa" case don't have to be handled?

Thank you for reviewing!

Returning NULL pointer is bug case such as calling after use
xdp_rxq_info_unreg().
so that, I think it can't handle at that moment.
we can make __xdp_return to add WARN_ON_ONCE() or
add return error code to driver.
But I'm not sure if these is useful information.

I might have misunderstood scenario of MEM_TYPE_ZERO_COPY
because there is no use case of MEM_TYPE_ZERO_COPY yet.

Thanks!

>
>>               rcu_read_unlock();
>>       default:
>>               /* Not possible, checked in xdp_rxq_info_reg_mem_model() */
>> --
>> 2.9.3
>>

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-20 20:05   ` Jakub Kicinski
@ 2018-07-23  9:39     ` Björn Töpel
  2018-07-23 19:58       ` Jakub Kicinski
  0 siblings, 1 reply; 14+ messages in thread
From: Björn Töpel @ 2018-07-23  9:39 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Daniel Borkmann, Björn Töpel, Jesper Dangaard Brouer,
	kafai, ap420073, ast, Netdev, Karlsson, Magnus

Den fre 20 juli 2018 kl 22:08 skrev Jakub Kicinski
<jakub.kicinski@netronome.com>:
>
> On Fri, 20 Jul 2018 10:18:21 -0700, Martin KaFai Lau wrote:
> > On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:
> > > rhashtable_lookup() can return NULL. so that NULL pointer
> > > check routine should be added.
> > >
> > > Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
> > > Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> > > ---
> > >  net/core/xdp.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/net/core/xdp.c b/net/core/xdp.c
> > > index 9d1f220..1c12bc7 100644
> > > --- a/net/core/xdp.c
> > > +++ b/net/core/xdp.c
> > > @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> > >             rcu_read_lock();
> > >             /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> > >             xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> > > -           xa->zc_alloc->free(xa->zc_alloc, handle);
> > > +           if (xa)
> > > +                   xa->zc_alloc->free(xa->zc_alloc, handle);
> > hmm...It is not clear to me the "!xa" case don't have to be handled?
>
> Actually I have a more fundamental question about this interface I've
> been meaning to ask.
>
> IIUC free() can happen on any CPU at any time, when whatever device,
> socket or CPU this got redirected to completed the TX.  IOW there may
> be multiple producers.  Drivers would need to create spin lock a'la the
> a9744f7ca200 ("xsk: fix potential race in SKB TX completion code") fix?
>

Jakub, apologies for the slow response. I'm still in
"holiday/hammock&beer mode", but will be back in a week. :-P

The idea with the xdp_return_* functions are that an xdp_buff and
xdp_frame can have custom allocations schemes. The difference beween
struct xdp_buff and struct xdp_frame is lifetime. The xdp_buff
lifetime is within the napi context, whereas xdp_frame can have a
lifetime longer/outside the napi context. E.g. for a XDP_REDIRECT
scenario an xdp_buff is converted to a xdp_frame. The conversion is
done in include/net/xdp.h:convert_to_xdp_frame.

Currently, the zero-copy MEM_TYPE_ZERO_COPY memtype can *only* be used
for xdp_buff, meaning that the lifetime is constrained to a napi
context. Further, given an xdp_buff with memtype MEM_TYPE_ZERO_COPY,
doing XDP_REDIRECT to a target that is *not* an AF_XDP socket would
mean converting the xdp_buff to an xdp_frame. The xdp_frame can then
be free'd on any CPU.

Note that the xsk_rcv* functions is always called from an napi
context, and therefore is using the xdp_return_buff calls.

To answer your question -- no, this fix is *not* needed, because the
xdp_buff napi constrained, and the xdp_buff will only be free'd on one
CPU.

> We need some form of internal kernel circulation which would be MPSC.
> I'm currently hacking up the XSK code to tell me whether the frame was
> consumed by the correct XSK, and always clone the frame otherwise
> (claiming to be the "traditional" MEM_TYPE_PAGE_ORDER0).
>
> I feel like I'm missing something about the code.  Is redirect of
> ZC/UMEM frame outside the xsk not possible and the only returns we will
> see are from net/xdp/xsk.c?  That would work, but I don't see such a
> check.  Help would be appreciated.
>

Right now, this is the case (refer to the TODO in
convert_to_xdp_frame), i.e. you cannot redirect an ZC/UMEM allocated
xdp_buff to a target that is not an xsk. This must, obviously, change
so that an xdp_buff (of MEM_TYPE_ZERO_COPY) can be converted to an
xdp_frame. The xdp_frame must be able to be free'd from multiple CPUs,
so here the a more sophisticated allocation scheme is required.

> Also the fact that XSK bufs can't be freed, only completed, adds to the
> pain of implementing AF_XDP, we'd certainly need some form of "give
> back the frame, but I may need it later" SPSC mechanism, otherwise
> driver writers will have tough time.  Unless, again, I'm missing
> something about the code :)
>

Yup, moving the recycling scheme from driver to "generic" is a good
idea! I need to finish up those i40e zerocopy patches first though...

(...and I'm very excited that you're doing nfp support for AF_XDP!!!)


Björn

> > >             rcu_read_unlock();
> > >     default:
> > >             /* Not possible, checked in xdp_rxq_info_reg_mem_model() */
>

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-21 12:56   ` Taehee Yoo
@ 2018-07-23  9:41     ` Björn Töpel
  2018-07-23 13:21       ` Taehee Yoo
  2018-08-01 14:14       ` Jesper Dangaard Brouer
  0 siblings, 2 replies; 14+ messages in thread
From: Björn Töpel @ 2018-07-23  9:41 UTC (permalink / raw)
  To: ap420073
  Cc: kafai, Daniel Borkmann, ast, Björn Töpel,
	Jesper Dangaard Brouer, Netdev

Den lör 21 juli 2018 kl 14:58 skrev Taehee Yoo <ap420073@gmail.com>:
>
> 2018-07-21 2:18 GMT+09:00 Martin KaFai Lau <kafai@fb.com>:
> > On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:
> >> rhashtable_lookup() can return NULL. so that NULL pointer
> >> check routine should be added.
> >>
> >> Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
> >> Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> >> ---
> >>  net/core/xdp.c | 3 ++-
> >>  1 file changed, 2 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/net/core/xdp.c b/net/core/xdp.c
> >> index 9d1f220..1c12bc7 100644
> >> --- a/net/core/xdp.c
> >> +++ b/net/core/xdp.c
> >> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> >>               rcu_read_lock();
> >>               /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> >>               xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> >> -             xa->zc_alloc->free(xa->zc_alloc, handle);
> >> +             if (xa)
> >> +                     xa->zc_alloc->free(xa->zc_alloc, handle);
> > hmm...It is not clear to me the "!xa" case don't have to be handled?
>
> Thank you for reviewing!
>
> Returning NULL pointer is bug case such as calling after use
> xdp_rxq_info_unreg().
> so that, I think it can't handle at that moment.
> we can make __xdp_return to add WARN_ON_ONCE() or
> add return error code to driver.
> But I'm not sure if these is useful information.
>
> I might have misunderstood scenario of MEM_TYPE_ZERO_COPY
> because there is no use case of MEM_TYPE_ZERO_COPY yet.
>

Taehee, again, sorry for the slow response and thanks for patch!

If xa is NULL, the driver has a buggy/broken implementation. What
would be a proper way of dealing with this? BUG?


Björn

> Thanks!
>
> >
> >>               rcu_read_unlock();
> >>       default:
> >>               /* Not possible, checked in xdp_rxq_info_reg_mem_model() */
> >> --
> >> 2.9.3
> >>

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-23  9:41     ` Björn Töpel
@ 2018-07-23 13:21       ` Taehee Yoo
  2018-08-01 14:14       ` Jesper Dangaard Brouer
  1 sibling, 0 replies; 14+ messages in thread
From: Taehee Yoo @ 2018-07-23 13:21 UTC (permalink / raw)
  To: Björn Töpel
  Cc: Martin KaFai Lau, Daniel Borkmann, ast, Björn Töpel,
	Jesper Dangaard Brouer, Netdev

2018-07-23 18:41 GMT+09:00 Björn Töpel <bjorn.topel@gmail.com>:
> Den lör 21 juli 2018 kl 14:58 skrev Taehee Yoo <ap420073@gmail.com>:
>>
>> 2018-07-21 2:18 GMT+09:00 Martin KaFai Lau <kafai@fb.com>:
>> > On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:
>> >> rhashtable_lookup() can return NULL. so that NULL pointer
>> >> check routine should be added.
>> >>
>> >> Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
>> >> Signed-off-by: Taehee Yoo <ap420073@gmail.com>
>> >> ---
>> >>  net/core/xdp.c | 3 ++-
>> >>  1 file changed, 2 insertions(+), 1 deletion(-)
>> >>
>> >> diff --git a/net/core/xdp.c b/net/core/xdp.c
>> >> index 9d1f220..1c12bc7 100644
>> >> --- a/net/core/xdp.c
>> >> +++ b/net/core/xdp.c
>> >> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
>> >>               rcu_read_lock();
>> >>               /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
>> >>               xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
>> >> -             xa->zc_alloc->free(xa->zc_alloc, handle);
>> >> +             if (xa)
>> >> +                     xa->zc_alloc->free(xa->zc_alloc, handle);
>> > hmm...It is not clear to me the "!xa" case don't have to be handled?
>>
>> Thank you for reviewing!
>>
>> Returning NULL pointer is bug case such as calling after use
>> xdp_rxq_info_unreg().
>> so that, I think it can't handle at that moment.
>> we can make __xdp_return to add WARN_ON_ONCE() or
>> add return error code to driver.
>> But I'm not sure if these is useful information.
>>
>> I might have misunderstood scenario of MEM_TYPE_ZERO_COPY
>> because there is no use case of MEM_TYPE_ZERO_COPY yet.
>>
>
> Taehee, again, sorry for the slow response and thanks for patch!
>
> If xa is NULL, the driver has a buggy/broken implementation. What
> would be a proper way of dealing with this? BUG?
>

Thank you for reviewing!

I would like to add WARN_ON_ONCE. because code writers can
get opportunity for debugging this in runtime. also I think this bug
doesn't make critical side effect.

Thanks!

>
> Björn
>
>> Thanks!
>>
>> >
>> >>               rcu_read_unlock();
>> >>       default:
>> >>               /* Not possible, checked in xdp_rxq_info_reg_mem_model() */
>> >> --
>> >> 2.9.3
>> >>

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-23  9:39     ` Björn Töpel
@ 2018-07-23 19:58       ` Jakub Kicinski
  2018-07-26 12:13         ` Björn Töpel
  0 siblings, 1 reply; 14+ messages in thread
From: Jakub Kicinski @ 2018-07-23 19:58 UTC (permalink / raw)
  To: Björn Töpel
  Cc: Daniel Borkmann, Björn Töpel, Jesper Dangaard Brouer,
	kafai, ap420073, ast, Netdev, Karlsson, Magnus

On Mon, 23 Jul 2018 11:39:36 +0200, Björn Töpel wrote:
> Den fre 20 juli 2018 kl 22:08 skrev Jakub Kicinski:
> > On Fri, 20 Jul 2018 10:18:21 -0700, Martin KaFai Lau wrote:  
> > > On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:  
> > > > rhashtable_lookup() can return NULL. so that NULL pointer
> > > > check routine should be added.
> > > >
> > > > Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
> > > > Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> > > > ---
> > > >  net/core/xdp.c | 3 ++-
> > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/net/core/xdp.c b/net/core/xdp.c
> > > > index 9d1f220..1c12bc7 100644
> > > > --- a/net/core/xdp.c
> > > > +++ b/net/core/xdp.c
> > > > @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> > > >             rcu_read_lock();
> > > >             /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> > > >             xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> > > > -           xa->zc_alloc->free(xa->zc_alloc, handle);
> > > > +           if (xa)
> > > > +                   xa->zc_alloc->free(xa->zc_alloc, handle);  
> > > hmm...It is not clear to me the "!xa" case don't have to be handled?  
> >
> > Actually I have a more fundamental question about this interface I've
> > been meaning to ask.
> >
> > IIUC free() can happen on any CPU at any time, when whatever device,
> > socket or CPU this got redirected to completed the TX.  IOW there may
> > be multiple producers.  Drivers would need to create spin lock a'la the
> > a9744f7ca200 ("xsk: fix potential race in SKB TX completion code") fix?
> >  
> 
> Jakub, apologies for the slow response. I'm still in
> "holiday/hammock&beer mode", but will be back in a week. :-P

Ah, sorry to interrupt! :)

> The idea with the xdp_return_* functions are that an xdp_buff and
> xdp_frame can have custom allocations schemes. The difference beween
> struct xdp_buff and struct xdp_frame is lifetime. The xdp_buff
> lifetime is within the napi context, whereas xdp_frame can have a
> lifetime longer/outside the napi context. E.g. for a XDP_REDIRECT
> scenario an xdp_buff is converted to a xdp_frame. The conversion is
> done in include/net/xdp.h:convert_to_xdp_frame.
> 
> Currently, the zero-copy MEM_TYPE_ZERO_COPY memtype can *only* be used
> for xdp_buff, meaning that the lifetime is constrained to a napi
> context. Further, given an xdp_buff with memtype MEM_TYPE_ZERO_COPY,
> doing XDP_REDIRECT to a target that is *not* an AF_XDP socket would
> mean converting the xdp_buff to an xdp_frame. The xdp_frame can then
> be free'd on any CPU.
> 
> Note that the xsk_rcv* functions is always called from an napi
> context, and therefore is using the xdp_return_buff calls.
> 
> To answer your question -- no, this fix is *not* needed, because the
> xdp_buff napi constrained, and the xdp_buff will only be free'd on one
> CPU.

Oh, thanks, I missed the check in convert_to_xdp_frame(), so the only
frames which can come back via the free path are out of the error path
in __xsk_rcv_zc()?

That path looks a little surprising too, isn't the expectation that if
xdp_do_redirect() returns an error the driver retains the ownership of
the buffer? 
 
static int __xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
{
	int err = xskq_produce_batch_desc(xs->rx, (u64)xdp->handle, len);

	if (err) {
		xdp_return_buff(xdp);
		xs->rx_dropped++;
	}

	return err;
}

This seems to call xdp_return_buff() *and* return an error.

> > We need some form of internal kernel circulation which would be MPSC.
> > I'm currently hacking up the XSK code to tell me whether the frame was
> > consumed by the correct XSK, and always clone the frame otherwise
> > (claiming to be the "traditional" MEM_TYPE_PAGE_ORDER0).
> >
> > I feel like I'm missing something about the code.  Is redirect of
> > ZC/UMEM frame outside the xsk not possible and the only returns we will
> > see are from net/xdp/xsk.c?  That would work, but I don't see such a
> > check.  Help would be appreciated.
> >  
> 
> Right now, this is the case (refer to the TODO in
> convert_to_xdp_frame), i.e. you cannot redirect an ZC/UMEM allocated
> xdp_buff to a target that is not an xsk. This must, obviously, change
> so that an xdp_buff (of MEM_TYPE_ZERO_COPY) can be converted to an
> xdp_frame. The xdp_frame must be able to be free'd from multiple CPUs,
> so here the a more sophisticated allocation scheme is required.
> 
> > Also the fact that XSK bufs can't be freed, only completed, adds to the
> > pain of implementing AF_XDP, we'd certainly need some form of "give
> > back the frame, but I may need it later" SPSC mechanism, otherwise
> > driver writers will have tough time.  Unless, again, I'm missing
> > something about the code :)
> >  
> 
> Yup, moving the recycling scheme from driver to "generic" is a good
> idea! I need to finish up those i40e zerocopy patches first though...

Interesting, FWIW I wasn't necessarily thinking about full recycling,
although that would be the holy grail.  Just a generic way of giving up
buffers for example when user changes ring sizes or brings the device
down.

> (...and I'm very excited that you're doing nfp support for AF_XDP!!!)

Thanks, I'm still way out in the weeds but it's interesting work :)

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-23 19:58       ` Jakub Kicinski
@ 2018-07-26 12:13         ` Björn Töpel
  2018-07-26 18:47           ` Jakub Kicinski
  0 siblings, 1 reply; 14+ messages in thread
From: Björn Töpel @ 2018-07-26 12:13 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Daniel Borkmann, Björn Töpel, Jesper Dangaard Brouer,
	kafai, Taehee Yoo, ast, Netdev, Karlsson, Magnus

Den mån 23 juli 2018 kl 21:58 skrev Jakub Kicinski
<jakub.kicinski@netronome.com>:
>
> On Mon, 23 Jul 2018 11:39:36 +0200, Björn Töpel wrote:
> > Den fre 20 juli 2018 kl 22:08 skrev Jakub Kicinski:
> > > On Fri, 20 Jul 2018 10:18:21 -0700, Martin KaFai Lau wrote:
> > > > On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:
> > > > > rhashtable_lookup() can return NULL. so that NULL pointer
> > > > > check routine should be added.
> > > > >
> > > > > Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
> > > > > Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> > > > > ---
> > > > >  net/core/xdp.c | 3 ++-
> > > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/net/core/xdp.c b/net/core/xdp.c
> > > > > index 9d1f220..1c12bc7 100644
> > > > > --- a/net/core/xdp.c
> > > > > +++ b/net/core/xdp.c
> > > > > @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> > > > >             rcu_read_lock();
> > > > >             /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> > > > >             xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> > > > > -           xa->zc_alloc->free(xa->zc_alloc, handle);
> > > > > +           if (xa)
> > > > > +                   xa->zc_alloc->free(xa->zc_alloc, handle);
> > > > hmm...It is not clear to me the "!xa" case don't have to be handled?
> > >
> > > Actually I have a more fundamental question about this interface I've
> > > been meaning to ask.
> > >
> > > IIUC free() can happen on any CPU at any time, when whatever device,
> > > socket or CPU this got redirected to completed the TX.  IOW there may
> > > be multiple producers.  Drivers would need to create spin lock a'la the
> > > a9744f7ca200 ("xsk: fix potential race in SKB TX completion code") fix?
> > >
> >
> > Jakub, apologies for the slow response. I'm still in
> > "holiday/hammock&beer mode", but will be back in a week. :-P
>
> Ah, sorry to interrupt! :)
>

Don't make it a habit! ;-P

> > The idea with the xdp_return_* functions are that an xdp_buff and
> > xdp_frame can have custom allocations schemes. The difference beween
> > struct xdp_buff and struct xdp_frame is lifetime. The xdp_buff
> > lifetime is within the napi context, whereas xdp_frame can have a
> > lifetime longer/outside the napi context. E.g. for a XDP_REDIRECT
> > scenario an xdp_buff is converted to a xdp_frame. The conversion is
> > done in include/net/xdp.h:convert_to_xdp_frame.
> >
> > Currently, the zero-copy MEM_TYPE_ZERO_COPY memtype can *only* be used
> > for xdp_buff, meaning that the lifetime is constrained to a napi
> > context. Further, given an xdp_buff with memtype MEM_TYPE_ZERO_COPY,
> > doing XDP_REDIRECT to a target that is *not* an AF_XDP socket would
> > mean converting the xdp_buff to an xdp_frame. The xdp_frame can then
> > be free'd on any CPU.
> >
> > Note that the xsk_rcv* functions is always called from an napi
> > context, and therefore is using the xdp_return_buff calls.
> >
> > To answer your question -- no, this fix is *not* needed, because the
> > xdp_buff napi constrained, and the xdp_buff will only be free'd on one
> > CPU.
>
> Oh, thanks, I missed the check in convert_to_xdp_frame(), so the only
> frames which can come back via the free path are out of the error path
> in __xsk_rcv_zc()?
>
> That path looks a little surprising too, isn't the expectation that if
> xdp_do_redirect() returns an error the driver retains the ownership of
> the buffer?
>
> static int __xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
> {
>         int err = xskq_produce_batch_desc(xs->rx, (u64)xdp->handle, len);
>
>         if (err) {
>                 xdp_return_buff(xdp);
>                 xs->rx_dropped++;
>         }
>
>         return err;
> }
>
> This seems to call xdp_return_buff() *and* return an error.
>

Ugh, this is indeed an error. The xdp_return buff should be removed.
Thanks for spotting this!

So, yes, the way to get the buffer back (in ZC) to the driver is via
the error path (recycling) or via the UMEM fill queue.

> > > We need some form of internal kernel circulation which would be MPSC.
> > > I'm currently hacking up the XSK code to tell me whether the frame was
> > > consumed by the correct XSK, and always clone the frame otherwise
> > > (claiming to be the "traditional" MEM_TYPE_PAGE_ORDER0).
> > >
> > > I feel like I'm missing something about the code.  Is redirect of
> > > ZC/UMEM frame outside the xsk not possible and the only returns we will
> > > see are from net/xdp/xsk.c?  That would work, but I don't see such a
> > > check.  Help would be appreciated.
> > >
> >
> > Right now, this is the case (refer to the TODO in
> > convert_to_xdp_frame), i.e. you cannot redirect an ZC/UMEM allocated
> > xdp_buff to a target that is not an xsk. This must, obviously, change
> > so that an xdp_buff (of MEM_TYPE_ZERO_COPY) can be converted to an
> > xdp_frame. The xdp_frame must be able to be free'd from multiple CPUs,
> > so here the a more sophisticated allocation scheme is required.
> >
> > > Also the fact that XSK bufs can't be freed, only completed, adds to the
> > > pain of implementing AF_XDP, we'd certainly need some form of "give
> > > back the frame, but I may need it later" SPSC mechanism, otherwise
> > > driver writers will have tough time.  Unless, again, I'm missing
> > > something about the code :)
> > >
> >
> > Yup, moving the recycling scheme from driver to "generic" is a good
> > idea! I need to finish up those i40e zerocopy patches first though...
>
> Interesting, FWIW I wasn't necessarily thinking about full recycling,
> although that would be the holy grail.  Just a generic way of giving up
> buffers for example when user changes ring sizes or brings the device
> down.
>
> > (...and I'm very excited that you're doing nfp support for AF_XDP!!!)
>
> Thanks, I'm still way out in the weeds but it's interesting work :)

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-26 12:13         ` Björn Töpel
@ 2018-07-26 18:47           ` Jakub Kicinski
  0 siblings, 0 replies; 14+ messages in thread
From: Jakub Kicinski @ 2018-07-26 18:47 UTC (permalink / raw)
  To: Björn Töpel
  Cc: Daniel Borkmann, Björn Töpel, Jesper Dangaard Brouer,
	kafai, Taehee Yoo, ast, Netdev, Karlsson, Magnus

On Thu, 26 Jul 2018 14:13:20 +0200, Björn Töpel wrote:
> Den mån 23 juli 2018 kl 21:58 skrev Jakub Kicinski:
> > On Mon, 23 Jul 2018 11:39:36 +0200, Björn Töpel wrote:  
> > > Den fre 20 juli 2018 kl 22:08 skrev Jakub Kicinski:  
> > > > On Fri, 20 Jul 2018 10:18:21 -0700, Martin KaFai Lau wrote:  
> > > > > On Sat, Jul 21, 2018 at 01:04:45AM +0900, Taehee Yoo wrote:  
> > > > > > rhashtable_lookup() can return NULL. so that NULL pointer
> > > > > > check routine should be added.
> > > > > >
> > > > > > Fixes: 02b55e5657c3 ("xdp: add MEM_TYPE_ZERO_COPY")
> > > > > > Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> > > > > > ---
> > > > > >  net/core/xdp.c | 3 ++-
> > > > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > > > >
> > > > > > diff --git a/net/core/xdp.c b/net/core/xdp.c
> > > > > > index 9d1f220..1c12bc7 100644
> > > > > > --- a/net/core/xdp.c
> > > > > > +++ b/net/core/xdp.c
> > > > > > @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> > > > > >             rcu_read_lock();
> > > > > >             /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> > > > > >             xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> > > > > > -           xa->zc_alloc->free(xa->zc_alloc, handle);
> > > > > > +           if (xa)
> > > > > > +                   xa->zc_alloc->free(xa->zc_alloc, handle);  
> > > > > hmm...It is not clear to me the "!xa" case don't have to be handled?  
> > > >
> > > > Actually I have a more fundamental question about this interface I've
> > > > been meaning to ask.
> > > >
> > > > IIUC free() can happen on any CPU at any time, when whatever device,
> > > > socket or CPU this got redirected to completed the TX.  IOW there may
> > > > be multiple producers.  Drivers would need to create spin lock a'la the
> > > > a9744f7ca200 ("xsk: fix potential race in SKB TX completion code") fix?
> > > >  
> > >
> > > Jakub, apologies for the slow response. I'm still in
> > > "holiday/hammock&beer mode", but will be back in a week. :-P  
> >
> > Ah, sorry to interrupt! :)
> >  
> 
> Don't make it a habit! ;-P

:-D

> > > The idea with the xdp_return_* functions are that an xdp_buff and
> > > xdp_frame can have custom allocations schemes. The difference beween
> > > struct xdp_buff and struct xdp_frame is lifetime. The xdp_buff
> > > lifetime is within the napi context, whereas xdp_frame can have a
> > > lifetime longer/outside the napi context. E.g. for a XDP_REDIRECT
> > > scenario an xdp_buff is converted to a xdp_frame. The conversion is
> > > done in include/net/xdp.h:convert_to_xdp_frame.
> > >
> > > Currently, the zero-copy MEM_TYPE_ZERO_COPY memtype can *only* be used
> > > for xdp_buff, meaning that the lifetime is constrained to a napi
> > > context. Further, given an xdp_buff with memtype MEM_TYPE_ZERO_COPY,
> > > doing XDP_REDIRECT to a target that is *not* an AF_XDP socket would
> > > mean converting the xdp_buff to an xdp_frame. The xdp_frame can then
> > > be free'd on any CPU.
> > >
> > > Note that the xsk_rcv* functions is always called from an napi
> > > context, and therefore is using the xdp_return_buff calls.
> > >
> > > To answer your question -- no, this fix is *not* needed, because the
> > > xdp_buff napi constrained, and the xdp_buff will only be free'd on one
> > > CPU.  
> >
> > Oh, thanks, I missed the check in convert_to_xdp_frame(), so the only
> > frames which can come back via the free path are out of the error path
> > in __xsk_rcv_zc()?
> >
> > That path looks a little surprising too, isn't the expectation that if
> > xdp_do_redirect() returns an error the driver retains the ownership of
> > the buffer?
> >
> > static int __xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
> > {
> >         int err = xskq_produce_batch_desc(xs->rx, (u64)xdp->handle, len);
> >
> >         if (err) {
> >                 xdp_return_buff(xdp);
> >                 xs->rx_dropped++;
> >         }
> >
> >         return err;
> > }
> >
> > This seems to call xdp_return_buff() *and* return an error.
> >  
> 
> Ugh, this is indeed an error. The xdp_return buff should be removed.
> Thanks for spotting this!
> 
> So, yes, the way to get the buffer back (in ZC) to the driver is via
> the error path (recycling) or via the UMEM fill queue.

Okay, I'm gonna test and submit this later today for bpf tree:

diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index 72335c2e8108..4e937cd7c17d 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -84,10 +84,8 @@ static int __xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
 {
        int err = xskq_produce_batch_desc(xs->rx, (u64)xdp->handle, len);
 
-       if (err) {
-               xdp_return_buff(xdp);
+       if (err)
                xs->rx_dropped++;
-       }
 
        return err;
 }

Now the frame return/ZC allocator ->free path is all dead code :S

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-07-23  9:41     ` Björn Töpel
  2018-07-23 13:21       ` Taehee Yoo
@ 2018-08-01 14:14       ` Jesper Dangaard Brouer
  2018-08-01 14:43         ` Björn Töpel
  1 sibling, 1 reply; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2018-08-01 14:14 UTC (permalink / raw)
  To: Björn Töpel
  Cc: ap420073, kafai, Daniel Borkmann, ast, Björn Töpel,
	Netdev, brouer

On Mon, 23 Jul 2018 11:41:02 +0200
Björn Töpel <bjorn.topel@gmail.com> wrote:

> > >> diff --git a/net/core/xdp.c b/net/core/xdp.c
> > >> index 9d1f220..1c12bc7 100644
> > >> --- a/net/core/xdp.c
> > >> +++ b/net/core/xdp.c
> > >> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> > >>               rcu_read_lock();
> > >>               /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> > >>               xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> > >> -             xa->zc_alloc->free(xa->zc_alloc, handle);
> > >> +             if (xa)
> > >> +                     xa->zc_alloc->free(xa->zc_alloc, handle);  
> > > hmm...It is not clear to me the "!xa" case don't have to be handled?  
> >
> > Thank you for reviewing!
> >
> > Returning NULL pointer is bug case such as calling after use
> > xdp_rxq_info_unreg().
> > so that, I think it can't handle at that moment.
> > we can make __xdp_return to add WARN_ON_ONCE() or
> > add return error code to driver.
> > But I'm not sure if these is useful information.
> >
> > I might have misunderstood scenario of MEM_TYPE_ZERO_COPY
> > because there is no use case of MEM_TYPE_ZERO_COPY yet.
> >  
> 
> Taehee, again, sorry for the slow response and thanks for patch!
> 
> If xa is NULL, the driver has a buggy/broken implementation. What
> would be a proper way of dealing with this? BUG?

Hmm... I don't like these kind of changes to the hot-path code!

You might not realize this, but adding BUG() and WARN_ON() to the code
affect performance in ways you might not realize!  These macros gets
compiled and uses an asm instruction called "ud2".  Seeing the "ud2"
instruction causes the CPUs instruction cache prefetcher to stop.
Thus, if some code ends up below this instruction, this will cause more
i-cache-misses.

I don't know if xa==NULL is even possible, but if it is, then I think
this is a result of a driver mem_reg API usage bug.  And the mem-reg
API is full of WARN's and error messages, exactly to push these kind of
checks out of the fast-path.  There is no need for a BUG() call, as
deref a NULL pointer will case an OOPS, that is easy to read and
understand.

-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-08-01 14:14       ` Jesper Dangaard Brouer
@ 2018-08-01 14:43         ` Björn Töpel
  2018-08-01 20:25           ` Daniel Borkmann
  0 siblings, 1 reply; 14+ messages in thread
From: Björn Töpel @ 2018-08-01 14:43 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: Taehee Yoo, kafai, Daniel Borkmann, ast, Björn Töpel, Netdev

Den ons 1 aug. 2018 kl 16:14 skrev Jesper Dangaard Brouer <brouer@redhat.com>:
>
> On Mon, 23 Jul 2018 11:41:02 +0200
> Björn Töpel <bjorn.topel@gmail.com> wrote:
>
> > > >> diff --git a/net/core/xdp.c b/net/core/xdp.c
> > > >> index 9d1f220..1c12bc7 100644
> > > >> --- a/net/core/xdp.c
> > > >> +++ b/net/core/xdp.c
> > > >> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> > > >>               rcu_read_lock();
> > > >>               /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> > > >>               xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> > > >> -             xa->zc_alloc->free(xa->zc_alloc, handle);
> > > >> +             if (xa)
> > > >> +                     xa->zc_alloc->free(xa->zc_alloc, handle);
> > > > hmm...It is not clear to me the "!xa" case don't have to be handled?
> > >
> > > Thank you for reviewing!
> > >
> > > Returning NULL pointer is bug case such as calling after use
> > > xdp_rxq_info_unreg().
> > > so that, I think it can't handle at that moment.
> > > we can make __xdp_return to add WARN_ON_ONCE() or
> > > add return error code to driver.
> > > But I'm not sure if these is useful information.
> > >
> > > I might have misunderstood scenario of MEM_TYPE_ZERO_COPY
> > > because there is no use case of MEM_TYPE_ZERO_COPY yet.
> > >
> >
> > Taehee, again, sorry for the slow response and thanks for patch!
> >
> > If xa is NULL, the driver has a buggy/broken implementation. What
> > would be a proper way of dealing with this? BUG?
>
> Hmm... I don't like these kind of changes to the hot-path code!
>
> You might not realize this, but adding BUG() and WARN_ON() to the code
> affect performance in ways you might not realize!  These macros gets
> compiled and uses an asm instruction called "ud2".  Seeing the "ud2"
> instruction causes the CPUs instruction cache prefetcher to stop.
> Thus, if some code ends up below this instruction, this will cause more
> i-cache-misses.
>
> I don't know if xa==NULL is even possible, but if it is, then I think
> this is a result of a driver mem_reg API usage bug.  And the mem-reg
> API is full of WARN's and error messages, exactly to push these kind of
> checks out of the fast-path.  There is no need for a BUG() call, as
> deref a NULL pointer will case an OOPS, that is easy to read and
> understand.
>

Jesper, thanks for having a look! So, you're right that if xa==NULL
the driver is "broken/buggy" (as stated earlier!). I agree that
OOPSing on a NULL pointer is as good as a BUG!

The applied patch adds a WARN_ON_ONCE, and I thought best practice was
that a buggy driver shouldn't crash the kernel... What is considered
best practices in these scenarios? *I'd* prefer an OOPS instead of
WARN_ON_ONCE, to catch that buggy driver. Again, that's me. I thought
that most people prefer not crashing, hence the patch. :-)


Björn

> --
> Best regards,
>   Jesper Dangaard Brouer
>   MSc.CS, Principal Kernel Engineer at Red Hat
>   LinkedIn: http://www.linkedin.com/in/brouer

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-08-01 14:43         ` Björn Töpel
@ 2018-08-01 20:25           ` Daniel Borkmann
  2018-08-02 10:59             ` Björn Töpel
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Borkmann @ 2018-08-01 20:25 UTC (permalink / raw)
  To: Björn Töpel, Jesper Dangaard Brouer
  Cc: Taehee Yoo, kafai, ast, Björn Töpel, Netdev

On 08/01/2018 04:43 PM, Björn Töpel wrote:
> Den ons 1 aug. 2018 kl 16:14 skrev Jesper Dangaard Brouer <brouer@redhat.com>:
>> On Mon, 23 Jul 2018 11:41:02 +0200
>> Björn Töpel <bjorn.topel@gmail.com> wrote:
>>
>>>>>> diff --git a/net/core/xdp.c b/net/core/xdp.c
>>>>>> index 9d1f220..1c12bc7 100644
>>>>>> --- a/net/core/xdp.c
>>>>>> +++ b/net/core/xdp.c
>>>>>> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
>>>>>>               rcu_read_lock();
>>>>>>               /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
>>>>>>               xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
>>>>>> -             xa->zc_alloc->free(xa->zc_alloc, handle);
>>>>>> +             if (xa)
>>>>>> +                     xa->zc_alloc->free(xa->zc_alloc, handle);
>>>>> hmm...It is not clear to me the "!xa" case don't have to be handled?
>>>>
>>>> Thank you for reviewing!
>>>>
>>>> Returning NULL pointer is bug case such as calling after use
>>>> xdp_rxq_info_unreg().
>>>> so that, I think it can't handle at that moment.
>>>> we can make __xdp_return to add WARN_ON_ONCE() or
>>>> add return error code to driver.
>>>> But I'm not sure if these is useful information.
>>>>
>>>> I might have misunderstood scenario of MEM_TYPE_ZERO_COPY
>>>> because there is no use case of MEM_TYPE_ZERO_COPY yet.
>>>
>>> Taehee, again, sorry for the slow response and thanks for patch!
>>>
>>> If xa is NULL, the driver has a buggy/broken implementation. What
>>> would be a proper way of dealing with this? BUG?
>>
>> Hmm... I don't like these kind of changes to the hot-path code!
>>
>> You might not realize this, but adding BUG() and WARN_ON() to the code
>> affect performance in ways you might not realize!  These macros gets
>> compiled and uses an asm instruction called "ud2".  Seeing the "ud2"
>> instruction causes the CPUs instruction cache prefetcher to stop.
>> Thus, if some code ends up below this instruction, this will cause more
>> i-cache-misses.
>>
>> I don't know if xa==NULL is even possible, but if it is, then I think
>> this is a result of a driver mem_reg API usage bug.  And the mem-reg
>> API is full of WARN's and error messages, exactly to push these kind of
>> checks out of the fast-path.  There is no need for a BUG() call, as
>> deref a NULL pointer will case an OOPS, that is easy to read and
>> understand.
> 
> Jesper, thanks for having a look! So, you're right that if xa==NULL
> the driver is "broken/buggy" (as stated earlier!). I agree that
> OOPSing on a NULL pointer is as good as a BUG!
> 
> The applied patch adds a WARN_ON_ONCE, and I thought best practice was
> that a buggy driver shouldn't crash the kernel... What is considered
> best practices in these scenarios? *I'd* prefer an OOPS instead of
> WARN_ON_ONCE, to catch that buggy driver. Again, that's me. I thought
> that most people prefer not crashing, hence the patch. :-)

In that case, lets send a revert for the patch with a proper analysis
of why it is safe to omit the NULL check which should be placed as a
comment right near the rhashtable_lookup().

Thanks,
Daniel

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

* Re: [PATCH bpf] xdp: add NULL pointer check in __xdp_return()
  2018-08-01 20:25           ` Daniel Borkmann
@ 2018-08-02 10:59             ` Björn Töpel
  0 siblings, 0 replies; 14+ messages in thread
From: Björn Töpel @ 2018-08-02 10:59 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: Jesper Dangaard Brouer, Taehee Yoo, kafai, ast,
	Björn Töpel, Netdev

Den ons 1 aug. 2018 kl 22:25 skrev Daniel Borkmann <daniel@iogearbox.net>:
>
> On 08/01/2018 04:43 PM, Björn Töpel wrote:
> > Den ons 1 aug. 2018 kl 16:14 skrev Jesper Dangaard Brouer <brouer@redhat.com>:
> >> On Mon, 23 Jul 2018 11:41:02 +0200
> >> Björn Töpel <bjorn.topel@gmail.com> wrote:
> >>
> >>>>>> diff --git a/net/core/xdp.c b/net/core/xdp.c
> >>>>>> index 9d1f220..1c12bc7 100644
> >>>>>> --- a/net/core/xdp.c
> >>>>>> +++ b/net/core/xdp.c
> >>>>>> @@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
> >>>>>>               rcu_read_lock();
> >>>>>>               /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
> >>>>>>               xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
> >>>>>> -             xa->zc_alloc->free(xa->zc_alloc, handle);
> >>>>>> +             if (xa)
> >>>>>> +                     xa->zc_alloc->free(xa->zc_alloc, handle);
> >>>>> hmm...It is not clear to me the "!xa" case don't have to be handled?
> >>>>
> >>>> Thank you for reviewing!
> >>>>
> >>>> Returning NULL pointer is bug case such as calling after use
> >>>> xdp_rxq_info_unreg().
> >>>> so that, I think it can't handle at that moment.
> >>>> we can make __xdp_return to add WARN_ON_ONCE() or
> >>>> add return error code to driver.
> >>>> But I'm not sure if these is useful information.
> >>>>
> >>>> I might have misunderstood scenario of MEM_TYPE_ZERO_COPY
> >>>> because there is no use case of MEM_TYPE_ZERO_COPY yet.
> >>>
> >>> Taehee, again, sorry for the slow response and thanks for patch!
> >>>
> >>> If xa is NULL, the driver has a buggy/broken implementation. What
> >>> would be a proper way of dealing with this? BUG?
> >>
> >> Hmm... I don't like these kind of changes to the hot-path code!
> >>
> >> You might not realize this, but adding BUG() and WARN_ON() to the code
> >> affect performance in ways you might not realize!  These macros gets
> >> compiled and uses an asm instruction called "ud2".  Seeing the "ud2"
> >> instruction causes the CPUs instruction cache prefetcher to stop.
> >> Thus, if some code ends up below this instruction, this will cause more
> >> i-cache-misses.
> >>
> >> I don't know if xa==NULL is even possible, but if it is, then I think
> >> this is a result of a driver mem_reg API usage bug.  And the mem-reg
> >> API is full of WARN's and error messages, exactly to push these kind of
> >> checks out of the fast-path.  There is no need for a BUG() call, as
> >> deref a NULL pointer will case an OOPS, that is easy to read and
> >> understand.
> >
> > Jesper, thanks for having a look! So, you're right that if xa==NULL
> > the driver is "broken/buggy" (as stated earlier!). I agree that
> > OOPSing on a NULL pointer is as good as a BUG!
> >
> > The applied patch adds a WARN_ON_ONCE, and I thought best practice was
> > that a buggy driver shouldn't crash the kernel... What is considered
> > best practices in these scenarios? *I'd* prefer an OOPS instead of
> > WARN_ON_ONCE, to catch that buggy driver. Again, that's me. I thought
> > that most people prefer not crashing, hence the patch. :-)
>
> In that case, lets send a revert for the patch with a proper analysis
> of why it is safe to omit the NULL check which should be placed as a
> comment right near the rhashtable_lookup().
>

I'll do that (as soon as I've double-checked so that I'm not lying)!


Björn

> Thanks,
> Daniel

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

end of thread, other threads:[~2018-08-02 12:50 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-20 16:04 [PATCH bpf] xdp: add NULL pointer check in __xdp_return() Taehee Yoo
2018-07-20 17:18 ` Martin KaFai Lau
2018-07-20 20:05   ` Jakub Kicinski
2018-07-23  9:39     ` Björn Töpel
2018-07-23 19:58       ` Jakub Kicinski
2018-07-26 12:13         ` Björn Töpel
2018-07-26 18:47           ` Jakub Kicinski
2018-07-21 12:56   ` Taehee Yoo
2018-07-23  9:41     ` Björn Töpel
2018-07-23 13:21       ` Taehee Yoo
2018-08-01 14:14       ` Jesper Dangaard Brouer
2018-08-01 14:43         ` Björn Töpel
2018-08-01 20:25           ` Daniel Borkmann
2018-08-02 10:59             ` Björn Töpel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.