ncd: fix UAF on deferred UP delivery after handle close
ncd_deliver_up_cb (uasync_call_soon) держал сырой указатель handle h, который мог быть освобождён node_conn_direct_close/force_close раньше выполнения отложенного callback'а. Сохраняем токен call_soon в handle и отменяем его при close через uasync_call_soon_cancel.
This commit is contained in:
1 parent
e4557b0473
commit
de930b21a2
1 file changed
+19
-4
@@ -54,6 +54,7 @@ struct NODE_CONN_DIRECT {
|
||||
ncd_callback cb;
|
||||
void* cb_arg;
|
||||
struct NODE_CONN_DIRECT* next;
|
||||
void* deliver_up_token; /* handle uasync_call_soon отложенной доставки UP (для отмены при close) */
|
||||
};
|
||||
|
||||
/* ─── forward declarations ─── */
|
||||
@@ -379,9 +380,21 @@ static void ncd_connect_timeout_cb(void* arg) {
|
||||
|
||||
static void ncd_deliver_up_cb(void* arg) {
|
||||
struct NODE_CONN_DIRECT* h = (struct NODE_CONN_DIRECT*)arg;
|
||||
h->deliver_up_token = NULL; /* токен consumed — close больше не отменит освобождённый узел */
|
||||
if (h->cb) h->cb(h, NCD_EVENT_UP, h->cb_arg);
|
||||
}
|
||||
|
||||
/* Планирует отложенную доставку UP и сохраняет токен для возможной отмены при close. */
|
||||
static void ncd_schedule_deliver_up(struct UASYNC* ua, struct NODE_CONN_DIRECT* h) {
|
||||
h->deliver_up_token = uasync_call_soon(ua, h, ncd_deliver_up_cb);
|
||||
}
|
||||
|
||||
/* Отменяет pending-доставку UP (если ещё не сработала). Без этого h освобождается,
|
||||
* а отложенный ncd_deliver_up_cb читает freed-память — UAF. */
|
||||
static void ncd_cancel_deliver_up(struct NODE_CONN_DIRECT* h, struct UASYNC* ua) {
|
||||
if (h->deliver_up_token) { uasync_call_soon_cancel(ua, h->deliver_up_token); h->deliver_up_token = NULL; }
|
||||
}
|
||||
|
||||
/* ═══════════ FIN_WAIT ═══════════ */
|
||||
/*
|
||||
* fin_wait — состояние ожидания подтверждения закрытия от пира.
|
||||
@@ -573,7 +586,7 @@ int node_conn_direct_open(struct UTUN_INSTANCE* inst, uint64_t node_id,
|
||||
entry->handle_count++;
|
||||
*out_handle = h;
|
||||
if (entry->conn && entry->conn->state == 1 && entry->up) {
|
||||
uasync_call_soon(inst->ua, h, ncd_deliver_up_cb);
|
||||
ncd_schedule_deliver_up(inst->ua, h);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NCD, "[ncd] open REUSED (ready) node=0x%016llx handles=%d", (unsigned long long)node_id, entry->handle_count);
|
||||
} else if (entry->timed_out) {
|
||||
struct TOPO_NODE* ni = ncd_lookup_node(inst, node_id);
|
||||
@@ -613,7 +626,7 @@ int node_conn_direct_open(struct UTUN_INSTANCE* inst, uint64_t node_id,
|
||||
etcp_conn_add_cbk(conn, ncd_down_cb, entry, ETCP_CBK_EVENT_DOWN);
|
||||
|
||||
if (conn->state == 1 && entry->up) {
|
||||
uasync_call_soon(inst->ua, h, ncd_deliver_up_cb);
|
||||
ncd_schedule_deliver_up(inst->ua, h);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NCD, "[ncd] open REUSED new-entry (ready) node=0x%016llx conn=%p", (unsigned long long)node_id, (void*)conn);
|
||||
} else {
|
||||
{ struct TOPO_NODE* ni = ncd_lookup_node(inst, node_id);
|
||||
@@ -732,7 +745,7 @@ int node_conn_direct_open_node(struct UTUN_INSTANCE* inst, uint64_t node_id,
|
||||
entry->handle_count++;
|
||||
*out_handle = h;
|
||||
if (entry->conn && entry->conn->state == 1 && entry->up) {
|
||||
uasync_call_soon(inst->ua, h, ncd_deliver_up_cb);
|
||||
ncd_schedule_deliver_up(inst->ua, h);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NCD, "[ncd] open_node REUSED (ready) node=0x%016llx handles=%d", (unsigned long long)node_id, entry->handle_count);
|
||||
} else if (entry->timed_out) {
|
||||
ncd_revive_entry(entry, inst, ni, specific_sock);
|
||||
@@ -769,7 +782,7 @@ int node_conn_direct_open_node(struct UTUN_INSTANCE* inst, uint64_t node_id,
|
||||
etcp_conn_add_cbk(conn, ncd_down_cb, entry, ETCP_CBK_EVENT_DOWN);
|
||||
|
||||
if (conn->state == 1 && entry->up) {
|
||||
uasync_call_soon(inst->ua, h, ncd_deliver_up_cb);
|
||||
ncd_schedule_deliver_up(inst->ua, h);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NCD, "[ncd] open_node REUSED new-entry (ready) node=0x%016llx conn=%p", (unsigned long long)node_id, (void*)conn);
|
||||
} else {
|
||||
ncd_create_links(entry, ni, specific_sock);
|
||||
@@ -863,6 +876,7 @@ void node_conn_direct_close(struct NODE_CONN_DIRECT* h) {
|
||||
if (!h) return;
|
||||
struct ncd_entry* entry = h->entry;
|
||||
if (!entry) { u_free(h); return; }
|
||||
ncd_cancel_deliver_up(h, entry->ua);
|
||||
|
||||
uint64_t node_id = entry->node_id;
|
||||
struct ETCP_CONN* conn = entry->conn;
|
||||
@@ -953,6 +967,7 @@ void node_conn_direct_force_close(struct NODE_CONN_DIRECT* h) {
|
||||
if (!h) return;
|
||||
if (!h->entry) { DEBUG_ERROR(DEBUG_CATEGORY_NCD, "[ncd] force_close: h=%p h->entry=NULL", h); u_free(h); return; }
|
||||
struct ncd_entry* entry = h->entry;
|
||||
ncd_cancel_deliver_up(h, entry->ua);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NCD, "[ncd] force_close h=%p entry=%p node=0x%016llx handles=%d",
|
||||
h, entry, (unsigned long long)entry->node_id, entry->handle_count);
|
||||
|
||||
|
||||
Reference in new issue
Block a user