The branch, master has been updated via 7d8546ee4353851f0543d0ca2c4c67cb0cc75aea (commit) from 746168df2e691058e601016110fae818c6a265c3 (commit)
http://gitweb.samba.org/?p=ctdb.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 7d8546ee4353851f0543d0ca2c4c67cb0cc75aea Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Oct 29 14:56:10 2012 +1100 daemon: Protect against double free of callback state while shutting down When CTDB is shut down and monitoring has been stopped, monitor_context gets freed and all the callback states hanging off it. This includes callback state for current_monitor, if the current monitor event has not yet finished. As a result, when the shutdown event is called, current_monitor->callback state is not NULL, but it's actually freed and it's a dangling reference. So before executing callback function and freeing callback state check if ctdb->monitor->monitor_context is not NULL. Signed-off-by: Amitay Isaacs <ami...@gmail.com> ----------------------------------------------------------------------- Summary of changes: include/ctdb_private.h | 1 + server/ctdb_monitor.c | 7 +++++++ server/eventscript.c | 5 +++-- 3 files changed, 11 insertions(+), 2 deletions(-) Changeset truncated at 500 lines: diff --git a/include/ctdb_private.h b/include/ctdb_private.h index fb54195..5b519fb 100644 --- a/include/ctdb_private.h +++ b/include/ctdb_private.h @@ -1343,6 +1343,7 @@ int ctdb_repack(struct ctdb_context *ctdb, int argc, const char **argv); void ctdb_block_signal(int signum); void ctdb_unblock_signal(int signum); int32_t ctdb_monitoring_mode(struct ctdb_context *ctdb); +bool ctdb_stopped_monitoring(struct ctdb_context *ctdb); int ctdb_set_child_logging(struct ctdb_context *ctdb); void ctdb_lockdown_memory(struct ctdb_context *ctdb); diff --git a/server/ctdb_monitor.c b/server/ctdb_monitor.c index bc21e5b..984f947 100644 --- a/server/ctdb_monitor.c +++ b/server/ctdb_monitor.c @@ -506,3 +506,10 @@ int32_t ctdb_monitoring_mode(struct ctdb_context *ctdb) return ctdb->monitor->monitoring_mode; } +/* + * Check if monitoring has been stopped + */ +bool ctdb_stopped_monitoring(struct ctdb_context *ctdb) +{ + return (ctdb->monitor->monitor_context == NULL ? true : false); +} diff --git a/server/eventscript.c b/server/eventscript.c index 6a75877..762f950 100644 --- a/server/eventscript.c +++ b/server/eventscript.c @@ -781,8 +781,9 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb, if (ctdb->current_monitor) { struct ctdb_event_script_state *ms = talloc_get_type(ctdb->current_monitor, struct ctdb_event_script_state); - /* cancel it */ - if (ms->callback != NULL) { + /* Cancel current monitor callback state only if monitoring + * context ctdb->monitor->monitor_context has not been freed */ + if (ms->callback != NULL && !ctdb_stopped_monitoring(ctdb)) { ms->callback->fn(ctdb, -ECANCELED, ms->callback->private_data); talloc_free(ms->callback); } -- CTDB repository