File pacemaker-libservices-completed-ops-arent-on-blocked-ops-list.patch of Package pacemaker.14737
commit 94a4c58f675d163085a055f59fd6c3a2c9f57c43
Author: Ken Gaillot <kgaillot@redhat.com>
Date: Mon Feb 27 14:17:01 2017 -0600
Fix: libservices: ensure completed ops aren't on blocked ops list
This refactors removal of a completed operation from the in-flight ops list
into a new internal function services_untrack_op(), which allows the
in-flight ops list and handle_blocked_ops() to be static to services.c.
The new function also ensures the op isn't on the blocked ops list,
which could otherwise result in a use-after-free bug.
Index: pacemaker/lib/services/services.c
===================================================================
--- pacemaker.orig/lib/services/services.c
+++ pacemaker/lib/services/services.c
@@ -55,7 +55,9 @@ GHashTable *recurring_actions = NULL;
GList *blocked_ops = NULL;
/* ops currently active (in-flight) */
-GList *inflight_ops = NULL;
+static GList *inflight_ops = NULL;
+
+static void handle_blocked_ops(void);
svc_action_t *
services_action_create(const char *name, const char *action, int interval, int timeout)
@@ -614,6 +616,23 @@ services_add_inflight_op(svc_action_t *
}
}
+/*!
+ * \internal
+ * \brief Stop tracking an operation that completed
+ *
+ * \param[in] op Operation to stop tracking
+ */
+void
+services_untrack_op(svc_action_t *op)
+{
+ /* Op is no longer in-flight or blocked */
+ inflight_ops = g_list_remove(inflight_ops, op);
+ blocked_ops = g_list_remove(blocked_ops, op);
+
+ /* Op is no longer blocking other ops, so check if any need to run */
+ handle_blocked_ops();
+}
+
gboolean
services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t *))
{
@@ -658,7 +677,7 @@ is_op_blocked(const char *rsc)
return FALSE;
}
-void
+static void
handle_blocked_ops(void)
{
GList *executed_ops = NULL;
Index: pacemaker/lib/services/services_linux.c
===================================================================
--- pacemaker.orig/lib/services/services_linux.c
+++ pacemaker/lib/services/services_linux.c
@@ -47,9 +47,6 @@
# include "crm/common/cib_secrets.h"
#endif
-/* ops currently active (in-flight) */
-extern GList *inflight_ops;
-
static inline void
set_fd_opts(int fd, int opts)
{
@@ -259,9 +256,7 @@ operation_finalize(svc_action_t * op)
op->pid = 0;
- inflight_ops = g_list_remove(inflight_ops, op);
-
- handle_blocked_ops();
+ services_untrack_op(op);
if (!recurring && op->synchronous == FALSE) {
/*
Index: pacemaker/lib/services/services_private.h
===================================================================
--- pacemaker.orig/lib/services/services_private.h
+++ pacemaker/lib/services/services_private.h
@@ -61,7 +61,7 @@ gboolean operation_finalize(svc_action_t
void services_add_inflight_op(svc_action_t *op);
-void handle_blocked_ops(void);
+void services_untrack_op(svc_action_t *op);
gboolean is_op_blocked(const char *rsc);