From b0857156544475b2ed3cee50cb09ced6e6cbd953 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 15 Sep 2026 22:07:55 +0300 Subject: [PATCH] =?UTF-8?q?tun/nat:=20fix=20UAF=20=D0=BF=D1=80=D0=B8=20tea?= =?UTF-8?q?rdown=20=D0=B8=20use-after-free=20=D0=B2=20tun=5Fread=5Fpacket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/nat_transport.c | 2 +- src/tun_if.c | 2 +- src/utun_instance.c | 11 ++++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/nat_transport.c b/src/nat_transport.c index 4daa99f8..163373c9 100644 --- a/src/nat_transport.c +++ b/src/nat_transport.c @@ -107,7 +107,7 @@ static void nat_transport_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* if (!inst) { queue_dgram_free(entry); queue_entry_free(entry); return; } struct nat_transport_ctx* tr = &inst->nat_tr; struct eim_nat_ctx* ctx = &inst->nat; - if (!ctx->initialized) { queue_dgram_free(entry); queue_entry_free(entry); return; } + if (!tr->initialized || !ctx->initialized) { queue_dgram_free(entry); queue_entry_free(entry); return; } uint64_t src_node_id; memcpy(&src_node_id, entry->dgram + ROUTER_SVC_SRC_OFF, 8); diff --git a/src/tun_if.c b/src/tun_if.c index d9623718..e8864726 100644 --- a/src/tun_if.c +++ b/src/tun_if.c @@ -451,7 +451,7 @@ ssize_t tun_read_packet(struct tun_if* tun, uint8_t* buf, size_t len) tun->bytes_written += ret; tun->packets_written++; if (debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_TUN)) { - DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "[TUN->] %s", dump_ip_packet_to_buffer(buf + 1, pkt->len)); + DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "[TUN->] %s", dump_ip_packet_to_buffer(buf + 1, ret - 1)); } return ret; } diff --git a/src/utun_instance.c b/src/utun_instance.c index fc05a67c..d8747b90 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -462,6 +462,12 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) { broadcast_destroy_instance(instance); DEBUG_INFO(DEBUG_CATEGORY_SYS, "[DESTROY] F done — BGP + broadcast"); + /* Phase F2: NAT transport — отвязываем и закрываем nat_tun ДО разборки + сокетов/соединений, чтобы nat_transport_etcp_recv_cb не был вызван с + уже освобождённым буфером пакета (use-after-free при teardown). */ + if (instance->nat_tr.initialized) nat_transport_destroy(instance); + DEBUG_INFO(DEBUG_CATEGORY_SYS, "[DESTROY] F2 done — NAT transport"); + /* Phase G: ETCP sockets */ { struct ETCP_SOCKET* sock = instance->etcp_sockets; @@ -542,7 +548,7 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) { } DEBUG_INFO(DEBUG_CATEGORY_SYS, "[DESTROY] L done — deferred+pings"); - /* Phase M: TUN + proxy + routing + NAT */ + /* Phase M: TUN + proxy + routing */ if (instance->tun) { if (instance->tun->ifindex && instance->route_subnets) tun_route_del_all(instance->tun->ifindex, instance->tun->ifname, instance->route_subnets); @@ -556,8 +562,7 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) { routing_destroy(instance); if (instance->md.initialized) media_delivery_destroy(instance); media_async_destroy(instance->media_async); instance->media_async = NULL; - if (instance->nat_tr.initialized) nat_transport_destroy(instance); - DEBUG_INFO(DEBUG_CATEGORY_SYS, "[DESTROY] M done — TUN/proxy/routing/NAT"); + DEBUG_INFO(DEBUG_CATEGORY_SYS, "[DESTROY] M done — TUN/proxy/routing"); /* Phase N: etcp_router + nat_det + firewall */ etcp_router_destroy(instance);