Browse Source

etcp: защита от UAF в start_keepalive_timer/enter_ready_tcp + диагностика указателей

- start_keepalive_timer: guard !link->etcp->instance->ua (SIGSEGV на 80 строке)
- etcp_link_enter_ready_tcp: return при etcp->state==2 после reinit/apply_reset/conn_ready
- tcp_server_on_link/enter_ready_tcp: DEBUG_CATEGORY_DEBUG с адресами link/etcp/inst/ua
- topo_node: убрать лишние DEBUG_CATEGORY_DEBUG (chain_rtt)
v2
evgeny 3 weeks ago
parent
commit
be1f08b43e
  1. 7
      src/routing_layer/topo_node.c
  2. 7
      src/transport_layer/etcp_connections.c
  3. 7
      src/transport_layer/etcp_keepalive.c

7
src/routing_layer/topo_node.c

@ -564,24 +564,17 @@ void topo_node_ping_update_rtt(struct TOPO_GROUPS* groups, uint64_t node_id, uin
uint16_t topo_get_chain_rtt(struct TOPO_GROUP_NODE* nq) { uint16_t topo_get_chain_rtt(struct TOPO_GROUP_NODE* nq) {
if (!nq || !nq->paths || !nq->paths->head) { if (!nq || !nq->paths || !nq->paths->head) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chain_rtt: nid=%016llx NO PATHS", (unsigned long long)(nq ? nq->node_id : 0));
return 0xFFFF; return 0xFFFF;
} }
uint16_t best = 0xFFFF; uint16_t best = 0xFFFF;
for (struct ll_entry* e = nq->paths->head; e; e = e->next) { for (struct ll_entry* e = nq->paths->head; e; e = e->next) {
struct TOPO_NODEPATH* p = (struct TOPO_NODEPATH*)e; struct TOPO_NODEPATH* p = (struct TOPO_NODEPATH*)e;
if (!p->conn || !p->conn->links_up || !p->conn->rtt_last) { if (!p->conn || !p->conn->links_up || !p->conn->rtt_last) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chain_rtt: nid=%016llx SKIP conn=%s up=%d rtt=%u cum=%u",
(unsigned long long)nq->node_id, p->conn ? p->conn->log_name : "NULL",
p->conn ? p->conn->links_up : 0, p->conn ? p->conn->rtt_last : 0, p->cumulative_rtt);
continue; continue;
} }
uint16_t total = (uint16_t)((uint32_t)p->conn->rtt_last + p->cumulative_rtt); uint16_t total = (uint16_t)((uint32_t)p->conn->rtt_last + p->cumulative_rtt);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chain_rtt: nid=%016llx PATH %s rtt=%u+cum=%u=%u best=%u",
(unsigned long long)nq->node_id, p->conn->log_name, p->conn->rtt_last, p->cumulative_rtt, total, best);
if (total < best) best = total; if (total < best) best = total;
} }
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chain_rtt: nid=%016llx RESULT=%u(0x%04X)", (unsigned long long)nq->node_id, best, best);
return best; return best;
} }

7
src/transport_layer/etcp_connections.c

