netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes
@ 2017-02-28  4:41 Xin Long
  2017-02-28 14:23 ` Neil Horman
  2017-03-01 17:51 ` David Miller
  0 siblings, 2 replies; 5+ messages in thread
From: Xin Long @ 2017-02-28  4:41 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich,
	Andrey Konovalov

Commit cd2b70875058 ("sctp: check duplicate node before inserting a
new transport") called rhltable_lookup() to check for the duplicate
transport node in transport rhashtable.

But rhltable_lookup() doesn't call rcu_read_lock inside, it could cause
a use-after-free issue if it tries to dereference the node that another
cpu has freed it. Note that sock lock can not avoid this as it is per
sock.

This patch is to fix it by calling rcu_read_lock before checking for
duplicate transport nodes.

Fixes: cd2b70875058 ("sctp: check duplicate node before inserting a new transport")
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/sctp/input.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/sctp/input.c b/net/sctp/input.c
index fc45896..2a28ab2 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -884,14 +884,17 @@ int sctp_hash_transport(struct sctp_transport *t)
 	arg.paddr = &t->ipaddr;
 	arg.lport = htons(t->asoc->base.bind_addr.port);
 
+	rcu_read_lock();
 	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
 			       sctp_hash_params);
 
 	rhl_for_each_entry_rcu(transport, tmp, list, node)
 		if (transport->asoc->ep == t->asoc->ep) {
+			rcu_read_unlock();
 			err = -EEXIST;
 			goto out;
 		}
+	rcu_read_unlock();
 
 	err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
 				  &t->node, sctp_hash_params);
-- 
2.1.0

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

