aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2016-07-08 05:03:57 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-09 18:14:17 -0400
commit95556a883834122c616bbeb942654d745ceb9712 (patch)
tree38d19b84c9d1d2b632f0c08a321dd9fb44c7e5f3 /net/dccp
parent03addc2bcebd953e74c52f0664629032fd9767e9 (diff)
dccp: avoid deadlock in dccp_v4_ctl_send_reset
In the prep work I did before enabling BH while handling socket backlog, I missed two points in DCCP : 1) dccp_v4_ctl_send_reset() uses bh_lock_sock(), assuming BH were blocked. It is not anymore always true. 2) dccp_v4_route_skb() was using __IP_INC_STATS() instead of IP_INC_STATS() A similar fix was done for TCP, in commit 47dcc20a39d0 ("ipv4: tcp: ip_send_unicast_reply() is not BH safe") Fixes: 7309f8821fd6 ("dccp: do not assume DCCP code is non preemptible") Fixes: 5413d1babe8f ("net: do not block BH while processing socket backlog") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ipv4.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 5c7e413a3ae4..25dd25b47d41 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -462,7 +462,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
462 security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); 462 security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
463 rt = ip_route_output_flow(net, &fl4, sk); 463 rt = ip_route_output_flow(net, &fl4, sk);
464 if (IS_ERR(rt)) { 464 if (IS_ERR(rt)) {
465 __IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); 465 IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
466 return NULL; 466 return NULL;
467 } 467 }
468 468
@@ -527,17 +527,19 @@ static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
527 rxiph->daddr); 527 rxiph->daddr);
528 skb_dst_set(skb, dst_clone(dst)); 528 skb_dst_set(skb, dst_clone(dst));
529 529
530 local_bh_disable();
530 bh_lock_sock(ctl_sk); 531 bh_lock_sock(ctl_sk);
531 err = ip_build_and_send_pkt(skb, ctl_sk, 532 err = ip_build_and_send_pkt(skb, ctl_sk,
532 rxiph->daddr, rxiph->saddr, NULL); 533 rxiph->daddr, rxiph->saddr, NULL);
533 bh_unlock_sock(ctl_sk); 534 bh_unlock_sock(ctl_sk);
534 535
535 if (net_xmit_eval(err) == 0) { 536 if (net_xmit_eval(err) == 0) {
536 DCCP_INC_STATS(DCCP_MIB_OUTSEGS); 537 __DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
537 DCCP_INC_STATS(DCCP_MIB_OUTRSTS); 538 __DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
538 } 539 }
540 local_bh_enable();
539out: 541out:
540 dst_release(dst); 542 dst_release(dst);
541} 543}
542 544
543static void dccp_v4_reqsk_destructor(struct request_sock *req) 545static void dccp_v4_reqsk_destructor(struct request_sock *req)