From aa73e9d8cb1a9ba486c1664e4179c34b36e5fc88 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Thu, 2 Jul 2026 15:02:11 +0300 Subject: [PATCH] =?UTF-8?q?route=5Fconnectivity:=20fix=20UAF=20in=20conn?= =?UTF-8?q?=5Fprobe=5Ffinish=20=E2=80=94=20break=20ctx->nq=20on=20cancel?= =?UTF-8?q?=5Fnode,=20always=20free=20ctx=20in=20finish?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/control_server.c | 1 + src/route_connectivity.c | 61 +++++++++++++++++++++++----------------- src/route_node.h | 1 + 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/control_server.c b/src/control_server.c index c89c1c65..4f971282 100644 --- a/src/control_server.c +++ b/src/control_server.c @@ -91,6 +91,7 @@ static void client_write_callback(socket_t fd, void* arg); static void client_except_callback(socket_t fd, void* arg); static void handle_client_data(struct control_server* server, struct control_client* client); static void close_client(struct control_server* server, struct control_client* client); +static void control_client_idle_cb(void* arg); static void send_conn_list(struct control_server* server, struct control_client* client, uint8_t seq_id); static void send_socket_list(struct control_server* server, struct control_client* client, uint8_t seq_id); diff --git a/src/route_connectivity.c b/src/route_connectivity.c index a2d9352d..66b540f8 100644 --- a/src/route_connectivity.c +++ b/src/route_connectivity.c @@ -245,33 +245,36 @@ static void conn_probe_single_cb(int success, uint16_t rtt, void* arg, } static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) { - if (!ctx || !ctx->nq) return; - struct NODE_CONNECTIVITY* c = &ctx->nq->connectivity; - - switch (ctx->addr_type) { - case ADDR_TYPE_INTERFACE: - c->interface_status = ok ? PROBE_RESULT_REACHABLE : (c->interface_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->interface_status); - if (ok && ctx->best_across_sockets < c->interface_min_rtt) c->interface_min_rtt = ctx->best_across_sockets; - c->interface_probe_time = get_time_tb(); - break; - case ADDR_TYPE_NAT: - c->nat_status = ok ? PROBE_RESULT_REACHABLE : (c->nat_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->nat_status); - if (ok && ctx->best_across_sockets < c->nat_min_rtt) c->nat_min_rtt = ctx->best_across_sockets; - c->nat_probe_time = get_time_tb(); - break; - case ADDR_TYPE_REAL: - c->real_status = ok ? PROBE_RESULT_REACHABLE : (c->real_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->real_status); - if (ok && ctx->best_across_sockets < c->real_min_rtt) c->real_min_rtt = ctx->best_across_sockets; - c->real_probe_time = get_time_tb(); - break; - } + if (!ctx) return; + if (ctx->nq) { + struct NODE_CONNECTIVITY* c = &ctx->nq->connectivity; + if (c->probe_ctx == ctx) c->probe_ctx = NULL; + + switch (ctx->addr_type) { + case ADDR_TYPE_INTERFACE: + c->interface_status = ok ? PROBE_RESULT_REACHABLE : (c->interface_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->interface_status); + if (ok && ctx->best_across_sockets < c->interface_min_rtt) c->interface_min_rtt = ctx->best_across_sockets; + c->interface_probe_time = get_time_tb(); + break; + case ADDR_TYPE_NAT: + c->nat_status = ok ? PROBE_RESULT_REACHABLE : (c->nat_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->nat_status); + if (ok && ctx->best_across_sockets < c->nat_min_rtt) c->nat_min_rtt = ctx->best_across_sockets; + c->nat_probe_time = get_time_tb(); + break; + case ADDR_TYPE_REAL: + c->real_status = ok ? PROBE_RESULT_REACHABLE : (c->real_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->real_status); + if (ok && ctx->best_across_sockets < c->real_min_rtt) c->real_min_rtt = ctx->best_across_sockets; + c->real_probe_time = get_time_tb(); + break; + } - if (c->pending_count > 0) c->pending_count--; - if (c->pending_count == 0) { - c->probe_status = PROBE_STATUS_DONE; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe DONE for node %016llx: intf=%d nat=%d real=%d", - (unsigned long long)ctx->nq->node.node_id, - c->interface_status, c->nat_status, c->real_status); + if (c->pending_count > 0) c->pending_count--; + if (c->pending_count == 0) { + c->probe_status = PROBE_STATUS_DONE; + DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe DONE for node %016llx: intf=%d nat=%d real=%d", + (unsigned long long)ctx->nq->node.node_id, + c->interface_status, c->nat_status, c->real_status); + } } u_free(ctx); @@ -349,6 +352,7 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEIN ctx->timeout_ms = CONN_PROBE_TIMEOUT_MS; ctx->best_across_sockets = 65535; + nq->connectivity.probe_ctx = ctx; pend++; conn_probe_start_series(ctx); } @@ -407,6 +411,7 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEIN ctx->timeout_ms = CONN_PROBE_TIMEOUT_MS; ctx->best_across_sockets = 65535; + nq->connectivity.probe_ctx = ctx; pend++; conn_probe_start_series(ctx); } @@ -428,6 +433,10 @@ void route_connectivity_cancel_node(struct UTUN_INSTANCE* instance, struct NODEI if (!instance || !nq) return; nq->connectivity.probe_status = PROBE_STATUS_NONE; nq->connectivity.pending_count = 0; + if (nq->connectivity.probe_ctx) { + ((struct conn_probe_ctx*)nq->connectivity.probe_ctx)->nq = NULL; + nq->connectivity.probe_ctx = NULL; + } DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe cancelled for node %016llx", (unsigned long long)nq->node.node_id); } diff --git a/src/route_node.h b/src/route_node.h index 9048e9c6..a54f22ed 100644 --- a/src/route_node.h +++ b/src/route_node.h @@ -56,6 +56,7 @@ struct NODE_CONNECTIVITY { uint64_t nat_probe_time; uint64_t real_probe_time; uint64_t ping_req_time; // время последнего полученного ping request от этого узла (0.1ms tb) + void* probe_ctx; // активный conn_probe_ctx (для cancel) }; /**