Fix TCP proxy use-after-free during synchronous close
This commit is contained in:
1 parent
745ec3dbd2
commit
52ffb91101
2 files changed
+23
-2
No files matched your search
@@ -55,6 +55,18 @@ static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst,
|
||||
return proxy_send(inst, dst, ETCP_RT_ID_TCP_PROXY_CLIENT, subcmd, sid, data, len, force);
|
||||
}
|
||||
|
||||
// CLOSE может синхронно освободить rc через on_closed: резервируем состояние до push.
|
||||
static void server_queue_close(struct tcp_proxy_server_conn* rc) {
|
||||
if (rc->close_queued) return;
|
||||
rc->close_queued = 1;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_PROXY, "proxy exit: queue CLOSE peer=%016llx sid=%08x fd=%d",
|
||||
(unsigned long long)rc->peer_node_id, rc->stream_id, (int)rc->tc->sock);
|
||||
if (tcp_conn_push_close(rc->tc) == 0) return;
|
||||
rc->close_queued = 0;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "proxy exit: queue CLOSE failed peer=%016llx sid=%08x",
|
||||
(unsigned long long)rc->peer_node_id, rc->stream_id);
|
||||
}
|
||||
|
||||
// FIN относится только к прочитанному направлению: сначала передаём весь read_queue.
|
||||
static void server_maybe_finish(struct tcp_proxy_server_conn* rc) {
|
||||
struct tcp_conn* tc = rc->tc;
|
||||
@@ -64,7 +76,7 @@ static void server_maybe_finish(struct tcp_proxy_server_conn* rc) {
|
||||
proxy_flow_flush(&rc->flow);
|
||||
}
|
||||
if (rc->flow.fin_sent && rc->flow.fin_received && tc->fin_local) {
|
||||
if (tcp_conn_push_close(tc) == 0) rc->close_queued = 1;
|
||||
server_queue_close(rc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +389,7 @@ void tcp_proxy_server_handle_close(struct UTUN_INSTANCE* inst, uint64_t peer, ui
|
||||
}
|
||||
}
|
||||
if (rc->tc->connected) {
|
||||
if (!rc->close_queued && tcp_conn_push_close(rc->tc) == 0) rc->close_queued = 1;
|
||||
server_queue_close(rc);
|
||||
} else tcp_proxy_server_conn_free(rc);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user