Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35724bcc authored by Wei Wang's avatar Wei Wang Committed by Dmitry Shmidt
Browse files

BACKPORT: tcp: fix potential double free issue for fastopen_req



commit 7db92362d2fee5887f6b0c41653b8c9f8f5d6020 upstream.

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: 19f6d3f3c842 ("net/tcp-fastopen: Add new API support")
Reported-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Signed-off-by: default avatarWei Wang <weiwan@google.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>

Change-Id: I6bb174d6997470643df5ba34e1f9858e16f4989d
Fixes: Change-Id: Icc181febd74e3117c2fc835d7ed935e107b5815e
       ("BACKPORT: net/tcp-fastopen: Add new API support")
Signed-off-by: default avatarAmit Pundir <amit.pundir@linaro.org>
parent 2a5cc53e
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -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;
	/* 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) {