Skip to content

Commit ebf6c9c

Browse files
edumazetdavem330
authored andcommitted
ipv6: tcp: add a missing tcp_v6_restore_cb()
Dmitry reported use-after-free in ip6_datagram_recv_specific_ctl() A similar bug was fixed in commit 8ce4862 ("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: 971f10e ("tcp: better TCP_SKB_CB layout to reduce cache line misses") Signed-off-by: Eric Dumazet <[email protected]> Reported-by: Dmitry Vyukov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7892032 commit ebf6c9c

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

net/ipv6/tcp_ipv6.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,16 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
991991
return 0; /* don't send reset */
992992
}
993993

994+
static void tcp_v6_restore_cb(struct sk_buff *skb)
995+
{
996+
/* We need to move header back to the beginning if xfrm6_policy_check()
997+
* and tcp_v6_fill_cb() are going to be called again.
998+
* ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
999+
*/
1000+
memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
1001+
sizeof(struct inet6_skb_parm));
1002+
}
1003+
9941004
static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
9951005
struct request_sock *req,
9961006
struct dst_entry *dst,
@@ -1182,8 +1192,10 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
11821192
sk_gfp_mask(sk, GFP_ATOMIC));
11831193
consume_skb(ireq->pktopts);
11841194
ireq->pktopts = NULL;
1185-
if (newnp->pktoptions)
1195+
if (newnp->pktoptions) {
1196+
tcp_v6_restore_cb(newnp->pktoptions);
11861197
skb_set_owner_r(newnp->pktoptions, newsk);
1198+
}
11871199
}
11881200
}
11891201

@@ -1198,16 +1210,6 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
11981210
return NULL;
11991211
}
12001212

1201-
static void tcp_v6_restore_cb(struct sk_buff *skb)
1202-
{
1203-
/* We need to move header back to the beginning if xfrm6_policy_check()
1204-
* and tcp_v6_fill_cb() are going to be called again.
1205-
* ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
1206-
*/
1207-
memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
1208-
sizeof(struct inet6_skb_parm));
1209-
}
1210-
12111213
/* The socket must have it's spinlock held when we get
12121214
* here, unless it is a TCP_LISTEN socket.
12131215
*

0 commit comments

Comments
 (0)