======================================================================== uTun3 AUDIT FINDINGS — Сводный отчёт ======================================================================== Аудит от 14.05.2026 — обход основных модулей (use-after-free, out-of-bounds, утечки, reentrancy) ======================================================================== HIGH (19 проблем) ======================================================================== 1. u_async.c:137-165 use-after-free Частичный успех u_realloc в socket_array_add_internal: если часть реаллоков прошла, а часть нет — старые массивы уже освобождены, новые не выделены, sa->sockets/sa->fd_to_index/sa->index_to_fd указывают на освобождённую память. 2. u_async.c:842,1167 логическая ошибка process_posted_tasks никогда не вызывается на Linux. В epoll-пути: drain_wakeup_pipe не вызывает handle_wakeup/process_posted_tasks. В poll-пути: wakeup-слот (i==0) обрабатывается с drain_wakeup_pipe и continue, минуя зарегистрированный коллбэк. Следствие: uasync_post из другого потока не доставляет задачи — posted_tasks накапливаются бесконечно. 3. u_async.c:1383,1398,1418 утечка памяти При сбое создания wakeup (pipe/socket) в uasync_create не освобождаются: ua->sockets, ua->timeout_heap, ua->timeout_pool, ua->epoll_fd. 4. memory_pool.c:51-69 double-free Нет детекта double-free. Повторный free создаёт цикл во freelist, memory_pool_alloc выдаёт один и тот же блок двум потребителям. 5. etcp.c:679-683 утечка памяти input_queue_cb: при исчерпании inflight_pool вызывается queue_entry_free(in_pkt) без queue_dgram_free(&in_pkt->ll). dgram из data_pool утекает. 6. etcp_connections.c:87,876-926 use-after-free burst_resp_timer не отменяется в etcp_link_close. Коллбэк burst_resp_timeout_cb срабатывает на освобождённом link. 7. etcp_connections.c:846-854 use-after-free stats_timer не отменяется при провале insert_link в etcp_link_new. link_stats_timer_cb срабатывает на освобождённом link. 8. etcp_connections.c:879-886 use-after-free Ветка conn==NULL в etcp_link_close пропускает отмену ВСЕХ таймеров (stats_timer, init_timer, shaper_timer, keepalive_timer, burst_resp_timer). Любой из них сработает на освобождённом link. 9. etcp_connections.c:1388,1531,1561 out-of-bounds read INIT request парсинг: проверка pkt_len < 12 должна быть pkt_len < 26 (23 байта заголовка). Пакет с длиной 12-25 пройдёт проверку, но читает за границей расшифрованных данных. 10. pkt_normalizer.c:33 null deref if (!pn) pn->alloc_errors++ — разыменование NULL после u_calloc. 11. pkt_normalizer.c:300 null deref pn_buf_renew в цикле without проверки возврата → memcpy(NULL, ...) при сбое memory_pool_alloc. 12. eim_nat.c:80-93 логическая ошибка Переполнение uint16_t порта: next_port с 65535→0, затем порты ниже port_start выделяются (включая порт 0). Соединения нерабочие. 13. eim_nat.c (весь файл) логическая ошибка Нет механизма истечения/удаления NAT-записей. Таблица навсегда исчерпывается при долгой работе, eim_nat_egress начинает отказывать. 14. route_bgp.c:749,762-766 утечка памяти route_bgp_process_nodeinfo: при пересоздании nodeinfo1 старая очередь paths сохраняется в локальную переменную, но затем перезаписывается новой queue_new() — утечка. 15. route_bgp.c:904-907 утечка памяти route_bgp_send_nodeinfo: при провале etcp_send не освобождаются p (u_malloc) и e (queue_entry_new). 16. route_ping.c:126-134 утечка памяти route_ping_cancel_for_conn: nat_check_arg (p->arg, u_calloc) не освобождается. В нормальном и таймаутном путях коллбэк освобождает, но cancel-путь коллбэк не вызывает. 17. ll_queue.c:321,439 reentrancy Синхронный вызов коллбэка при первом queue_data_put (count==1) без отложенного возобновления через uasync → рекурсивный ack_timeout_check с устаревшим указателем current. 18. secure_channel.c:379,711 потенциальный OOB write sc_encrypt пишет в caller buffer без параметра capacity. Контракт API опасен: вызывающий должен сам гарантировать размер буфера. 19. secure_channel.c:432,756 потенциальный OOB write sc_decrypt — аналогично, нет проверки capacity выходного буфера. ======================================================================== MEDIUM (18 проблем) ======================================================================== 20. u_async.c:591-639 use-after-free Stale handle в uasync_cancel_timeout/uasync_call_soon_cancel. Нет инвалидации (generation counter), пул может переиспользовать память. 21. memory_pool.c:8,38,61,95 race condition Глобальная g_total_free изменяется без блокировок, общая для всех пулов. 22. memory_pool.c:51-69 потенциальный OOB write Нет проверки принадлежности блока пулу. Free в чужой пул вызывает memset с чужим object_size — частичная очистка или запись за границу. 23. timeout_heap.c:43-45 утечка / несоответствие документации Документация обещает free() при free_callback==NULL, код этого не делает. 24. etcp.c:718-763 reentrancy Вложенный ack_timeout_check (через input_send_q_cb→etcp_request_pkt→ wait_ack_cb) обрабатывает не тот entry, т.к. outer loop использует current, который мог быть перемещён/удалён внутренним вызовом. 25. etcp.c:747,944 утечка / дрейф счётчиков Непроверенный queue_data_put_with_index: при провале счётчики (retransmissions_count, inflight_bytes) не откатываются. 26. etcp_connections.c:1731,1763 out-of-bounds read INIT_RESPONSE парсинг: нужно >=19 байт, проверяется только >=3. 27. etcp_connections.c:748-753 use-after-free + бесконечный цикл etcp_socket_remove: при link->conn==NULL remove_link пропускается, num_channels не уменьшается, цикл перечитывает освобождённый conn->links[0]. 28. etcp_connections.c:1736-1738 логическая ошибка link_status перезаписывается значением remote_keepalive, игнорируя локальный recv_keepalive. Временно помечает link UP даже когда локальный приём мёртв. 29. pkt_normalizer.c:43 integer overflow/underflow frag_size = mtu - ACK_REZERV - UDP_HDR_SIZE - UDP_SC_HDR_SIZE. При mtu < 158 беззнаковое вычитание даёт ~65379 → огромные буферы. 30. pkt_normalizer.c:240 утечка памяти При провале queue_data_put фрагмент и dgram не освобождаются. 31. eim_nat.c:97,173 null deref Нет проверки ctx->initialized/ctx->table в egress/ingress. 32. eim_nat.c:268,293 логическая ошибка Статические пробросы (port forward) вне port range недоступны. 33. secure_channel.c:66 key hygiene Нет sc_free_ctx — сессионный ключ не зануляется при уничтожении контекста. 34. secure_channel.c:322,620 key hygiene ECDH shared secret остаётся на стеке незанулённым после sc_derive_session_key. 35. secure_channel.c:352,680 nonce entropy При постоянном провале random_bytes seed остаётся 0 (static init). Nonce становится полностью предсказуемым (counter+timestamp). 36. route_bgp.c:1122 утечка памяти route_bgp_send_nat_info: etcp_send без проверки → pkt/e утекают при провале. 37. route_bgp.c:1157 утечка памяти (аналогично #36) route_bgp_send_nat_check_req: etcp_send без проверки. 38. config_parser.c:1055-1066 логическая ошибка update_config_keys дописывает [global] секцию в конец файла. При повторном вызове получается дубликат секции, парсер может сбойнуть. ======================================================================== LOW (13 проблем) ======================================================================== 39. u_async.c:1594-1617 утечка (abort) abort() в destroy до освобождения posted_tasks и мьютекса. 40. u_async.c:1608 race condition posted_tasks_head читается без posted_lock в destroy. 41. memory_pool.c:47 truncation size_t → uint32_t в u_calloc_impl (object_size > UINT32_MAX). 42. memory_pool.h:16 signedness int free_count может обернуться при двойном освобождении. 43. timeout_heap.c:31 dead code freed_count никогда не обновляется, timeout_heap_get_freed_count не реализован. 44. timeout_heap.c:66-67 integer overflow capacity*2 и sizeof(TimeoutEntry)*new_cap могут переполниться. 45. ll_queue.c:106-127 dangling pointer queue_free освобождает hash_table, но не чистит entry->hash_next. 46. pkt_normalizer.c:374 десинхронизация потока При провале ll_alloc_lldgram 2 байта заголовка уже consumed, но фрагмент сброшен → потеря данных. 47. eim_nat.c:105,181 unaligned access (ARM) *(uint16_t*)(ip_data + 6) — невыровненный доступ на ARM. 48. secure_channel.c:108-131 избыточность CRC32 поверх CCM (аутентифицированное шифрование) избыточен. 49. secure_channel.h:51-52 dead code Неиспользуемые поля send_nonce[13]/recv_nonce[13]. 50. config_parser.c:312 undefined behavior ~0U << (32 - cidr) при cidr==0 — сдвиг на ширину типа. 51. route_ping.c:227 integer overflow uint16_t avg_rtt = timeout_ms * 10 — переполнение при timeout_ms > 6553. ======================================================================== Файлы без ошибок ======================================================================== - route_node.c — чисто - tun_if.c — чисто - etcp_api.c — только порядок queue_entry_free/dgram_free (LOW, см. etcp.c Issue #7 старого аудита) - etcp_loadbalancer.c — не аудирован (250 строк) ======================================================================== Рекомендуемый порядок исправления ======================================================================== 1. КРИТИЧЕСКИ ФУНКЦИОНАЛЬНЫЕ: u_async.c #2 (posted_tasks не работают на Linux) u_async.c #3 (утечки при сбое старта) 2. USE-AFTER-FREE: etcp_connections.c #6,#7,#8,#5 (висячие таймеры) u_async.c #1 (частичный realloc) ll_queue.c #17 (reentrancy) 3. УТЕЧКИ ПАМЯТИ: etcp.c #5 (dgram из data_pool) route_bgp.c #14,#15,#36,#37 route_ping.c #16 4. OOB / NULL DEREF: etcp_connections.c #9,#26 (INIT bounds) pkt_normalizer.c #10,#11 (null deref) 5. ЛОГИКА: eim_nat.c #12,#13 (порты + expiry) memory_pool.c #4 (double-free) config_parser.c #38 (дубликат секции)