Browse Source

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.
topo_upd
evgeny 2 months ago
parent
commit
21a0ee6caf
  1. 13
      src/routing_layer/conn_mgr_core.c

13
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);

Loading…
Cancel
Save