Browse Source

fix: use-after-free in route table — add route_delete before u_free in route_bgp_update_my_nodeinfo and route_bgp_process_nodeinfo, relax routes_overlap to allow hierarchical routes

Root cause: when bgp->local_node was reallocated (changed=1), old route
entries remained with stale v_node_info pointing to freed memory. The freed
memory got reused by a BGP peer's NODEINFO_Q, causing route_lookup to return
wrong node_id (b3b2b1b0afaeadac instead of local), which then failed at
etcp_route_send with 'no BGP route' and dropped packets to 10.23.2.1.

Changes:
- route_node.c: route_delete(old) before u_free + route_insert(new) after alloc
- utun_instance.c: remove duplicate route_insert (now atomic inside function)
- route_bgp.c: route_delete before freeing old peer NODEINFO_Q
- route_lib.c: routes_overlap now rejects only exact prefix+network duplicates
- tests/Makefile.am: add route_lib.o to test_route6_lib
chatgui
Evgeny 3 months ago
parent
commit
53d41d5c62
  1. 2
      AGENTS.md
  2. 27
      readme.md
  3. 1
      src/route_bgp.c
  4. 5
      src/route_lib.c
  5. 10
      src/route_node.c
  6. 3
      src/utun_instance.c
  7. 1
      tests/Makefile.am

2
AGENTS.md

@ -490,7 +490,7 @@ void lottie_animation_destroy(Lottie_Animation *anim);
- **Commit Messages:** Use imperative mood, concise (50-72 chars) - **Commit Messages:** Use imperative mood, concise (50-72 chars)
- **Language:** Mix of English (technical) and Russian (business logic) - **Language:** Mix of English (technical) and Russian (business logic)
- **Tags:** Version tags follow vX.Y.Z format - **Tags:** Version tags follow vX.Y.Z format
- "cp" or "кп" in prompt = do commit and push (всех изменений на текущий момент, не откатывая) - "cp" or "кп" in prompt = do commit and push (всех изменений на текущий момент, не откатывая). Запрещено откатывать "лишние" изменения сделаные вне сессии (если сильно надо - сделать бэкап). если нет дополнительных указаний - комить всё что изменилось как есть.
## Quick Start for New Features ## Quick Start for New Features
1. Add new source file to `src/Makefile.am` under `utun_SOURCES` 1. Add new source file to `src/Makefile.am` under `utun_SOURCES`

27
readme.md

@ -0,0 +1,27 @@
UTUN
Идея: объединить узлы в единую локальную сеть.
Чтобы узлы сами находили оптимальные линки между собой, пробивали NAT где это можно, где нельзя - выбирали посредника с хорошей связью; чтобы подсто было добавлять новые узлы и адреса узлов сразу виделись во всей сети.
Потенциальные варианты использования:
- локальная сеть. хочу объединить офис, сотрудников (включая их работчие подсети), телефоны, офисы, сервер доступа итд в одно адресное пространство.
- чат с файлообменником. узлы сети - это мемберы группы и одновременно сети.
- CDN. узлы - потребители контента - это мемберы сети, которые распространяют трафик.
То есть задача utun - обеспечить связность группы узлов и адаптацию работы всей сети к подключению-отключении отдельных узлов.
Механизмы:
1. Пробитие nat.
2. автообновление списка узлов и их адресов для подключения
3. шифрование трафика и маскировка handshake.
handshake просиходит без сигнатур по которым можно опреедлить тип сервиса, весь трафик выглядлит как случайный набор байт случайного размера
4. многоканальные подключения, агрегирование каналов, исключение мёртвых каналов
подключиться к узлу можно через несколько линков. UTUN будет объединять пропускную способность каналов, наблюдая за состоянием каналов, не допуская перегрузки и обеспечивая быстрые переповторы через другие каналы при потерях или большой задержке.
5. динамическая маршрутизация. Узлы могут назначать себе IP адреса и при подключении к сети анонсировать свои адреса/подсети.
это максимально упрощает добавление нового узла в сеть.
6. автоматический роутинг между узлами: узлы маршрутизируют трафик между собой.
используя статические подключения, прописанные в конфиге.
7. прямые подключения и поиск лучших подключений
узлы могут подключаться друг к другу напрямую, либо если оба узла за строгим NAT - выбирать оптимального посредника.
Узлы определяют свой тип подключения и NAT. Например у ростелеком - EIM NAT который можно использовать и для входящих подклюений.
Можно использовать IPv6.

1
src/route_bgp.c

