7736186
From: Eric Dumazet <edumazet@google.com>
7736186
Date: 2016-08-17 12:56:26
7736186
Subject: [PATCH net] tcp: fix use after free in tcp_xmit_retransmit_queue()
7736186
7736186
When tcp_sendmsg() allocates a fresh and empty skb, it puts it at the
7736186
tail of the write queue using tcp_add_write_queue_tail()
7736186
7736186
Then it attempts to copy user data into this fresh skb.
7736186
7736186
If the copy fails, we undo the work and remove the fresh skb.
7736186
7736186
Unfortunately, this undo lacks the change done to tp->highest_sack and
7736186
we can leave a dangling pointer (to a freed skb)
7736186
7736186
Later, tcp_xmit_retransmit_queue() can dereference this pointer and
7736186
access freed memory. For regular kernels where memory is not unmapped,
7736186
this might cause SACK bugs because tcp_highest_sack_seq() is buggy,
7736186
returning garbage instead of tp->snd_nxt, but with various debug
7736186
features like CONFIG_DEBUG_PAGEALLOC, this can crash the kernel.
7736186
7736186
This bug was found by Marco Grassi thanks to syzkaller.
7736186
7736186
Fixes: 6859d49475d4 ("[TCP]: Abstract tp->highest_sack accessing & point to next skb")
7736186
Reported-by: Marco Grassi <marco.gra@gmail.com>
7736186
Signed-off-by: Eric Dumazet <edumazet@google.com>
7736186
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
7736186
Cc: Yuchung Cheng <ycheng@google.com>
7736186
Cc: Neal Cardwell <ncardwell@google.com>
7736186
---
7736186
 include/net/tcp.h |    2 ++
7736186
 1 file changed, 2 insertions(+)
7736186
7736186
diff --git a/include/net/tcp.h b/include/net/tcp.h
7736186
index c00e7d51bb18..7717302cab91 100644
7736186
--- a/include/net/tcp.h
7736186
+++ b/include/net/tcp.h
7736186
@@ -1523,6 +1523,8 @@ static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unli
7736186
 {
7736186
 	if (sk->sk_send_head == skb_unlinked)
7736186
 		sk->sk_send_head = NULL;
7736186
+	if (tcp_sk(sk)->highest_sack == skb_unlinked)
7736186
+		tcp_sk(sk)->highest_sack = NULL;
7736186
 }
7736186
 
7736186
 static inline void tcp_init_send_head(struct sock *sk)
7736186