diff options
Diffstat (limited to 'net/ipv4/tcp_timer.c')
| -rw-r--r-- | net/ipv4/tcp_timer.c | 15 | 
1 files changed, 15 insertions, 0 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 968fda198376..388158c9d9f6 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -48,11 +48,19 @@ static void tcp_write_err(struct sock *sk)   *  to prevent DoS attacks. It is called when a retransmission timeout   *  or zero probe timeout occurs on orphaned socket.   * + *  Also close if our net namespace is exiting; in that case there is no + *  hope of ever communicating again since all netns interfaces are already + *  down (or about to be down), and we need to release our dst references, + *  which have been moved to the netns loopback interface, so the namespace + *  can finish exiting.  This condition is only possible if we are a kernel + *  socket, as those do not hold references to the namespace. + *   *  Criteria is still not confirmed experimentally and may change.   *  We kill the socket, if:   *  1. If number of orphaned sockets exceeds an administratively configured   *     limit.   *  2. If we have strong memory pressure. + *  3. If our net namespace is exiting.   */  static int tcp_out_of_resources(struct sock *sk, bool do_reset)  { @@ -81,6 +89,13 @@ static int tcp_out_of_resources(struct sock *sk, bool do_reset)  		__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY);  		return 1;  	} + +	if (!check_net(sock_net(sk))) { +		/* Not possible to send reset; just close */ +		tcp_done(sk); +		return 1; +	} +  	return 0;  }  | 
