From 21a0ee6caf13b8656039af7332b28e95c88990a4 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 4 Aug 2026 20:53:38 +0300 Subject: [PATCH] conn_mgr: fix use-after-free in invite NCD callback cleanup cm_invite_fail and cm_handle_invite_info_resp: always close invite's NCD handle before freeing the invite struct. Previously the NCD close was skipped when nq->handle != NULL (success path never closed it at all), leaving cm_invite_ncd_callback registered with a dangling pointer. On subsequent NCD DOWN event the stale callback caused SIGSEGV. --- src/routing_layer/conn_mgr_core.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/routing_layer/conn_mgr_core.c b/src/routing_layer/conn_mgr_core.c index f48ad5ab..c487cc2d 100644 --- a/src/routing_layer/conn_mgr_core.c +++ b/src/routing_layer/conn_mgr_core.c @@ -789,6 +789,7 @@ void cm_handle_invite_info_resp(struct CONN_MGR* mgr, struct ETCP_CONN* conn, co DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "invite: membership CONFIRMED by 0x%016llx name=\"%.*s\" — joined to channel, handle registered", (unsigned long long)inv->node_id, resp->node_name_len, resp->node_name_len ? (const char*)resp->node_name : ""); if (inv->cb) inv->cb(inv->handle, inv->node_id, inv->mgr->group->group_id, CONN_EVENT_JOIN, inv->cb_arg); + if (inv->ncd_handle) { node_conn_direct_close(inv->ncd_handle); inv->ncd_handle = NULL; } cm_invite_cleanup(inv); } @@ -813,17 +814,7 @@ void cm_invite_fail(struct cm_invite_pending* inv) { if (e) queue_remove_data(inv->mgr->instance->tcp_connections, e); stcp_link_close(inv->tcp_link); inv->tcp_link = NULL; } - if (inv->ncd_handle) { - struct TOPO_GROUP_NODE* nq = topo_node_find_by_id(inv->mgr->group, inv->node_id); - if (nq && nq->handle != NULL) { - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: invite fail node=0x%016llx — handle registered, skip NCD close", - (unsigned long long)inv->node_id); - } else { - DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "cm_invite_fail: CLOSE NCD, nq=%p", (void*)nq); - node_conn_direct_close(inv->ncd_handle); - } - inv->ncd_handle = NULL; - } + if (inv->ncd_handle) { node_conn_direct_close(inv->ncd_handle); inv->ncd_handle = NULL; } if (inv->temp_nq) { queue_remove_data(inv->mgr->group->nodes, &inv->temp_nq->ll); topo_nodeq_free_group_fields(inv->mgr->instance->topo_groups, inv->temp_nq);