This is a note to let you know that I've just added the patch titled ipv6: tcp: add a missing tcp_v6_restore_cb() to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Tue Feb 14 17:03:08 PST 2017 From: Eric Dumazet <edumazet@xxxxxxxxxx> Date: Sun, 5 Feb 2017 20:23:22 -0800 Subject: ipv6: tcp: add a missing tcp_v6_restore_cb() From: Eric Dumazet <edumazet@xxxxxxxxxx> [ 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@xxxxxxxxxx> Reported-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- net/ipv6/tcp_ipv6.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -987,6 +987,16 @@ drop: return 0; /* don't send reset */ } +static void tcp_v6_restore_cb(struct sk_buff *skb) +{ + /* We need to move header back to the beginning if xfrm6_policy_check() + * and tcp_v6_fill_cb() are going to be called again. + * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there. + */ + memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, + sizeof(struct inet6_skb_parm)); +} + static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, struct request_sock *req, struct dst_entry *dst, @@ -1178,8 +1188,10 @@ static struct sock *tcp_v6_syn_recv_sock sk_gfp_mask(sk, GFP_ATOMIC)); consume_skb(ireq->pktopts); ireq->pktopts = NULL; - if (newnp->pktoptions) + if (newnp->pktoptions) { + tcp_v6_restore_cb(newnp->pktoptions); skb_set_owner_r(newnp->pktoptions, newsk); + } } } @@ -1194,16 +1206,6 @@ out: return NULL; } -static void tcp_v6_restore_cb(struct sk_buff *skb) -{ - /* We need to move header back to the beginning if xfrm6_policy_check() - * and tcp_v6_fill_cb() are going to be called again. - * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there. - */ - memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, - sizeof(struct inet6_skb_parm)); -} - /* The socket must have it's spinlock held when we get * here, unless it is a TCP_LISTEN socket. * Patches currently in stable-queue which might be from edumazet@xxxxxxxxxx are queue-4.9/ipv6-pointer-math-error-in-ip6_tnl_parse_tlv_enc_lim.patch queue-4.9/netlabel-out-of-bound-access-in-cipso_v4_validate.patch queue-4.9/packet-round-up-linear-to-header-len.patch queue-4.9/tun-read-vnet_hdr_sz-once.patch queue-4.9/ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch queue-4.9/l2tp-do-not-use-udp_ioctl.patch queue-4.9/tcp-fix-0-divide-in-__tcp_select_window.patch queue-4.9/can-fix-kernel-panic-at-security_sock_rcv_skb.patch queue-4.9/net-introduce-device-min_header_len.patch queue-4.9/macvtap-read-vnet_hdr_size-once.patch queue-4.9/tcp-avoid-infinite-loop-in-tcp_splice_read.patch queue-4.9/mlx4-invoke-softirqs-after-napi_reschedule.patch queue-4.9/ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch queue-4.9/ipv4-keep-skb-dst-around-in-presence-of-ip-options.patch queue-4.9/net-use-a-work-queue-to-defer-net_disable_timestamp-work.patch queue-4.9/ip6_gre-fix-ip6gre_err-invalid-reads.patch