goto out_up;
 }
 
+static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
+{
+       if (unlikely(sk1 == sk2) || !sk2) {
+               unix_state_lock(sk1);
+               return;
+       }
+       if (sk1 < sk2) {
+               unix_state_lock(sk1);
+               unix_state_lock_nested(sk2);
+       } else {
+               unix_state_lock(sk2);
+               unix_state_lock_nested(sk1);
+       }
+}
+
+static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
+{
+       if (unlikely(sk1 == sk2) || !sk2) {
+               unix_state_unlock(sk1);
+               return;
+       }
+       unix_state_unlock(sk1);
+       unix_state_unlock(sk2);
+}
+
 static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
                              int alen, int flags)
 {
                    !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
                        goto out;
 
+restart:
                other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
                if (!other)
                        goto out;
 
-               unix_state_lock(sk);
+               unix_state_double_lock(sk, other);
+
+               /* Apparently VFS overslept socket death. Retry. */
+               if (sock_flag(other, SOCK_DEAD)) {
+                       unix_state_double_unlock(sk, other);
+                       sock_put(other);
+                       goto restart;
+               }
 
                err = -EPERM;
                if (!unix_may_send(sk, other))
                 *      1003.1g breaking connected state with AF_UNSPEC
                 */
                other = NULL;
-               unix_state_lock(sk);
+               unix_state_double_lock(sk, other);
        }
 
        /*
        if (unix_peer(sk)) {
                struct sock *old_peer = unix_peer(sk);
                unix_peer(sk)=other;
-               unix_state_unlock(sk);
+               unix_state_double_unlock(sk, other);
 
                if (other != old_peer)
                        unix_dgram_disconnected(sk, old_peer);
                sock_put(old_peer);
        } else {
                unix_peer(sk)=other;
-               unix_state_unlock(sk);
+               unix_state_double_unlock(sk, other);
        }
        return 0;
 
 out_unlock:
-       unix_state_unlock(sk);
+       unix_state_double_unlock(sk, other);
        sock_put(other);
 out:
        return err;