Skip to content

Commit

Permalink
sctp: Fix another socket race during accept/peeloff
Browse files Browse the repository at this point in the history
There is a race between sctp_rcv() and sctp_accept() where we
have moved the association from the listening socket to the
accepted socket, but sctp_rcv() processing cached the old
socket and continues to use it.

The easy solution is to check for the socket mismatch once we've
grabed the socket lock.  If we hit a mis-match, that means
that were are currently holding the lock on the listening socket,
but the association is refrencing a newly accepted socket.  We need
to drop the lock on the old socket and grab the lock on the new one.

A more proper solution might be to create accepted sockets when
the new association is established, similar to TCP.  That would
eliminate the race for 1-to-1 style sockets, but it would still
existing for 1-to-many sockets where a user wished to peeloff an
association.  For now, we'll live with this easy solution as
it addresses the problem.

Reported-by: Michal Hocko <mhocko@suse.cz>
Reported-by: Karsten Keil <kkeil@suse.de>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vlad Yasevich authored and davem330 committed Jan 22, 2009
1 parent 759af00 commit ae53b5b
Showing 1 changed file with 13 additions and 0 deletions.
13 changes: 13 additions & 0 deletions net/sctp/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,19 @@ int sctp_rcv(struct sk_buff *skb)
*/
sctp_bh_lock_sock(sk);

if (sk != rcvr->sk) {
/* Our cached sk is different from the rcvr->sk. This is
* because migrate()/accept() may have moved the association
* to a new socket and released all the sockets. So now we
* are holding a lock on the old socket while the user may
* be doing something with the new socket. Switch our veiw
* of the current sk.
*/
sctp_bh_unlock_sock(sk);
sk = rcvr->sk;
sctp_bh_lock_sock(sk);
}

if (sock_owned_by_user(sk)) {
SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
sctp_add_backlog(sk, skb);
Expand Down

0 comments on commit ae53b5b

Please sign in to comment.