]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/ipv6/tcp_ipv6.c
tcp/dccp: fix ireq->pktopts race
[mirror_ubuntu-artful-kernel.git] / net / ipv6 / tcp_ipv6.c
index 714bc5ad096e9beda5226c4caf8ddd4efae038bf..ea2f4d5440b58266f46525114e7bd9d025fb91d6 100644 (file)
@@ -1084,16 +1084,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
        /* Clone RX bits */
        newnp->rxopt.all = np->rxopt.all;
 
-       /* Clone pktoptions received with SYN */
        newnp->pktoptions = NULL;
-       if (ireq->pktopts) {
-               newnp->pktoptions = skb_clone(ireq->pktopts,
-                                             sk_gfp_atomic(sk, GFP_ATOMIC));
-               consume_skb(ireq->pktopts);
-               ireq->pktopts = NULL;
-               if (newnp->pktoptions)
-                       skb_set_owner_r(newnp->pktoptions, newsk);
-       }
        newnp->opt        = NULL;
        newnp->mcast_oif  = tcp_v6_iif(skb);
        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 *
                goto out;
        }
        *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
+       /* Clone pktoptions received with SYN, if we own the req */
+       if (*own_req && ireq->pktopts) {
+               newnp->pktoptions = skb_clone(ireq->pktopts,
+                                             sk_gfp_atomic(sk, GFP_ATOMIC));
+               consume_skb(ireq->pktopts);
+               ireq->pktopts = NULL;
+               if (newnp->pktoptions)
+                       skb_set_owner_r(newnp->pktoptions, newsk);
+       }
 
        return newsk;