From 08f7f85477610a4916c1ec866aa467b28f1bbec3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 26 Jul 2010 13:58:48 +0930 Subject: [PATCH] takeover: prevent crash by avoiding free in traverse on RST timeout After 5 attempts to send a RST to a client without any response, we free "con"; this is done during a traverse. This frees the node we are walking through (the node is made a child of "con" down in rb_tree.c's trbt_create_node() (Valgrind would catch this, as Martin confirmed). So, we create a temporary parent and reparent onto that; then we free that parent after the traverse, thus deleting the unwanted nodes. CQ:S1019041 Signed-off-by: Rusty Russell --- server/ctdb_takeover.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/server/ctdb_takeover.c b/server/ctdb_takeover.c index 52db386d..9a8f16fe 100644 --- a/server/ctdb_takeover.c +++ b/server/ctdb_takeover.c @@ -2259,7 +2259,8 @@ static void tickle_connection_traverse(void *param, void *data) /* have tried too many times, just give up */ if (con->count >= 5) { - talloc_free(con); + /* can't delete in traverse: reparent to delete_cons */ + talloc_steal(param, con); return; } @@ -2279,11 +2280,13 @@ static void ctdb_tickle_sentenced_connections(struct event_context *ev, struct t struct timeval t, void *private_data) { struct ctdb_kill_tcp *killtcp = talloc_get_type(private_data, struct ctdb_kill_tcp); - + void *delete_cons = talloc_new(NULL); /* loop over all connections sending tickle ACKs */ - trbt_traversearray32(killtcp->connections, KILLTCP_KEYLEN, tickle_connection_traverse, NULL); + trbt_traversearray32(killtcp->connections, KILLTCP_KEYLEN, tickle_connection_traverse, delete_cons); + /* now we've finished traverse, it's safe to do deletion. */ + talloc_free(delete_cons); /* If there are no more connections to kill we can remove the entire killtcp structure -- 2.34.1