From: Vlad Yasevich <vyasevich@gmail.com>
To: mleitner@redhat.com
Cc: Xin Long <lucien.xin@gmail.com>,
network dev <netdev@vger.kernel.org>,
linux-sctp@vger.kernel.org, vyasevic@redhat.com,
daniel@iogearbox.net, davem@davemloft.net
Subject: Re: [PATCH net-next 2/5] sctp: apply rhashtable api to send/recv path
Date: Mon, 11 Jan 2016 10:00:13 -0500 [thread overview]
Message-ID: <5693C37D.4020704@gmail.com> (raw)
In-Reply-To: <20160106174236.GB6061@mrl.redhat.com>
On 01/06/2016 12:42 PM, mleitner@redhat.com wrote:
> On Tue, Jan 05, 2016 at 02:07:11PM -0500, Vlad Yasevich wrote:
>> On 12/30/2015 10:50 AM, Xin Long wrote:
>>> apply lookup apis to two functions, for __sctp_endpoint_lookup_assoc
>>> and __sctp_lookup_association, it's invoked in the protection of sock
>>> lock, it will be safe, but sctp_lookup_association need to call
>>> rcu_read_lock() and to detect the t->dead to protect it.
>>>
>>> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>>> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>>> ---
>>> net/sctp/associola.c | 5 +++++
>>> net/sctp/endpointola.c | 35 ++++++++---------------------------
>>> net/sctp/input.c | 39 ++++++++++-----------------------------
>>> net/sctp/protocol.c | 6 ++++++
>>> 4 files changed, 29 insertions(+), 56 deletions(-)
>>>
>>> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
>>> index 559afd0..2bf8ec9 100644
>>> --- a/net/sctp/associola.c
>>> +++ b/net/sctp/associola.c
>>> @@ -383,6 +383,7 @@ void sctp_association_free(struct sctp_association *asoc)
>>> list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
>>> transport = list_entry(pos, struct sctp_transport, transports);
>>> list_del_rcu(pos);
>>> + sctp_unhash_transport(transport);
>>> sctp_transport_free(transport);
>>> }
>>>
>>> @@ -500,6 +501,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
>>>
>>> /* Remove this peer from the list. */
>>> list_del_rcu(&peer->transports);
>>> + /* Remove this peer from the transport hashtable */
>>> + sctp_unhash_transport(peer);
>>>
>>> /* Get the first transport of asoc. */
>>> pos = asoc->peer.transport_addr_list.next;
>>> @@ -699,6 +702,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
>>> /* Attach the remote transport to our asoc. */
>>> list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
>>> asoc->peer.transport_count++;
>>> + /* Add this peer into the transport hashtable */
>>> + sctp_hash_transport(peer);
>>
>> This is actually problematic. The issue is that transports are unhashed when removed.
>> however, transport removal happens after the association has been declared dead and
>> should have been removed from the hash and marked unreachable.
>>
>> As a result, with the code above, you can now find and return a dead association.
>> Checking for 'dead' state is racy.
>
> Mind elaborating why you think this is racy? (More below)
>
>> The best solution I've come up with is to hash the transports in sctp_hash_established()
>> and clean-up in __sctp_unhash_established(), and then handle ADD-IP case separately.
>
> The idea was exactly the opposite :) to avoid such calls. All calls to
> sctp_unhash_established() were followed by sctp_association_free(), and
> vice-versa, indicating that it could (and probably should) be embedded
> in sctp_association_free() itself.
Oh, I understand the idea and the desire...
>
> No extra locking was taken other than to protect the hash table itself,
> which now is different. The check against ->dead should be quite as
> effective as prior implementation, as it's marked dead quite early in
> sctp_association_free(). We could do it a bit earlier if necessary.
>
> Please correct if I'm wrong, but AFAIU rhashtable, it's possible to
> return an element that is being removed by another CPU, due to RCU
> usage. If that's right, the early removal is not enough anymore and
> only a check like the the ->dead one can protect it then. Hmmm we
> probably should use something more atomic there then.
So, I've been looking at this problem trying to figure out what specifically
triggers this race. It comes down to what seems like a small change in
in __sctp_lookup_association(), but it is significant. The old code
took a ref on the found association while under a read lock for the hash bucket.
This guaranteed that the association still existed in the hash, if even though
it was in the process of being removed, we were guaranteed to have a proper ref
on it. With the new code, the guarantee is gone. It looks like we
illegally take a ref on the association without any requisite protections. As
a result, the transport may have been unhashed and the association is going through
the destroy phase, when we bump the ref (technically from 0).
I think what Herbert recently suggested may help us here. He suggested hashing a
list object and linking transports to it. I am thinking right now that f we take it
one step further and put a lock inside that list object that protects the list,
then we might be able to solve this race.
>
>> The above would also remove the necessity to check for temporary associations, since they
>> should never be hashed.
>
> Agreed. We could add a simple
> if (t->asoc->temp)
> return;
> to the new sctp_hash/unhash_transport to fix that.
Good idea.
-vlad
>
> Marcelo
>
next prev parent reply other threads:[~2016-01-11 15:00 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-30 15:50 [PATCH net-next 0/5] sctp: use transport hashtable to replace association's with rhashtable Xin Long
2015-12-30 15:50 ` [PATCH net-next 1/5] sctp: add the rhashtable apis for sctp global transport hashtable Xin Long
2015-12-30 15:50 ` [PATCH net-next 2/5] sctp: apply rhashtable api to send/recv path Xin Long
2015-12-30 15:50 ` [PATCH net-next 3/5] sctp: apply rhashtable api to sctp procfs Xin Long
2015-12-30 15:50 ` [PATCH net-next 4/5] sctp: drop the old assoc hashtable of sctp Xin Long
2015-12-30 15:50 ` [PATCH net-next 5/5] sctp: remove the local_bh_disable/enable in sctp_endpoint_lookup_assoc Xin Long
2016-01-05 19:07 ` [PATCH net-next 2/5] sctp: apply rhashtable api to send/recv path Vlad Yasevich
2016-01-06 16:18 ` Xin Long
2016-01-06 17:42 ` mleitner
2016-01-11 15:00 ` Vlad Yasevich [this message]
2015-12-30 16:57 ` [PATCH net-next 1/5] sctp: add the rhashtable apis for sctp global transport hashtable Eric Dumazet
2015-12-30 17:50 ` David Miller
2016-01-11 9:32 ` Herbert Xu
2016-01-11 16:33 ` Marcelo Ricardo Leitner
2016-01-11 18:08 ` Vlad Yasevich
2016-01-11 18:19 ` Marcelo Ricardo Leitner
2015-12-30 17:41 ` Marcelo Ricardo Leitner
2016-01-05 10:10 ` Xin Long
2016-01-11 9:22 ` Herbert Xu
2016-01-05 18:38 ` Vlad Yasevich
2016-01-06 17:01 ` Xin Long
2016-01-06 18:19 ` Marcelo Ricardo Leitner
2016-01-07 17:23 ` Marcelo Ricardo Leitner
2016-01-07 20:28 ` Vlad Yasevich
2016-01-11 9:30 ` Herbert Xu
2016-01-11 16:00 ` mleitner
2016-01-11 17:20 ` Vlad Yasevich
2016-01-11 18:09 ` mleitner
2016-01-11 21:35 ` David Miller
2016-01-11 21:31 ` David Miller
2015-12-30 17:19 ` [PATCH net-next 0/5] sctp: use transport hashtable to replace association's with rhashtable Eric Dumazet
2015-12-30 17:32 ` Marcelo Ricardo Leitner
2015-12-30 19:11 ` Eric Dumazet
2015-12-30 20:44 ` David Miller
2015-12-30 21:57 ` Eric Dumazet
2015-12-30 22:29 ` Marcelo Ricardo Leitner
2015-12-30 17:52 ` David Miller
2015-12-30 19:03 ` Eric Dumazet
2015-12-30 20:40 ` David Miller
2016-01-04 22:30 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5693C37D.4020704@gmail.com \
--to=vyasevich@gmail.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=linux-sctp@vger.kernel.org \
--cc=lucien.xin@gmail.com \
--cc=mleitner@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=vyasevic@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).