@ -790,6 +790,7 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
if (need_alloc) { if (need_alloc) {
if (nodeinfo1) { if (nodeinfo1) {
if (bgp->instance->rt) route_delete(bgp->instance->rt, nodeinfo1);
queue_remove_data(bgp->nodes, &nodeinfo1->ll); queue_remove_data(bgp->nodes, &nodeinfo1->ll);
queue_free(paths); queue_free(paths);
queue_entry_free(&nodeinfo1->ll); queue_entry_free(&nodeinfo1->ll);

5
src/route_lib.c

@ -21,10 +21,7 @@ static uint32_t prefix_to_mask(uint8_t prefix) {
} }
static bool routes_overlap(uint32_t net1, uint8_t pre1, uint32_t net2, uint8_t pre2) { static bool routes_overlap(uint32_t net1, uint8_t pre1, uint32_t net2, uint8_t pre2) {
uint32_t mask1 = prefix_to_mask(pre1); if (pre1 == pre2 && net1 == net2) return true;
uint32_t mask2 = prefix_to_mask(pre2);
if ((net1 & mask2) == net2 && pre1 >= pre2) return true;
if ((net2 & mask1) == net1 && pre2 >= pre1) return true;
return false; return false;
} }

10
src/route_node.c

@ -10,6 +10,7 @@
#include "config_parser.h" #include "config_parser.h"
#include "route_node.h" #include "route_node.h"
#include "route_bgp.h" #include "route_bgp.h"
#include "route_lib.h"
#include "etcp_debug.h" #include "etcp_debug.h"
static const uint8_t* node_dyn_start(const struct NODEINFO* info) { static const uint8_t* node_dyn_start(const struct NODEINFO* info) {
@ -486,7 +487,10 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
} }
if (changed) { if (changed) {
if (bgp->local_node) u_free(bgp->local_node); if (bgp->local_node) {
if (instance->rt) route_delete(instance->rt, bgp->local_node);
u_free(bgp->local_node);
}
bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + dyn); bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + dyn);
if (!bgp->local_node) return -1; if (!bgp->local_node) return -1;
bgp->local_node->node.node_id = instance->node_id; bgp->local_node->node.node_id = instance->node_id;
@ -608,6 +612,10 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
DEBUG_INFO(DEBUG_CATEGORY_BGP, "my_nodeinfo updated: v4s=%d v4a=%d v6s=%d v6a=%d v4sub=%d v6sub=%d ver=%d", DEBUG_INFO(DEBUG_CATEGORY_BGP, "my_nodeinfo updated: v4s=%d v4a=%d v6s=%d v6a=%d v4sub=%d v6sub=%d ver=%d",
sock_count, addr_count, sock6_count, addr6_count, vc, vc6, bgp->local_node->node.ver); sock_count, addr_count, sock6_count, addr6_count, vc, vc6, bgp->local_node->node.ver);
if (instance->rt) {
if (!route_insert(instance->rt, bgp->local_node))
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_bgp_update_my_nodeinfo: failed to re-insert local routes after update");
}
} else { } else {
bgp->local_node->last_ver = bgp->local_node->node.ver; bgp->local_node->last_ver = bgp->local_node->node.ver;
} }

3
src/utun_instance.c

@ -126,8 +126,7 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
} else { } else {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized");
if (instance->rt && instance->bgp->local_node) { if (instance->rt && instance->bgp->local_node) {
route_bgp_update_my_nodeinfo(instance,instance->bgp); route_bgp_update_my_nodeinfo(instance, instance->bgp);
if (route_insert(instance->rt,instance->bgp->local_node)) DEBUG_INFO(DEBUG_CATEGORY_ROUTING,"Added local routes"); else DEBUG_WARN(DEBUG_CATEGORY_ROUTING,"Failed to add local routes");
} }
} }

1
tests/Makefile.am

@ -209,6 +209,7 @@ test_radix_LDADD = $(COMMON_LIBS)
test_route6_lib_SOURCES = test_route6_lib.c test_route6_lib_SOURCES = test_route6_lib.c
test_route6_lib_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib test_route6_lib_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
test_route6_lib_LDADD = $(top_builddir)/src/utun-route6_lib.o \ test_route6_lib_LDADD = $(top_builddir)/src/utun-route6_lib.o \
$(top_builddir)/src/utun-route_lib.o \
$(top_builddir)/src/utun-route_node.o \ $(top_builddir)/src/utun-route_node.o \
$(top_builddir)/src/utun-etcp_debug.o \ $(top_builddir)/src/utun-etcp_debug.o \
$(COMMON_LIBS) $(COMMON_LIBS)

Loading…
Cancel
Save