File bug-964183_pacemaker-crmd-remote-disconnect-use-after-free.patch of Package pacemaker.1630
commit 59c0fa751cf8293fee3344d404540d55f363ab3f
Author: Gao,Yan <ygao@suse.com>
Date: Thu Feb 18 18:00:33 2016 +0100
Fix: crmd: Prevent use-after-free when an unexpected remote client takes over
diff --git a/crmd/crmd_lrm.h b/crmd/crmd_lrm.h
index 0e7ff48..412ce5b 100644
--- a/crmd/crmd_lrm.h
+++ b/crmd/crmd_lrm.h
@@ -123,6 +123,7 @@ lrm_state_t *lrm_state_find_or_create(const char *node_name);
* Regular resources go to the lrmd, and remote connection resources are
* handled locally in the crmd.
*/
+void lrm_state_disconnect_only(lrm_state_t * lrm_state);
void lrm_state_disconnect(lrm_state_t * lrm_state);
int lrm_state_ipc_connect(lrm_state_t * lrm_state);
int lrm_state_remote_connect_async(lrm_state_t * lrm_state, const char *server, int port,
diff --git a/crmd/lrm_state.c b/crmd/lrm_state.c
index 0f50fef..0e0c650 100644
--- a/crmd/lrm_state.c
+++ b/crmd/lrm_state.c
@@ -327,7 +327,7 @@ remote_proxy_disconnect_by_node(const char * node_name)
}
void
-lrm_state_disconnect(lrm_state_t * lrm_state)
+lrm_state_disconnect_only(lrm_state_t * lrm_state)
{
int removed = 0;
@@ -344,6 +344,16 @@ lrm_state_disconnect(lrm_state_t * lrm_state)
removed = g_hash_table_foreach_remove(lrm_state->pending_ops, fail_pending_op, lrm_state);
crm_trace("Synthesized %d operation failures for %s", removed, lrm_state->node_name);
}
+}
+
+void
+lrm_state_disconnect(lrm_state_t * lrm_state)
+{
+ if (!lrm_state->conn) {
+ return;
+ }
+
+ lrm_state_disconnect_only(lrm_state);
lrmd_api_delete(lrm_state->conn);
lrm_state->conn = NULL;
diff --git a/crmd/remote_lrmd_ra.c b/crmd/remote_lrmd_ra.c
index 181c462..27c951a 100644
--- a/crmd/remote_lrmd_ra.c
+++ b/crmd/remote_lrmd_ra.c
@@ -492,8 +492,11 @@ remote_lrm_op_callback(lrmd_event_data_t * op)
if (ra_data->migrate_status == expect_takeover) {
ra_data->migrate_status = takeover_complete;
} else {
- crm_err("Unexpected pacemaker_remote client takeover. Disconnecting");
- lrm_state_disconnect(lrm_state);
+ crm_err("Unexpected pacemaker_remote client takeover for %s. Disconnecting", op->remote_nodename);
+ /* In this case, lrmd_tls_connection_destroy() will be called under the control of mainloop. */
+ /* Do not free lrm_state->conn yet. */
+ /* It'll be freed in the following stop action. */
+ lrm_state_disconnect_only(lrm_state);
}
return;
}