Browse Source

tun/nat: fix UAF при teardown и use-after-free в tun_read_packet

router-recv-conn-uaf
evgeny 2 weeks ago
parent
commit
b085715654
  1. 2
      src/nat_transport.c
  2. 2
      src/tun_if.c
  3. 11
      src/utun_instance.c

2
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; } if (!inst) { queue_dgram_free(entry); queue_entry_free(entry); return; }
struct nat_transport_ctx* tr = &inst->nat_tr; struct nat_transport_ctx* tr = &inst->nat_tr;
struct eim_nat_ctx* ctx = &inst->nat; 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; uint64_t src_node_id;
memcpy(&src_node_id, entry->dgram + ROUTER_SVC_SRC_OFF, 8); memcpy(&src_node_id, entry->dgram + ROUTER_SVC_SRC_OFF, 8);

2
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->bytes_written += ret;
tun->packets_written++; tun->packets_written++;
if (debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_TUN)) { 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; return ret;
} }

11
src/utun_instance.c

@ -462,6 +462,12 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
broadcast_destroy_instance(instance); broadcast_destroy_instance(instance);
DEBUG_INFO(DEBUG_CATEGORY_SYS, "[DESTROY] F done — BGP + broadcast"); 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 */ /* Phase G: ETCP sockets */
{ {
struct ETCP_SOCKET* sock = instance->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"); 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) {
if (instance->tun->ifindex && instance->route_subnets) if (instance->tun->ifindex && instance->route_subnets)
tun_route_del_all(instance->tun->ifindex, instance->tun->ifname, 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); routing_destroy(instance);
if (instance->md.initialized) media_delivery_destroy(instance); if (instance->md.initialized) media_delivery_destroy(instance);
media_async_destroy(instance->media_async); instance->media_async = NULL; 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");
DEBUG_INFO(DEBUG_CATEGORY_SYS, "[DESTROY] M done — TUN/proxy/routing/NAT");
/* Phase N: etcp_router + nat_det + firewall */ /* Phase N: etcp_router + nat_det + firewall */
etcp_router_destroy(instance); etcp_router_destroy(instance);

Loading…
Cancel
Save