|
@@ -249,6 +249,19 @@ int sctp_rcv(struct sk_buff *skb)
|
|
*/
|
|
*/
|
|
sctp_bh_lock_sock(sk);
|
|
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)) {
|
|
if (sock_owned_by_user(sk)) {
|
|
SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
|
|
SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
|
|
sctp_add_backlog(sk, skb);
|
|
sctp_add_backlog(sk, skb);
|