aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2017-02-05 23:23:22 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-18 09:11:41 -0500
commit1e340bb22af3afc881db78c17b73eaf3d26fb8fe (patch)
tree933da44e1f1594050e3d326803fa85f227fb177b
parentae1768bbbc469b75662c6714957fe5886cc960c4 (diff)
ipv6: tcp: add a missing tcp_v6_restore_cb()
[ Upstream commit ebf6c9cb23d7e56eec8575a88071dec97ad5c6e2 ] Dmitry reported use-after-free in ip6_datagram_recv_specific_ctl() A similar bug was fixed in commit 8ce48623f0cf ("ipv6: tcp: restore IP6CB for pktoptions skbs"), but I missed another spot. tcp_v6_syn_recv_sock() can indeed set np->pktoptions from ireq->pktopts Fixes: 971f10eca186 ("tcp: better TCP_SKB_CB layout to reduce cache line misses") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/ipv6/tcp_ipv6.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b9f1fee9a886..e5ee107a0575 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -987,6 +987,16 @@ drop:
987 return 0; /* don't send reset */ 987 return 0; /* don't send reset */
988} 988}
989 989
990static void tcp_v6_restore_cb(struct sk_buff *skb)
991{
992 /* We need to move header back to the beginning if xfrm6_policy_check()
993 * and tcp_v6_fill_cb() are going to be called again.
994 * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
995 */
996 memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
997 sizeof(struct inet6_skb_parm));
998}
999
990static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, 1000static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
991 struct request_sock *req, 1001 struct request_sock *req,
992 struct dst_entry *dst, 1002 struct dst_entry *dst,
@@ -1178,8 +1188,10 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
1178 sk_gfp_mask(sk, GFP_ATOMIC)); 1188 sk_gfp_mask(sk, GFP_ATOMIC));
1179 consume_skb(ireq->pktopts); 1189 consume_skb(ireq->pktopts);
1180 ireq->pktopts = NULL; 1190 ireq->pktopts = NULL;
1181 if (newnp->pktoptions) 1191 if (newnp->pktoptions) {
1192 tcp_v6_restore_cb(newnp->pktoptions);
1182 skb_set_owner_r(newnp->pktoptions, newsk); 1193 skb_set_owner_r(newnp->pktoptions, newsk);
1194 }
1183 } 1195 }
1184 } 1196 }
1185 1197
@@ -1194,16 +1206,6 @@ out:
1194 return NULL; 1206 return NULL;
1195} 1207}
1196 1208
1197static void tcp_v6_restore_cb(struct sk_buff *skb)
1198{
1199 /* We need to move header back to the beginning if xfrm6_policy_check()
1200 * and tcp_v6_fill_cb() are going to be called again.
1201 * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
1202 */
1203 memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
1204 sizeof(struct inet6_skb_parm));
1205}
1206
1207/* The socket must have it's spinlock held when we get 1209/* The socket must have it's spinlock held when we get
1208 * here, unless it is a TCP_LISTEN socket. 1210 * here, unless it is a TCP_LISTEN socket.
1209 * 1211 *