forked from mirrors/linux
		
	tcp: fix req->saved_syn race
For the reasons explained in commitce1050089c("tcp/dccp: fix ireq->pktopts race"), we need to make sure we do not access req->saved_syn unless we own the request sock. This fixes races for listeners using TCP_SAVE_SYN option. Fixes:e994b2f0fb("tcp: do not lock listener to process SYN packets") Fixes:079096f103("tcp/dccp: install syn_recv requests into ehash table") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Ying Cai <ycai@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									428ad1bc6d
								
							
						
					
					
						commit
						805c4bc057
					
				
					 4 changed files with 21 additions and 11 deletions
				
			
		|  | @ -397,6 +397,13 @@ static inline void fastopen_queue_tune(struct sock *sk, int backlog) | |||
| 	queue->fastopenq.max_qlen = min_t(unsigned int, backlog, somaxconn); | ||||
| } | ||||
| 
 | ||||
| static inline void tcp_move_syn(struct tcp_sock *tp, | ||||
| 				struct request_sock *req) | ||||
| { | ||||
| 	tp->saved_syn = req->saved_syn; | ||||
| 	req->saved_syn = NULL; | ||||
| } | ||||
| 
 | ||||
| static inline void tcp_saved_syn_free(struct tcp_sock *tp) | ||||
| { | ||||
| 	kfree(tp->saved_syn); | ||||
|  |  | |||
|  | @ -1326,6 +1326,8 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, | |||
| 	if (__inet_inherit_port(sk, newsk) < 0) | ||||
| 		goto put_and_exit; | ||||
| 	*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); | ||||
| 	if (*own_req) | ||||
| 		tcp_move_syn(newtp, req_unhash); | ||||
| 
 | ||||
| 	return newsk; | ||||
| 
 | ||||
|  |  | |||
|  | @ -551,9 +551,6 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, | |||
| 		newtp->rack.mstamp.v64 = 0; | ||||
| 		newtp->rack.advanced = 0; | ||||
| 
 | ||||
| 		newtp->saved_syn = req->saved_syn; | ||||
| 		req->saved_syn = NULL; | ||||
| 
 | ||||
| 		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); | ||||
| 	} | ||||
| 	return newsk; | ||||
|  |  | |||
|  | @ -1140,8 +1140,11 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
| 		goto out; | ||||
| 	} | ||||
| 	*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); | ||||
| 	if (*own_req) { | ||||
| 		tcp_move_syn(newtp, req_unhash); | ||||
| 
 | ||||
| 		/* Clone pktoptions received with SYN, if we own the req */ | ||||
| 	if (*own_req && ireq->pktopts) { | ||||
| 		if (ireq->pktopts) { | ||||
| 			newnp->pktoptions = skb_clone(ireq->pktopts, | ||||
| 						      sk_gfp_atomic(sk, GFP_ATOMIC)); | ||||
| 			consume_skb(ireq->pktopts); | ||||
|  | @ -1149,6 +1152,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
| 			if (newnp->pktoptions) | ||||
| 				skb_set_owner_r(newnp->pktoptions, newsk); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return newsk; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Eric Dumazet
						Eric Dumazet