Blame SOURCES/006-fence-output-fix.patch

c54a00
From 70577be56d841d2f58545877d36f3c3eaeaaae63 Mon Sep 17 00:00:00 2001
c54a00
From: Klaus Wenninger <klaus.wenninger@aon.at>
c54a00
Date: Wed, 3 Apr 2019 16:11:20 +0200
c54a00
Subject: [PATCH] Fix: service-lib: avoid call-pattern leading to
c54a00
 use-after-free
c54a00
c54a00
---
c54a00
 include/crm/services.h          |  8 +++++++-
c54a00
 lib/fencing/st_client.c         | 18 +++++++++++++++---
c54a00
 lib/services/services.c         | 13 ++++++++++++-
c54a00
 lib/services/services_linux.c   |  5 +++++
c54a00
 lib/services/services_private.h |  1 +
c54a00
 5 files changed, 40 insertions(+), 5 deletions(-)
c54a00
c54a00
diff --git a/include/crm/services.h b/include/crm/services.h
c54a00
index eddafc3..cbb2354 100644
c54a00
--- a/include/crm/services.h
c54a00
+++ b/include/crm/services.h
c54a00
@@ -307,11 +307,17 @@ typedef struct svc_action_s {
c54a00
  *
c54a00
  * \param[in] op services action data
c54a00
  * \param[in] action_callback callback for when the action completes
c54a00
+ * \param[in] action_fork_callback callback for when action forked successfully
c54a00
  *
c54a00
  * \retval TRUE succesfully started execution
c54a00
  * \retval FALSE failed to start execution, no callback will be received
c54a00
  */
c54a00
-    gboolean services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t *));
c54a00
+    gboolean services_action_async_fork_notify(svc_action_t * op,
c54a00
+        void (*action_callback) (svc_action_t *),
c54a00
+        void (*action_fork_callback) (svc_action_t *));
c54a00
+
c54a00
+    gboolean services_action_async(svc_action_t * op,
c54a00
+                                   void (*action_callback) (svc_action_t *));
c54a00
 
c54a00
     gboolean services_action_cancel(const char *name, const char *action, int interval);
c54a00
 
c54a00
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
c54a00
index 1c56cf4..0c1eadc 100644
c54a00
--- a/lib/fencing/st_client.c
c54a00
+++ b/lib/fencing/st_client.c
c54a00
@@ -827,6 +827,18 @@ stonith_action_async_done(svc_action_t *svc_action)
c54a00
     stonith__destroy_action(action);
c54a00
 }
c54a00
 
c54a00
+static void
c54a00
+stonith_action_async_forked(svc_action_t *svc_action)
c54a00
+{
c54a00
+    stonith_action_t *action = (stonith_action_t *) svc_action->cb_data;
c54a00
+
c54a00
+    action->pid = svc_action->pid;
c54a00
+    action->svc_action = svc_action;
c54a00
+
c54a00
+    crm_trace("Child process %d performing action '%s' successfully forked",
c54a00
+              action->pid, action->action);
c54a00
+}
c54a00
+
c54a00
 static int
c54a00
 internal_stonith_action_execute(stonith_action_t * action)
c54a00
 {
c54a00
@@ -873,12 +885,12 @@ internal_stonith_action_execute(stonith_action_t * action)
c54a00
 
c54a00
     if (action->async) {
c54a00
         /* async */
c54a00
-        if(services_action_async(svc_action, &stonith_action_async_done) == FALSE) {
c54a00
+        if(services_action_async_fork_notify(svc_action,
c54a00
+            &stonith_action_async_done,
c54a00
+            &stonith_action_async_forked) == FALSE) {
c54a00
             services_action_free(svc_action);
c54a00
             svc_action = NULL;
c54a00
         } else {
c54a00
-            action->pid = svc_action->pid;
c54a00
-            action->svc_action = svc_action;
c54a00
             rc = 0;
c54a00
         }
c54a00
 
c54a00
diff --git a/lib/services/services.c b/lib/services/services.c
c54a00
index 60402e7..ef2c5fc 100644
c54a00
--- a/lib/services/services.c
c54a00
+++ b/lib/services/services.c
c54a00
@@ -843,12 +843,17 @@ services_untrack_op(svc_action_t *op)
c54a00
 }
c54a00
 
c54a00
 gboolean
c54a00
-services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t *))
c54a00
+services_action_async_fork_notify(svc_action_t * op,
c54a00
+                                  void (*action_callback) (svc_action_t *),
c54a00
+                                  void (*action_fork_callback) (svc_action_t *))
c54a00
 {
c54a00
     op->synchronous = false;
c54a00
     if (action_callback) {
c54a00
         op->opaque->callback = action_callback;
c54a00
     }
c54a00
+    if (action_fork_callback) {
c54a00
+        op->opaque->fork_callback = action_fork_callback;
c54a00
+    }
c54a00
 
c54a00
     if (op->interval > 0) {
c54a00
         init_recurring_actions();
c54a00
@@ -868,6 +873,12 @@ services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t *
c54a00
     return action_exec_helper(op);
c54a00
 }
c54a00
 
c54a00
+gboolean
c54a00
+services_action_async(svc_action_t * op,
c54a00
+                      void (*action_callback) (svc_action_t *))
c54a00
+{
c54a00
+    return services_action_async_fork_notify(op, action_callback, NULL);
c54a00
+}
c54a00
 
c54a00
 static gboolean processing_blocked_ops = FALSE;
c54a00
 
c54a00
diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c
c54a00
index d79c16d..705901e 100644
c54a00
--- a/lib/services/services_linux.c
c54a00
+++ b/lib/services/services_linux.c
c54a00
@@ -877,6 +877,11 @@ services_os_action_execute(svc_action_t * op)
c54a00
         op->opaque->stdin_fd = -1;
c54a00
     }
c54a00
 
c54a00
+    // after fds are setup properly and before we plug anything into mainloop
c54a00
+    if (op->opaque->fork_callback) {
c54a00
+        op->opaque->fork_callback(op);
c54a00
+    }
c54a00
+
c54a00
     if (op->synchronous) {
c54a00
         action_synced_wait(op, pmask);
c54a00
         sigchld_cleanup();
c54a00
diff --git a/lib/services/services_private.h b/lib/services/services_private.h
c54a00
index 9735da7..227e17f 100644
c54a00
--- a/lib/services/services_private.h
c54a00
+++ b/lib/services/services_private.h
c54a00
@@ -36,6 +36,7 @@ struct svc_action_private_s {
c54a00
 
c54a00
     guint repeat_timer;
c54a00
     void (*callback) (svc_action_t * op);
c54a00
+    void (*fork_callback) (svc_action_t * op);
c54a00
 
c54a00
     int stderr_fd;
c54a00
     mainloop_io_t *stderr_gsource;
c54a00
-- 
c54a00
1.8.3.1
c54a00