OSDN Git Service

net: ipv4: Fix race in tcp_v4_nuke_addr().
authorRobert Love <rlove@google.com>
Thu, 8 Oct 2009 19:06:22 +0000 (15:06 -0400)
committerDima Zavin <dima@android.com>
Thu, 8 Oct 2009 19:35:08 +0000 (12:35 -0700)
To fix a recursive deadlock in 2.6.29, we stopped holding the hash table lock
across tcp_done() calls. This fixed the deadlock, but introduced a race where
the socket could die or change state.

Fix: Before unlocking the hash table, we grab a reference to the socket. We
can then unlock the hash table without risk of the socket going away. We then
lock the socket, which is safe because it is pinned. We can then call
tcp_done() without recursive deadlock and without race. Upon return, we unlock
the socket and then unpin it, killing it.

Change-Id: Idcdae072b48238b01bdbc8823b60310f1976e045
Signed-off-by: Robert Love <rlove@google.com>
Acked-by: Dima Zavin <dima@android.com>
net/ipv4/tcp_ipv4.c

index b04e5ad..ad0463d 100644 (file)
@@ -1879,8 +1879,14 @@ restart:
 
                        sk->sk_err = ETIMEDOUT;
                        sk->sk_error_report(sk);
+
+                       sock_hold(sk);
                        spin_unlock_bh(lock);
+                       bh_lock_sock(sk);
                        tcp_done(sk);
+                       bh_unlock_sock(sk);
+                       sock_put(sk);
+
                        goto restart;
                }
                spin_unlock_bh(lock);