Commit 95556a88 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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 47dcc20a
("ipv4: tcp: ip_send_unicast_reply() is not BH safe")

Fixes: 7309f882 ("dccp: do not assume DCCP code is non preemptible")
Fixes: 5413d1ba ("net: do not block BH while processing socket backlog")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 03addc2b
...@@ -462,7 +462,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk, ...@@ -462,7 +462,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
rt = ip_route_output_flow(net, &fl4, sk); rt = ip_route_output_flow(net, &fl4, sk);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
__IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
return NULL; return NULL;
} }
...@@ -527,17 +527,19 @@ static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb) ...@@ -527,17 +527,19 @@ static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
rxiph->daddr); rxiph->daddr);
skb_dst_set(skb, dst_clone(dst)); skb_dst_set(skb, dst_clone(dst));
local_bh_disable();
bh_lock_sock(ctl_sk); bh_lock_sock(ctl_sk);
err = ip_build_and_send_pkt(skb, ctl_sk, err = ip_build_and_send_pkt(skb, ctl_sk,
rxiph->daddr, rxiph->saddr, NULL); rxiph->daddr, rxiph->saddr, NULL);
bh_unlock_sock(ctl_sk); bh_unlock_sock(ctl_sk);
if (net_xmit_eval(err) == 0) { if (net_xmit_eval(err) == 0) {
DCCP_INC_STATS(DCCP_MIB_OUTSEGS); __DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
DCCP_INC_STATS(DCCP_MIB_OUTRSTS); __DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
} }
local_bh_enable();
out: out:
dst_release(dst); dst_release(dst);
} }
static void dccp_v4_reqsk_destructor(struct request_sock *req) static void dccp_v4_reqsk_destructor(struct request_sock *req)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment