Browse Source

fix: node_registry crash — TOPO_NODE_REG_ENTRY node/lldata overlap

struct TOPO_NODE_REG_ENTRY имел node и ll.data[0] (гибкий массив) на одном смещении.
memcpy(re->ll.data, &node_id, 8) затирало re->node значением node_id,
из-за чего node_registry_find возвращал не указатель а битый node_id → SIGSEGV.

Убрал struct TOPO_NODE_REG_ENTRY, перешёл на явные смещения:
data[0..7]=ключ, data[8..15]=указатель, queue_entry_new(16).
topo_upd
Evgeny 2 months ago
parent
commit
7dee05c628
  1. 5
      src/routing_layer/topo_group.c
  2. 7
      src/routing_layer/topo_group.h
  3. 14
      src/routing_layer/topo_node.c

5
src/routing_layer/topo_group.c

@ -332,8 +332,9 @@ void topo_groups_destroy(struct UTUN_INSTANCE* instance) {
if (g->node_registry) {
struct ll_entry* re;
while ((re = queue_data_get(g->node_registry)) != NULL) {
struct TOPO_NODE_REG_ENTRY* r = (struct TOPO_NODE_REG_ENTRY*)re;
topo_node_unref(r->node);
struct TOPO_NODE* node;
memcpy(&node, re->data + 8, sizeof(node));
topo_node_unref(node);
queue_entry_free(re);
}
queue_free(g->node_registry);

7
src/routing_layer/topo_group.h

@ -119,10 +119,9 @@ struct ETCP_LINK;
#define TOPO_NODE_REGISTRY_HASH_SIZE 256
struct TOPO_NODE_REG_ENTRY {
struct ll_entry ll; // data[0..7] = node_id (hash key)
struct TOPO_NODE* node;
};
// node_registry entries: queue_entry_new(8 + sizeof(void*))
// data[0..7] = node_id (hash key, index_size=8)
// data[8..15] = struct TOPO_NODE* pointer
/**
* @brief Группа топологии (одна на каждый group_id: utun, чат-группа, …)

14
src/routing_layer/topo_node.c

@ -87,7 +87,10 @@ void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq) {
static struct TOPO_NODE* node_registry_find(struct TOPO_GROUPS* groups, uint64_t node_id) {
if (!groups || !groups->node_registry) return NULL;
struct ll_entry* e = queue_find_data_by_index(groups->node_registry, &node_id);
return e ? ((struct TOPO_NODE_REG_ENTRY*)e)->node : NULL;
if (!e) return NULL;
struct TOPO_NODE* node;
memcpy(&node, e->data + 8, sizeof(node));
return node;
}
struct TOPO_NODE* topo_node_registry_acquire(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
@ -98,16 +101,15 @@ struct TOPO_NODE* topo_node_registry_acquire(struct TOPO_GROUPS* groups, struct
topo_node_free_raw(groups, ni);
return existing;
}
struct ll_entry* qe = queue_entry_new(sizeof(struct TOPO_NODE_REG_ENTRY));
struct ll_entry* qe = queue_entry_new(8 + sizeof(struct TOPO_NODE*));
if (!qe) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "registry_acquire: queue_entry_new failed for node=%016llx", (unsigned long long)ni->node_id);
return NULL;
}
struct TOPO_NODE_REG_ENTRY* re = (struct TOPO_NODE_REG_ENTRY*)qe;
re->node = ni;
topo_node_ref(ni);
memcpy(re->ll.data, &ni->node_id, 8);
queue_data_put_with_index(groups->node_registry, &re->ll);
memcpy(qe->data, &ni->node_id, 8);
memcpy(qe->data + 8, &ni, sizeof(ni));
queue_data_put_with_index(groups->node_registry, qe);
return ni;
}

Loading…
Cancel
Save