* Re: [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes
  2017-02-28  4:41 [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes Xin Long
@ 2017-02-28 14:23 ` Neil Horman
  2017-02-28 14:37   ` Xin Long
  2017-03-01 17:51 ` David Miller
  1 sibling, 1 reply; 5+ messages in thread
From: Neil Horman @ 2017-02-28 14:23 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, Andrey Konovalov

On Tue, Feb 28, 2017 at 12:41:29PM +0800, Xin Long wrote:
> Commit cd2b70875058 ("sctp: check duplicate node before inserting a
> new transport") called rhltable_lookup() to check for the duplicate
> transport node in transport rhashtable.
> 
> But rhltable_lookup() doesn't call rcu_read_lock inside, it could cause
> a use-after-free issue if it tries to dereference the node that another
> cpu has freed it. Note that sock lock can not avoid this as it is per
> sock.
> 
> This patch is to fix it by calling rcu_read_lock before checking for
> duplicate transport nodes.
> 
> Fixes: cd2b70875058 ("sctp: check duplicate node before inserting a new transport")
> Reported-by: Andrey Konovalov <andreyknvl@google.com>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  net/sctp/input.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index fc45896..2a28ab2 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -884,14 +884,17 @@ int sctp_hash_transport(struct sctp_transport *t)
>  	arg.paddr = &t->ipaddr;
>  	arg.lport = htons(t->asoc->base.bind_addr.port);
>  
> +	rcu_read_lock();
>  	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
>  			       sctp_hash_params);
>  
>  	rhl_for_each_entry_rcu(transport, tmp, list, node)
>  		if (transport->asoc->ep == t->asoc->ep) {
> +			rcu_read_unlock();
>  			err = -EEXIST;
>  			goto out;
>  		}
> +	rcu_read_unlock();
>  
>  	err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
>  				  &t->node, sctp_hash_params);
> -- 
> 2.1.0
> 
> 

Hmm, rhltable_insert_key I think returns a pointer to the existing object in the
hash table if there is a collision (according to the _rhashtable_insert_fast
description).  Wouldn't it be better to eliminate the rhl_for_each_entry_rcu
entirely, and just check the returned pointer from rhltable_insert_key?

Neil

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

* Re: [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes
  2017-02-28 14:23 ` Neil Horman
@ 2017-02-28 14:37   ` Xin Long
  2017-02-28 14:58     ` Neil Horman
  0 siblings, 1 reply; 5+ messages in thread
From: Xin Long @ 2017-02-28 14:37 UTC (permalink / raw)
  To: Neil Horman
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, Andrey Konovalov

On Tue, Feb 28, 2017 at 10:23 PM, Neil Horman <nhorman@tuxdriver.com> wrote:
> On Tue, Feb 28, 2017 at 12:41:29PM +0800, Xin Long wrote:
>> Commit cd2b70875058 ("sctp: check duplicate node before inserting a
>> new transport") called rhltable_lookup() to check for the duplicate
>> transport node in transport rhashtable.
>>
>> But rhltable_lookup() doesn't call rcu_read_lock inside, it could cause
>> a use-after-free issue if it tries to dereference the node that another
>> cpu has freed it. Note that sock lock can not avoid this as it is per
>> sock.
>>
>> This patch is to fix it by calling rcu_read_lock before checking for
>> duplicate transport nodes.
>>
>> Fixes: cd2b70875058 ("sctp: check duplicate node before inserting a new transport")
>> Reported-by: Andrey Konovalov <andreyknvl@google.com>
>> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>> ---
>>  net/sctp/input.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/net/sctp/input.c b/net/sctp/input.c
>> index fc45896..2a28ab2 100644
>> --- a/net/sctp/input.c
>> +++ b/net/sctp/input.c
>> @@ -884,14 +884,17 @@ int sctp_hash_transport(struct sctp_transport *t)
>>       arg.paddr = &t->ipaddr;
>>       arg.lport = htons(t->asoc->base.bind_addr.port);
>>
>> +     rcu_read_lock();
>>       list = rhltable_lookup(&sctp_transport_hashtable, &arg,
>>                              sctp_hash_params);
>>
>>       rhl_for_each_entry_rcu(transport, tmp, list, node)
>>               if (transport->asoc->ep == t->asoc->ep) {
>> +                     rcu_read_unlock();
>>                       err = -EEXIST;
>>                       goto out;
>>               }
>> +     rcu_read_unlock();
>>
>>       err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
>>                                 &t->node, sctp_hash_params);
>> --
>> 2.1.0
>>
>>
>
> Hmm, rhltable_insert_key I think returns a pointer to the existing object in the
> hash table if there is a collision (according to the _rhashtable_insert_fast
> description).  Wouldn't it be better to eliminate the rhl_for_each_entry_rcu
> entirely, and just check the returned pointer from rhltable_insert_key?
I wish it could do it, but rhlist(rhltable_insert_key) allows duplicate
node to be inserted, it will never return the existing node. :(

I guess the codes you saw are only for the old rhashtable api (they are
together with rhlist codes in __rhashtable_insert_fast).

Thanks

>
> Neil
>

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

* Re: [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes
  2017-02-28 14:37   ` Xin Long
@ 2017-02-28 14:58     ` Neil Horman
  0 siblings, 0 replies; 5+ messages in thread
From: Neil Horman @ 2017-02-28 14:58 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, Andrey Konovalov

On Tue, Feb 28, 2017 at 10:37:35PM +0800, Xin Long wrote:
> On Tue, Feb 28, 2017 at 10:23 PM, Neil Horman <nhorman@tuxdriver.com> wrote:
> > On Tue, Feb 28, 2017 at 12:41:29PM +0800, Xin Long wrote:
> >> Commit cd2b70875058 ("sctp: check duplicate node before inserting a
> >> new transport") called rhltable_lookup() to check for the duplicate
> >> transport node in transport rhashtable.
> >>
> >> But rhltable_lookup() doesn't call rcu_read_lock inside, it could cause
> >> a use-after-free issue if it tries to dereference the node that another
> >> cpu has freed it. Note that sock lock can not avoid this as it is per
> >> sock.
> >>
> >> This patch is to fix it by calling rcu_read_lock before checking for
> >> duplicate transport nodes.
> >>
> >> Fixes: cd2b70875058 ("sctp: check duplicate node before inserting a new transport")
> >> Reported-by: Andrey Konovalov <andreyknvl@google.com>
> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> >> ---
> >>  net/sctp/input.c | 3 +++
> >>  1 file changed, 3 insertions(+)
> >>
> >> diff --git a/net/sctp/input.c b/net/sctp/input.c
> >> index fc45896..2a28ab2 100644
> >> --- a/net/sctp/input.c
> >> +++ b/net/sctp/input.c
> >> @@ -884,14 +884,17 @@ int sctp_hash_transport(struct sctp_transport *t)
> >>       arg.paddr = &t->ipaddr;
> >>       arg.lport = htons(t->asoc->base.bind_addr.port);
> >>
> >> +     rcu_read_lock();
> >>       list = rhltable_lookup(&sctp_transport_hashtable, &arg,
> >>                              sctp_hash_params);
> >>
> >>       rhl_for_each_entry_rcu(transport, tmp, list, node)
> >>               if (transport->asoc->ep == t->asoc->ep) {
> >> +                     rcu_read_unlock();
> >>                       err = -EEXIST;
> >>                       goto out;
> >>               }
> >> +     rcu_read_unlock();
> >>
> >>       err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
> >>                                 &t->node, sctp_hash_params);
> >> --
> >> 2.1.0
> >>
> >>
> >
> > Hmm, rhltable_insert_key I think returns a pointer to the existing object in the
> > hash table if there is a collision (according to the _rhashtable_insert_fast
> > description).  Wouldn't it be better to eliminate the rhl_for_each_entry_rcu
> > entirely, and just check the returned pointer from rhltable_insert_key?
> I wish it could do it, but rhlist(rhltable_insert_key) allows duplicate
> node to be inserted, it will never return the existing node. :(
> 
> I guess the codes you saw are only for the old rhashtable api (they are
> together with rhlist codes in __rhashtable_insert_fast).
> 
> Thanks
> 
yeah, you're right, can't do it that way

Acked-by: Neil Horman <nhorman@tuxdriver.com>

> >
> > Neil
> >
> 

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

* Re: [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes
  2017-02-28  4:41 [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes Xin Long
  2017-02-28 14:23 ` Neil Horman
@ 2017-03-01 17:51 ` David Miller
  1 sibling, 0 replies; 5+ messages in thread
From: David Miller @ 2017-03-01 17:51 UTC (permalink / raw)
  To: lucien.xin
  Cc: netdev, linux-sctp, marcelo.leitner, nhorman, vyasevich, andreyknvl

From: Xin Long <lucien.xin@gmail.com>
Date: Tue, 28 Feb 2017 12:41:29 +0800

> Commit cd2b70875058 ("sctp: check duplicate node before inserting a
> new transport") called rhltable_lookup() to check for the duplicate
> transport node in transport rhashtable.
> 
> But rhltable_lookup() doesn't call rcu_read_lock inside, it could cause
> a use-after-free issue if it tries to dereference the node that another
> cpu has freed it. Note that sock lock can not avoid this as it is per
> sock.
> 
> This patch is to fix it by calling rcu_read_lock before checking for
> duplicate transport nodes.
> 
> Fixes: cd2b70875058 ("sctp: check duplicate node before inserting a new transport")
> Reported-by: Andrey Konovalov <andreyknvl@google.com>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Applied.

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

end of thread, other threads:[~2017-03-01 17:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-28  4:41 [PATCH net] sctp: call rcu_read_lock before checking for duplicate transport nodes Xin Long
2017-02-28 14:23 ` Neil Horman
2017-02-28 14:37   ` Xin Long
2017-02-28 14:58     ` Neil Horman
2017-03-01 17:51 ` David Miller

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