diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/input.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index bf612d954d41..2e4a8646dbc3 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -249,6 +249,19 @@ int sctp_rcv(struct sk_buff *skb) | |||
249 | */ | 249 | */ |
250 | sctp_bh_lock_sock(sk); | 250 | sctp_bh_lock_sock(sk); |
251 | 251 | ||
252 | if (sk != rcvr->sk) { | ||
253 | /* Our cached sk is different from the rcvr->sk. This is | ||
254 | * because migrate()/accept() may have moved the association | ||
255 | * to a new socket and released all the sockets. So now we | ||
256 | * are holding a lock on the old socket while the user may | ||
257 | * be doing something with the new socket. Switch our veiw | ||
258 | * of the current sk. | ||
259 | */ | ||
260 | sctp_bh_unlock_sock(sk); | ||
261 | sk = rcvr->sk; | ||
262 | sctp_bh_lock_sock(sk); | ||
263 | } | ||
264 | |||
252 | if (sock_owned_by_user(sk)) { | 265 | if (sock_owned_by_user(sk)) { |
253 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); | 266 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); |
254 | sctp_add_backlog(sk, skb); | 267 | sctp_add_backlog(sk, skb); |