From: Vsevolod Stakhov Date: Thu, 16 Oct 2025 07:43:22 +0000 (+0100) Subject: [Fix] Fix use-after-free in fuzzy TCP connection cleanup X-Git-Tag: 3.14.0~71 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d2f543ed8d507ac261552f97cbe25935902dc61;p=thirdparty%2Frspamd.git [Fix] Fix use-after-free in fuzzy TCP connection cleanup Cache the upstream name as a string when creating TCP connections to avoid dereferencing the upstream pointer during connection cleanup. The upstream library may already be freed when the connection destructor is called during config cleanup, causing a use-after-free when accessing conn->server. --- diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index 674912b748..0c2f5a617f 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -228,6 +228,7 @@ struct fuzzy_tcp_write_buf { struct fuzzy_tcp_connection { struct fuzzy_rule *rule; /* Parent rule */ struct upstream *server; /* Connected upstream */ + char *server_name; /* Cached upstream name for logging */ rspamd_inet_addr_t *addr; /* Server address */ int fd; /* Socket file descriptor */ @@ -564,8 +565,12 @@ fuzzy_tcp_connection_free(struct fuzzy_tcp_connection *conn) } msg_debug("fuzzy_tcp: freeing connection to %s for rule %s", - rspamd_upstream_name(conn->server), - conn->rule->name); + conn->server_name ? conn->server_name : "unknown", + conn->rule ? conn->rule->name : "unknown"); + + if (conn->server_name) { + g_free(conn->server_name); + } g_free(conn); } @@ -669,6 +674,7 @@ fuzzy_tcp_connect_async(struct fuzzy_rule *rule, conn = fuzzy_tcp_connection_new(rule, task->event_loop); conn->fd = fd; conn->server = upstream; + conn->server_name = g_strdup(rspamd_upstream_name(upstream)); conn->addr = addr; conn->connecting = TRUE; conn->connect_start = rspamd_get_calendar_ticks(); @@ -800,7 +806,7 @@ fuzzy_tcp_connection_cleanup(struct fuzzy_tcp_connection *conn, const char *reas } msg_info("fuzzy_tcp: cleaning up connection to %s for rule %s, reason: %s", - rspamd_upstream_name(conn->server), + conn->server_name ? conn->server_name : "unknown", conn->rule->name, reason ? reason : "unknown");