Skip to content

Commit ce10500

Browse files
edumazetdavem330
authored andcommitted
tcp/dccp: fix ireq->pktopts race
IPv6 request sockets store a pointer to skb containing the SYN packet to be able to transfer it to full blown socket when 3WHS is done (ireq->pktopts -> np->pktoptions) As explained in commit 5e0724d ("tcp/dccp: fix hashdance race for passive sessions"), we must transfer the skb only if we won the hashdance race, if multiple cpus receive the 'ack' packet completing 3WHS at the same time. Fixes: e994b2f ("tcp: do not lock listener to process SYN packets") Fixes: 079096f ("tcp/dccp: install syn_recv requests into ehash table") Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7b56543 commit ce10500

File tree

2 files changed

+17
-17
lines changed

2 files changed

+17
-17
lines changed

net/dccp/ipv6.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -477,15 +477,7 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
477477
/* Clone RX bits */
478478
newnp->rxopt.all = np->rxopt.all;
479479

480-
/* Clone pktoptions received with SYN */
481480
newnp->pktoptions = NULL;
482-
if (ireq->pktopts != NULL) {
483-
newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC);
484-
consume_skb(ireq->pktopts);
485-
ireq->pktopts = NULL;
486-
if (newnp->pktoptions)
487-
skb_set_owner_r(newnp->pktoptions, newsk);
488-
}
489481
newnp->opt = NULL;
490482
newnp->mcast_oif = inet6_iif(skb);
491483
newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
@@ -515,6 +507,14 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
515507
goto out;
516508
}
517509
*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
510+
/* Clone pktoptions received with SYN, if we own the req */
511+
if (*own_req && ireq->pktopts) {
512+
newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC);
513+
consume_skb(ireq->pktopts);
514+
ireq->pktopts = NULL;
515+
if (newnp->pktoptions)
516+
skb_set_owner_r(newnp->pktoptions, newsk);
517+
}
518518

519519
return newsk;
520520

net/ipv6/tcp_ipv6.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,16 +1084,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
10841084
/* Clone RX bits */
10851085
newnp->rxopt.all = np->rxopt.all;
10861086

1087-
/* Clone pktoptions received with SYN */
10881087
newnp->pktoptions = NULL;
1089-
if (ireq->pktopts) {
1090-
newnp->pktoptions = skb_clone(ireq->pktopts,
1091-
sk_gfp_atomic(sk, GFP_ATOMIC));
1092-
consume_skb(ireq->pktopts);
1093-
ireq->pktopts = NULL;
1094-
if (newnp->pktoptions)
1095-
skb_set_owner_r(newnp->pktoptions, newsk);
1096-
}
10971088
newnp->opt = NULL;
10981089
newnp->mcast_oif = tcp_v6_iif(skb);
10991090
newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
@@ -1149,6 +1140,15 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
11491140
goto out;
11501141
}
11511142
*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
1143+
/* Clone pktoptions received with SYN, if we own the req */
1144+
if (*own_req && ireq->pktopts) {
1145+
newnp->pktoptions = skb_clone(ireq->pktopts,
1146+
sk_gfp_atomic(sk, GFP_ATOMIC));
1147+
consume_skb(ireq->pktopts);
1148+
ireq->pktopts = NULL;
1149+
if (newnp->pktoptions)
1150+
skb_set_owner_r(newnp->pktoptions, newsk);
1151+
}
11521152

11531153
return newsk;
11541154

0 commit comments

Comments
 (0)