@ -48,6 +48,8 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link);
// TCP server: on new incoming connection → create ETCP_LINK + enter ready // TCP server: on new incoming connection → create ETCP_LINK + enter ready
void tcp_server_on_link(struct stcp_link *link, struct ETCP_SOCKET *tcp_sock) { void tcp_server_on_link(struct stcp_link *link, struct ETCP_SOCKET *tcp_sock) {
struct UTUN_INSTANCE *inst = tcp_sock->instance; struct UTUN_INSTANCE *inst = tcp_sock->instance;
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "tcp_server_on_link: link=%p tcp_sock=%p inst=%p inst->ua=%p",
(void*)link, (void*)tcp_sock, (void*)inst, (void*)(inst ? inst->ua : NULL));
const uint8_t *pubkey = stcp_link_get_peer_pubkey(link); const uint8_t *pubkey = stcp_link_get_peer_pubkey(link);
if (!pubkey) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: no peer pubkey"); return; } if (!pubkey) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: no peer pubkey"); return; }
uint64_t node_id = sc_derive_node_id_from_pubkey(pubkey); uint64_t node_id = sc_derive_node_id_from_pubkey(pubkey);
@ -1066,6 +1068,9 @@ void etcp_link_close(struct ETCP_LINK* link) {
void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) { void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) {
if (!link || !link->etcp) return; if (!link || !link->etcp) return;
struct ETCP_CONN *etcp = link->etcp; struct ETCP_CONN *etcp = link->etcp;
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "enter_ready_tcp: link=%p etcp=%p inst=%p ua=%p conn_state=%d tcp_link=%p",
(void*)link, (void*)etcp, (void*)etcp->instance, (void*)(etcp->instance ? etcp->instance->ua : NULL),
etcp->state, (void*)link->tcp_link);
/* Синхронизация got_initial_pkt: если я грязный (1) а пир чистый (0) → сбросить */ /* Синхронизация got_initial_pkt: если я грязный (1) а пир чистый (0) → сбросить */
if (link->tcp_link) { if (link->tcp_link) {
@ -1077,6 +1082,7 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) {
etcp_conn_reinit(etcp, "tcp peer clean"); etcp_conn_reinit(etcp, "tcp peer clean");
} }
etcp_conn_apply_peer_reset_id(etcp, peer_rid); etcp_conn_apply_peer_reset_id(etcp, peer_rid);
if (etcp->state == 2) { DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "enter_ready_tcp: conn DELETED after reinit/apply_reset, link=%p", (void*)link); return; }
link->peer_device_type = stcp_link_get_peer_device_type(link->tcp_link); link->peer_device_type = stcp_link_get_peer_device_type(link->tcp_link);
{ uint16_t peer_ka = stcp_link_get_peer_keepalive_interval(link->tcp_link); { uint16_t peer_ka = stcp_link_get_peer_keepalive_interval(link->tcp_link);
@ -1092,6 +1098,7 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) {
etcp->tcp_link_count++; etcp->tcp_link_count++;
if (link->tcp_link) { const uint8_t* ed = stcp_link_get_peer_ed25519_pubkey(link->tcp_link); if (ed) memcpy(etcp->peer_ed25519_pubkey, ed, SC_PUBKEY_SIZE); } if (link->tcp_link) { const uint8_t* ed = stcp_link_get_peer_ed25519_pubkey(link->tcp_link); if (ed) memcpy(etcp->peer_ed25519_pubkey, ed, SC_PUBKEY_SIZE); }
if (etcp->initialized == 0) etcp_conn_ready(etcp); if (etcp->initialized == 0) etcp_conn_ready(etcp);
if (etcp->state == 2) { DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "enter_ready_tcp: conn DELETED after conn_ready, link=%p", (void*)link); return; }
etcp_link_send_keepalive(link); etcp_link_send_keepalive(link);
start_keepalive_timer(link); start_keepalive_timer(link);
loadbalancer_link_ready(link); loadbalancer_link_ready(link);

7
src/transport_layer/etcp_keepalive.c

@ -69,6 +69,13 @@ static int etcp_all_links_down(struct ETCP_CONN* etcp) {
} }
void start_keepalive_timer(struct ETCP_LINK* link) { void start_keepalive_timer(struct ETCP_LINK* link) {
if (!link || !link->etcp || !link->etcp->instance || !link->etcp->instance->ua) {
DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "start_keepalive_timer: BAD link=%p etcp=%p inst=%p ua=%p",
(void*)link, (void*)(link ? link->etcp : NULL),
(void*)(link && link->etcp ? link->etcp->instance : NULL),
(void*)(link && link->etcp && link->etcp->instance ? link->etcp->instance->ua : NULL));
return;
}
// Start keepalive timer // Start keepalive timer
if (link->init_timer) {// cancel init timer if (link->init_timer) {// cancel init timer
uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer); uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer);

Loading…
Cancel
Save