mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
BACKPORT: tcp: fix potential double free issue for fastopen_req
commit7db92362d2upstream. tp->fastopen_req could potentially be double freed if a malicious user does the following: 1. Enable TCP_FASTOPEN_CONNECT sockopt and do a connect() on the socket. 2. Call connect() with AF_UNSPEC to disconnect the socket. 3. Make this socket a listening socket by calling listen(). 4. Accept incoming connections and generate child sockets. All child sockets will get a copy of the pointer of fastopen_req. 5. Call close() on all sockets. fastopen_req will get freed multiple times. Fixes:19f6d3f3c8("net/tcp-fastopen: Add new API support") Reported-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Wei Wang <weiwan@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Change-Id: I6bb174d6997470643df5ba34e1f9858e16f4989d Fixes: Change-Id: Icc181febd74e3117c2fc835d7ed935e107b5815e ("BACKPORT: net/tcp-fastopen: Add new API support") Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
This commit is contained in:
@@ -1115,9 +1115,14 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
|
||||
flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
|
||||
err = __inet_stream_connect(sk->sk_socket, uaddr,
|
||||
msg->msg_namelen, flags);
|
||||
inet->defer_connect = 0;
|
||||
*copied = tp->fastopen_req->copied;
|
||||
tcp_free_fastopen_req(tp);
|
||||
/* fastopen_req could already be freed in __inet_stream_connect
|
||||
* if the connection times out or gets rst
|
||||
*/
|
||||
if (tp->fastopen_req) {
|
||||
*copied = tp->fastopen_req->copied;
|
||||
tcp_free_fastopen_req(tp);
|
||||
inet->defer_connect = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2331,6 +2336,10 @@ int tcp_disconnect(struct sock *sk, int flags)
|
||||
sk->sk_rx_dst = NULL;
|
||||
tcp_saved_syn_free(tp);
|
||||
|
||||
/* Clean up fastopen related fields */
|
||||
tcp_free_fastopen_req(tp);
|
||||
inet->defer_connect = 0;
|
||||
|
||||
WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
|
||||
|
||||
if (sk->sk_frag.page) {
|
||||
|
||||
Reference in New Issue
Block a user