forked from mirrors/linux
		
	tcp: fix potential double free issue for fastopen_req
tp->fastopen_req could potentially be double freed if a malicious
user does the following:
1. Enable TCP_FASTOPEN_CONNECT sockopt and do a connect() on the socket.
2. Call connect() with AF_UNSPEC to disconnect the socket.
3. Make this socket a listening socket by calling listen().
4. Accept incoming connections and generate child sockets. All child
   sockets will get a copy of the pointer of fastopen_req.
5. Call close() on all sockets. fastopen_req will get freed multiple
   times.
Fixes: 19f6d3f3c8 ("net/tcp-fastopen: Add new API support")
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Wei Wang <weiwan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									94352d4509
								
							
						
					
					
						commit
						7db92362d2
					
				
					 1 changed files with 12 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -1110,9 +1110,14 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 | 
			
		|||
	flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
 | 
			
		||||
	err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
 | 
			
		||||
				    msg->msg_namelen, flags, 1);
 | 
			
		||||
	inet->defer_connect = 0;
 | 
			
		||||
	*copied = tp->fastopen_req->copied;
 | 
			
		||||
	tcp_free_fastopen_req(tp);
 | 
			
		||||
	/* fastopen_req could already be freed in __inet_stream_connect
 | 
			
		||||
	 * if the connection times out or gets rst
 | 
			
		||||
	 */
 | 
			
		||||
	if (tp->fastopen_req) {
 | 
			
		||||
		*copied = tp->fastopen_req->copied;
 | 
			
		||||
		tcp_free_fastopen_req(tp);
 | 
			
		||||
		inet->defer_connect = 0;
 | 
			
		||||
	}
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2318,6 +2323,10 @@ int tcp_disconnect(struct sock *sk, int flags)
 | 
			
		|||
	memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
 | 
			
		||||
	__sk_dst_reset(sk);
 | 
			
		||||
 | 
			
		||||
	/* Clean up fastopen related fields */
 | 
			
		||||
	tcp_free_fastopen_req(tp);
 | 
			
		||||
	inet->defer_connect = 0;
 | 
			
		||||
 | 
			
		||||
	WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
 | 
			
		||||
 | 
			
		||||
	sk->sk_error_report(sk);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue