From 5633903be09c16726c998a0375e7b3aba0ebd2e6 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 10 Sep 2026 17:53:14 +0300 Subject: [PATCH] =?UTF-8?q?stcp:=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20=D0=BF=D1=80=D0=B8=D0=BD=D1=8F=D1=82=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=BA=D0=BE=D0=BD=D0=BD=D0=B5=D0=BA=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B2=20stcp=5Fserver=5Fdestroy=20(UAF=20server=5Ftlink->conn?= =?UTF-8?q?=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20tcp=5Fsocket=5Fremove)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/transport_layer/stcp.c | 3 +++ src/transport_layer/stcp.h | 7 +++++++ src/transport_layer/stcp_server.c | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/src/transport_layer/stcp.c b/src/transport_layer/stcp.c index 9fd4d23d..9424f773 100644 --- a/src/transport_layer/stcp.c +++ b/src/transport_layer/stcp.c @@ -27,6 +27,7 @@ void stcp_conn_set_on_close(struct stcp_conn *c, void (*cb)(struct stcp_conn *co void stcp_conn_free(struct stcp_conn *c) { if (!c) return; + stcp_server_remove_conn(c); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_conn_free: c=%p sock=%d sock_id=%p recv_buf=%p state=%d allocated=%d", (void*)c, (int)c->sock, (void*)c->socket_id, (void*)c->recv_buf, (int)c->state, (int)c->allocated); if (c->socket_id) { uasync_remove_socket_t(c->ua, c->sock); c->socket_id = NULL; } @@ -292,6 +293,8 @@ void stcp_conn_do_close(struct stcp_conn *c, int err) { int prev = c->state; c->state = STCP_STATE_CLOSED; + stcp_server_remove_conn(c); + if (c->hs_timer) { uasync_cancel_timeout(c->ua, c->hs_timer); c->hs_timer = NULL; } DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_conn close is_server=%d prev_state=%d err=%d sock=%d", c->is_server, prev, err, (int)c->sock); diff --git a/src/transport_layer/stcp.h b/src/transport_layer/stcp.h index dc235db6..3f20dfa5 100644 --- a/src/transport_layer/stcp.h +++ b/src/transport_layer/stcp.h @@ -18,6 +18,7 @@ extern "C" { struct UTUN_INSTANCE; struct ETCP_CONN; +struct stcp_server; typedef void (*stcp_ping_cb)(int success, uint16_t rtt, void *arg); @@ -143,6 +144,9 @@ struct stcp_conn { uint16_t recv_msg_size; // stream: size from decoded header void (*recv_on_chunk)(struct stcp_conn *c, uint8_t *data, size_t len); uint8_t rx_paused; // reading paused due to rx_queue overflow + + struct stcp_server *srv; // владеющий сервер (accept-сторона), NULL для клиентских коннектов + struct stcp_conn *srv_next; // звено в списке принятых коннектов сервера }; void stcp_conn_free(struct stcp_conn *c); @@ -175,6 +179,9 @@ void stcp_recv_try(struct stcp_conn *c); // unified close: closes socket, frees buffers, calls on_close. does NOT clean streams (stcp_conn_free does) void stcp_conn_do_close(struct stcp_conn *c, int err); +// снимает принятый коннект из списка владеющего сервера (реализация в stcp_server.c) +void stcp_server_remove_conn(struct stcp_conn *c); + // handshake timeout callback (for use with uasync_set_timeout) void hs_timeout_cb(void *arg); diff --git a/src/transport_layer/stcp_server.c b/src/transport_layer/stcp_server.c index 19f937b1..e4fc3a2a 100644 --- a/src/transport_layer/stcp_server.c +++ b/src/transport_layer/stcp_server.c @@ -36,8 +36,18 @@ struct stcp_server { uint8_t reality_enabled; struct reality_server_config reality_srv; char reality_dest[REALITY_DEST_MAX]; + + struct stcp_conn *conns; // список принятых (accept) коннектов — закрываются при destroy }; +void stcp_server_remove_conn(struct stcp_conn *c) { + if (!c || !c->srv) return; + struct stcp_conn **pp = &c->srv->conns; + while (*pp && *pp != c) pp = &(*pp)->srv_next; + if (*pp) *pp = c->srv_next; + c->srv = NULL; +} + static void server_accept_cb(socket_t sock, void *arg); static void server_conn_read_cb(socket_t sock, void *arg); static void server_hs_phase1_cb(struct stcp_conn *c, uint8_t *data, size_t len); @@ -290,6 +300,10 @@ static void server_accept_cb(socket_t listen_sock, void *arg) { stcp_recv_set(c, SC_PUBKEY_ENC_SIZE + STCP_HS_ENC_CLIENT, 0, server_hs_phase1_cb); } c->hs_timer = uasync_set_timeout(c->ua, STCP_HS_TIMEOUT, c, hs_timeout_cb, "stcp_hs"); + + c->srv = srv; + c->srv_next = srv->conns; + srv->conns = c; DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_server: accepted connection fd=%d", (int)cli_sock); } @@ -356,6 +370,10 @@ void stcp_server_destroy(struct stcp_server *srv) { if (!srv) return; if (srv->listen_id) uasync_remove_socket_t(srv->ua, srv->listen_sock); if (srv->listen_sock != SOCKET_INVALID) socket_close_wrapper(srv->listen_sock); + while (srv->conns) { + struct stcp_conn *c = srv->conns; + stcp_conn_do_close(c, 0); // снимает c из списка (c->srv) и каскадно закрывает серверный ETCP_LINK + } u_free(srv); DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_server destroyed"); }