Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.5:Update
pacemaker.34783
bsc#1209640-0001-Fix-controller-avoid-use-after...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File bsc#1209640-0001-Fix-controller-avoid-use-after-free-when-disconnecti.patch of Package pacemaker.34783
From db7f6f3e99524a613758747ffcedd29fc067bbc1 Mon Sep 17 00:00:00 2001 From: "Gao,Yan" <ygao@suse.com> Date: Thu, 23 Mar 2023 19:05:13 +0100 Subject: [PATCH] Fix: controller: avoid use-after-free when disconnecting proxy IPCs during shutdown Previously internal_lrm_state_destroy() directly freed and removed any relevant proxy entries from proxy_table, which could potentially leave the proxy IPCs connected and cause use-after-free when g_main_context_dispatch() -> ... -> remote_proxy_disconnected() was later called in crmd_exit(). The solution is to make sure any connected proxies get disconnected. So that remote_proxy_disconnected() will be called and as well remove the entries from proxy_table. --- daemons/controld/controld_execd_state.c | 86 ++++++++++++++----------- 1 file changed, 47 insertions(+), 39 deletions(-) Index: pacemaker-2.0.4+20200616.2deceaa3a/daemons/controld/controld_execd_state.c =================================================================== --- pacemaker-2.0.4+20200616.2deceaa3a.orig/daemons/controld/controld_execd_state.c +++ pacemaker-2.0.4+20200616.2deceaa3a/daemons/controld/controld_execd_state.c @@ -156,6 +156,45 @@ remote_proxy_remove_by_node(gpointer key return FALSE; } +static remote_proxy_t * +find_connected_proxy_by_node(const char * node_name) +{ + GHashTableIter gIter; + remote_proxy_t *proxy = NULL; + + CRM_CHECK(proxy_table != NULL, return NULL); + + g_hash_table_iter_init(&gIter, proxy_table); + + while (g_hash_table_iter_next(&gIter, NULL, (gpointer *) &proxy)) { + if (proxy->source + && safe_str_eq(node_name, proxy->node_name)) { + return proxy; + } + } + + return NULL; +} + +static void +remote_proxy_disconnect_by_node(const char * node_name) +{ + remote_proxy_t *proxy = NULL; + + CRM_CHECK(proxy_table != NULL, return); + + while ((proxy = find_connected_proxy_by_node(node_name)) != NULL) { + /* mainloop_del_ipc_client() eventually calls remote_proxy_disconnected() + * , which removes the entry from proxy_table. + * Do not do this in a g_hash_table_iter_next() loop. */ + if (proxy->source) { + mainloop_del_ipc_client(proxy->source); + } + } + + return; +} + static void internal_lrm_state_destroy(gpointer data) { @@ -165,7 +204,16 @@ internal_lrm_state_destroy(gpointer data return; } - crm_trace("Destroying proxy table %s with %d members", lrm_state->node_name, g_hash_table_size(proxy_table)); + /* Rather than directly remove the recorded proxy entries from proxy_table, + * make sure any connected proxies get disconnected. So that + * remote_proxy_disconnected() will be called and as well remove the + * entries from proxy_table. + */ + remote_proxy_disconnect_by_node(lrm_state->node_name); + + crm_trace("Destroying proxy table %s with %u members", + lrm_state->node_name, g_hash_table_size(proxy_table)); + // Just in case there's still any leftovers in proxy_table g_hash_table_foreach_remove(proxy_table, remote_proxy_remove_by_node, (char *) lrm_state->node_name); remote_ra_cleanup(lrm_state); lrmd_api_delete(lrm_state->conn); @@ -285,45 +333,6 @@ lrm_state_get_list(void) return g_hash_table_get_values(lrm_state_table); } -static remote_proxy_t * -find_connected_proxy_by_node(const char * node_name) -{ - GHashTableIter gIter; - remote_proxy_t *proxy = NULL; - - CRM_CHECK(proxy_table != NULL, return NULL); - - g_hash_table_iter_init(&gIter, proxy_table); - - while (g_hash_table_iter_next(&gIter, NULL, (gpointer *) &proxy)) { - if (proxy->source - && safe_str_eq(node_name, proxy->node_name)) { - return proxy; - } - } - - return NULL; -} - -static void -remote_proxy_disconnect_by_node(const char * node_name) -{ - remote_proxy_t *proxy = NULL; - - CRM_CHECK(proxy_table != NULL, return); - - while ((proxy = find_connected_proxy_by_node(node_name)) != NULL) { - /* mainloop_del_ipc_client() eventually calls remote_proxy_disconnected() - * , which removes the entry from proxy_table. - * Do not do this in a g_hash_table_iter_next() loop. */ - if (proxy->source) { - mainloop_del_ipc_client(proxy->source); - } - } - - return; -} - void lrm_state_disconnect_only(lrm_state_t * lrm_state) {
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor