@@ -877,7 +877,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
877877
878878 err = ip_build_and_send_pkt (skb , sk , ireq -> ir_loc_addr ,
879879 ireq -> ir_rmt_addr ,
880- ireq -> opt );
880+ rcu_dereference ( ireq -> ireq_opt ) );
881881 err = net_xmit_eval (err );
882882 }
883883
@@ -889,7 +889,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
889889 */
890890static void tcp_v4_reqsk_destructor (struct request_sock * req )
891891{
892- kfree (inet_rsk (req )-> opt );
892+ kfree (rcu_dereference_protected ( inet_rsk (req )-> ireq_opt , 1 ) );
893893}
894894
895895#ifdef CONFIG_TCP_MD5SIG
@@ -1265,10 +1265,11 @@ static void tcp_v4_init_req(struct request_sock *req,
12651265 struct sk_buff * skb )
12661266{
12671267 struct inet_request_sock * ireq = inet_rsk (req );
1268+ struct net * net = sock_net (sk_listener );
12681269
12691270 sk_rcv_saddr_set (req_to_sk (req ), ip_hdr (skb )-> daddr );
12701271 sk_daddr_set (req_to_sk (req ), ip_hdr (skb )-> saddr );
1271- ireq -> opt = tcp_v4_save_options (sock_net ( sk_listener ) , skb );
1272+ RCU_INIT_POINTER ( ireq -> ireq_opt , tcp_v4_save_options (net , skb ) );
12721273}
12731274
12741275static struct dst_entry * tcp_v4_route_req (const struct sock * sk ,
@@ -1355,10 +1356,9 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
13551356 sk_daddr_set (newsk , ireq -> ir_rmt_addr );
13561357 sk_rcv_saddr_set (newsk , ireq -> ir_loc_addr );
13571358 newsk -> sk_bound_dev_if = ireq -> ir_iif ;
1358- newinet -> inet_saddr = ireq -> ir_loc_addr ;
1359- inet_opt = ireq -> opt ;
1360- rcu_assign_pointer (newinet -> inet_opt , inet_opt );
1361- ireq -> opt = NULL ;
1359+ newinet -> inet_saddr = ireq -> ir_loc_addr ;
1360+ inet_opt = rcu_dereference (ireq -> ireq_opt );
1361+ RCU_INIT_POINTER (newinet -> inet_opt , inet_opt );
13621362 newinet -> mc_index = inet_iif (skb );
13631363 newinet -> mc_ttl = ip_hdr (skb )-> ttl ;
13641364 newinet -> rcv_tos = ip_hdr (skb )-> tos ;
@@ -1403,9 +1403,12 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
14031403 if (__inet_inherit_port (sk , newsk ) < 0 )
14041404 goto put_and_exit ;
14051405 * own_req = inet_ehash_nolisten (newsk , req_to_sk (req_unhash ));
1406- if (* own_req )
1406+ if (likely ( * own_req )) {
14071407 tcp_move_syn (newtp , req );
1408-
1408+ ireq -> ireq_opt = NULL ;
1409+ } else {
1410+ newinet -> inet_opt = NULL ;
1411+ }
14091412 return newsk ;
14101413
14111414exit_overflow :
@@ -1416,6 +1419,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
14161419 tcp_listendrop (sk );
14171420 return NULL ;
14181421put_and_exit :
1422+ newinet -> inet_opt = NULL ;
14191423 inet_csk_prepare_forced_close (newsk );
14201424 tcp_done (newsk );
14211425 goto exit ;
0 commit comments