aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2018-10-02 15:35:05 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-02 18:52:12 -0400
commit2ab2ddd301a22ca3c5f0b743593e4ad2953dfa53 (patch)
tree3ec72a50a6be78a4bc8eb73d8c9bd14df798aa26
parentff58e2df62ce29d0552278c290ae494b30fe0c6f (diff)
inet: make sure to grab rcu_read_lock before using ireq->ireq_opt
Timer handlers do not imply rcu_read_lock(), so my recent fix triggered a LOCKDEP warning when SYNACK is retransmit. Lets add rcu_read_lock()/rcu_read_unlock() pairs around ireq->ireq_opt usages instead of guessing what is done by callers, since it is not worth the pain. Get rid of ireq_opt_deref() helper since it hides the logic without real benefit, since it is now a standard rcu_dereference(). Fixes: 1ad98e9d1bdf ("tcp/dccp: fix lockdep issue when SYN is backlogged") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/inet_sock.h5
-rw-r--r--net/dccp/ipv4.c4
-rw-r--r--net/ipv4/inet_connection_sock.c5
-rw-r--r--net/ipv4/tcp_ipv4.c4
4 files changed, 10 insertions, 8 deletions
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index a8cd5cf9ff5b..a80fd0ac4563 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -130,11 +130,6 @@ static inline int inet_request_bound_dev_if(const struct sock *sk,
130 return sk->sk_bound_dev_if; 130 return sk->sk_bound_dev_if;
131} 131}
132 132
133static inline struct ip_options_rcu *ireq_opt_deref(const struct inet_request_sock *ireq)
134{
135 return rcu_dereference(ireq->ireq_opt);
136}
137
138struct inet_cork { 133struct inet_cork {
139 unsigned int flags; 134 unsigned int flags;
140 __be32 addr; 135 __be32 addr;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index b08feb219b44..8e08cea6f178 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -493,9 +493,11 @@ static int dccp_v4_send_response(const struct sock *sk, struct request_sock *req
493 493
494 dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->ir_loc_addr, 494 dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->ir_loc_addr,
495 ireq->ir_rmt_addr); 495 ireq->ir_rmt_addr);
496 rcu_read_lock();
496 err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, 497 err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
497 ireq->ir_rmt_addr, 498 ireq->ir_rmt_addr,
498 ireq_opt_deref(ireq)); 499 rcu_dereference(ireq->ireq_opt));
500 rcu_read_unlock();
499 err = net_xmit_eval(err); 501 err = net_xmit_eval(err);
500 } 502 }
501 503
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index dfd5009f96ef..15e7f7915a21 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -544,7 +544,8 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
544 struct ip_options_rcu *opt; 544 struct ip_options_rcu *opt;
545 struct rtable *rt; 545 struct rtable *rt;
546 546
547 opt = ireq_opt_deref(ireq); 547 rcu_read_lock();
548 opt = rcu_dereference(ireq->ireq_opt);
548 549
549 flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark, 550 flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark,
550 RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, 551 RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
@@ -558,11 +559,13 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
558 goto no_route; 559 goto no_route;
559 if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) 560 if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
560 goto route_err; 561 goto route_err;
562 rcu_read_unlock();
561 return &rt->dst; 563 return &rt->dst;
562 564
563route_err: 565route_err:
564 ip_rt_put(rt); 566 ip_rt_put(rt);
565no_route: 567no_route:
568 rcu_read_unlock();
566 __IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); 569 __IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
567 return NULL; 570 return NULL;
568} 571}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 44c09eddbb78..cd426313a298 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -943,9 +943,11 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
943 if (skb) { 943 if (skb) {
944 __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr); 944 __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
945 945
946 rcu_read_lock();
946 err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, 947 err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
947 ireq->ir_rmt_addr, 948 ireq->ir_rmt_addr,
948 ireq_opt_deref(ireq)); 949 rcu_dereference(ireq->ireq_opt));
950 rcu_read_unlock();
949 err = net_xmit_eval(err); 951 err = net_xmit_eval(err);
950 } 952 }
951 953