Skip to content

Commit 7db9236

Browse files
tracywwnjdavem330
authored andcommitted
tcp: fix potential double free issue for fastopen_req
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: 19f6d3f ("net/tcp-fastopen: Add new API support") Reported-by: Andrey Konovalov <[email protected]> Signed-off-by: Wei Wang <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 94352d4 commit 7db9236

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

net/ipv4/tcp.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,9 +1110,14 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
11101110
flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
11111111
err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
11121112
msg->msg_namelen, flags, 1);
1113-
inet->defer_connect = 0;
1114-
*copied = tp->fastopen_req->copied;
1115-
tcp_free_fastopen_req(tp);
1113+
/* fastopen_req could already be freed in __inet_stream_connect
1114+
* if the connection times out or gets rst
1115+
*/
1116+
if (tp->fastopen_req) {
1117+
*copied = tp->fastopen_req->copied;
1118+
tcp_free_fastopen_req(tp);
1119+
inet->defer_connect = 0;
1120+
}
11161121
return err;
11171122
}
11181123

@@ -2318,6 +2323,10 @@ int tcp_disconnect(struct sock *sk, int flags)
23182323
memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
23192324
__sk_dst_reset(sk);
23202325

2326+
/* Clean up fastopen related fields */
2327+
tcp_free_fastopen_req(tp);
2328+
inet->defer_connect = 0;
2329+
23212330
WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
23222331

23232332
sk->sk_error_report(sk);

0 commit comments

Comments
 (0)