From f37ac2c6379a5169c3dfce6e685af81f1ff7cb77 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 22 Oct 2026 22:47:50 +0200 Subject: [PATCH] Verify deferred teardown when the TX timer cannot start --- tests/Makefile.am | 3 ++- tests/test_etcp_windows.c | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 3229371e..b9d5e1b7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1012,7 +1012,8 @@ test_etcp_session_LDFLAGS = $(test_clock_ldflags) test_etcp_windows_SOURCES = test_etcp_windows.c $(test_clock_sources) test_etcp_windows_LDADD = $(LIBUTUN) $(COMMON_LIBS) -test_etcp_windows_LDFLAGS = $(test_clock_ldflags) -Wl,--wrap=etcp_encrypt_send -Wl,--wrap=memory_pool_alloc_impl -Wl,--wrap=bbr_main +test_etcp_windows_LDFLAGS = $(test_clock_ldflags) -Wl,--wrap=etcp_encrypt_send -Wl,--wrap=memory_pool_alloc_impl \\ + -Wl,--wrap=bbr_main -Wl,--wrap=uasync_set_timeout test_etcp_router_tcp_SOURCES = test_etcp_router_tcp.c test_etcp_router_tcp_LDADD = $(LIBUTUN) $(COMMON_LIBS) diff --git a/tests/test_etcp_windows.c b/tests/test_etcp_windows.c index 331531cb..cacfe6af 100644 --- a/tests/test_etcp_windows.c +++ b/tests/test_etcp_windows.c @@ -16,7 +16,13 @@ static struct UTUN_INSTANCE inst; static struct utun_config cfg; static struct ETCP_CONN* conn; static struct ETCP_LINK *a, *b; -static unsigned sends, fail_alloc, fail_send, bbr_calls, saw_cwnd_limited, saw_app_limited; +static unsigned sends, fail_alloc, fail_send, fail_tx_timer, bbr_calls, saw_cwnd_limited, saw_app_limited; + +void* __real_uasync_set_timeout(struct UASYNC*, int, void*, timeout_callback_t, const char*); +void* __wrap_uasync_set_timeout(struct UASYNC* loop, int delay, void* arg, timeout_callback_t callback, const char* name) { + if (fail_tx_timer && !strcmp(name, "etcp_tx")) { fail_tx_timer--; return NULL; } + return __real_uasync_set_timeout(loop, delay, arg, callback, name); +} int __wrap_etcp_encrypt_send(struct ETCP_DGRAM* pkt) { CHECK(conn->tx_running && pkt->link && pkt->link->initialized && pkt->link->link_status); @@ -56,7 +62,7 @@ static void check_accounting(void) { static void setup(void) { memset(&inst, 0, sizeof(inst)); memset(&cfg, 0, sizeof(cfg)); - sends = fail_alloc = fail_send = bbr_calls = saw_cwnd_limited = saw_app_limited = 0; + sends = fail_alloc = fail_send = fail_tx_timer = bbr_calls = saw_cwnd_limited = saw_app_limited = 0; ua = uasync_create(); CHECK(ua); inst.ua = ua; inst.node_id = 1; inst.config = &cfg; cfg.global.bbr_max_cwnd = INFLIGHT_LIM_MAX; inst.connections = queue_new(ua, 16, 0, 8, "windows"); @@ -277,13 +283,24 @@ static void config_limits(void) { } } +/* Отказ TX-таймера закрывает транспорт после выхода из вызывающего стека, без UAF очереди/линков. */ +static void timer_failure(void) { + setup(); CHECK(!conn->tx_timer && etcp_conn_ref_take(conn) == 0); + fail_tx_timer = 1; enqueue(100); + CHECK(conn->close_requested && conn->close_token && conn->state != 2 && conn->links); + uasync_drain_immediate(ua); + CHECK(conn->state == 2 && !conn->tx_timer && !conn->links); + etcp_conn_ref_free(conn); teardown(); +} + int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG); test_clock_init(10); size_t baseline = u_get_allocated_count(); void (*cases[])(void) = {selection, boundaries_ack_burst, late_ack_and_migration, lost_ack_and_shrink, - grow_and_session, allocation_and_send_failure, removed_link_and_bbr, pacing_reset_close, initial_readiness, config_limits}; + grow_and_session, allocation_and_send_failure, removed_link_and_bbr, pacing_reset_close, initial_readiness, + config_limits, timer_failure}; for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { cases[i](); CHECK(u_get_allocated_count() == baseline); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS ETCP window scenario %u", i);