From 07a82c5c8f9d60989ea88c5a3cc316ee290ea784 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
Date: Tue, 16 Apr 2019 00:04:57 +0200
Subject: [PATCH 5/7] High: pacemakerd vs. IPC/procfs confused deputy
 authenticity issue (3/4)

[3/4: other daemons to authenticate IPC servers of fellow processes]

Now that CVE-2018-16877 issue alone is still only partially covered
based on the preceding commits in the set, put the server-by-client
authentication (enabled and 1/3 and partially sported in 2/3) into
practice widely amongst the communicating pacemaker child daemons and
towards CPG API provided by 3rd party but principally using the same
underlying IPC mechanism facilitated by libqb, and consequently close
the remaining "big gap".

As a small justification to introducing yet another "return
value" int variable, type-correctness is restored for those
that shall be cs_error_t to begin with.
---
 lib/cluster/corosync.c | 178 +++++++++++++++++++++++++++++++++++++++++--------
 lib/cluster/cpg.c      |  94 +++++++++++++++++++-------
 lib/common/ipc.c       |  43 +++++++++++-
 mcp/corosync.c         |  76 ++++++++++++++++-----
 4 files changed, 320 insertions(+), 71 deletions(-)

Index: pacemaker-1.1.16+20170320.77ea74d/lib/cluster/corosync.c
===================================================================
--- pacemaker-1.1.16+20170320.77ea74d.orig/lib/cluster/corosync.c
+++ pacemaker-1.1.16+20170320.77ea74d/lib/cluster/corosync.c
@@ -1,19 +1,10 @@
 /*
- * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2004-2019 the Pacemaker project contributors
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * The version control history for this file may have further details.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
@@ -40,6 +31,8 @@
 
 #include <crm/msg_xml.h>
 
+#include <crm/common/ipc_internal.h>  /* PCMK__SPECIAL_PID* */
+
 quorum_handle_t pcmk_quorum_handle = 0;
 
 gboolean(*quorum_app_callback) (unsigned long long seq, gboolean quorate) = NULL;
@@ -52,10 +45,15 @@ char *
 corosync_node_name(uint64_t /*cmap_handle_t */ cmap_handle, uint32_t nodeid)
 {
     int lpc = 0;
-    int rc = CS_OK;
+    cs_error_t rc = CS_OK;
     int retries = 0;
     char *name = NULL;
     cmap_handle_t local_handle = 0;
+    int fd = -1;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     /* nodeid == 0 == CMAN_NODEID_US */
     if (nodeid == 0) {
@@ -85,6 +83,27 @@ corosync_node_name(uint64_t /*cmap_handle_t */ cmap_handle, uint32_t nodeid)
 
     if (cmap_handle == 0) {
         cmap_handle = local_handle;
+
+        rc = cmap_fd_get(cmap_handle, &fd);
+        if (rc != CS_OK) {
+            crm_err("Could not obtain the CMAP API connection: %s (%d)",
+                    cs_strerror(rc), rc);
+            goto bail;
+        }
+
+        /* CMAP provider run as root (in given user namespace, anyway)? */
+        if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                                &found_uid, &found_gid))) {
+            crm_err("CMAP provider is not authentic:"
+                    " process %lld (uid: %lld, gid: %lld)",
+                    (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                    (long long) found_uid, (long long) found_gid);
+            goto bail;
+        } else if (rv < 0) {
+            crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
+                    strerror(-rv), -rv);
+            goto bail;
+        }
     }
 
     while (name == NULL && cmap_handle != 0) {
@@ -126,6 +145,7 @@ corosync_node_name(uint64_t /*cmap_handle_t */ cmap_handle, uint32_t nodeid)
         lpc++;
     }
 
+bail:
     if(local_handle) {
         cmap_finalize(local_handle);
     }
@@ -249,11 +269,15 @@ gboolean
 cluster_connect_quorum(gboolean(*dispatch) (unsigned long long, gboolean),
                        void (*destroy) (gpointer))
 {
-    int rc = -1;
+    cs_error_t rc;
     int fd = 0;
     int quorate = 0;
     uint32_t quorum_type = 0;
     struct mainloop_fd_callbacks quorum_fd_callbacks;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     quorum_fd_callbacks.dispatch = pcmk_quorum_dispatch;
     quorum_fd_callbacks.destroy = destroy;
@@ -262,7 +286,8 @@ cluster_connect_quorum(gboolean(*dispatch) (unsigned long long, gboolean),
 
     rc = quorum_initialize(&pcmk_quorum_handle, &quorum_callbacks, &quorum_type);
     if (rc != CS_OK) {
-        crm_err("Could not connect to the Quorum API: %d\n", rc);
+        crm_err("Could not connect to the Quorum API: %s (%d)",
+                cs_strerror(rc), rc);
         goto bail;
 
     } else if (quorum_type != QUORUM_SET) {
@@ -270,6 +295,29 @@ cluster_connect_quorum(gboolean(*dispatch) (unsigned long long, gboolean),
         goto bail;
     }
 
+    rc = quorum_fd_get(pcmk_quorum_handle, &fd);
+    if (rc != CS_OK) {
+        crm_err("Could not obtain the Quorum API connection: %s (%d)",
+                strerror(rc), rc);
+        goto bail;
+    }
+
+    /* Quorum provider run as root (in given user namespace, anyway)? */
+    if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                            &found_uid, &found_gid))) {
+        crm_err("Quorum provider is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        rc = CS_ERR_ACCESS;
+        goto bail;
+    } else if (rv < 0) {
+        crm_err("Could not verify authenticity of Quorum provider: %s (%d)",
+                strerror(-rv), -rv);
+        rc = CS_ERR_ACCESS;
+        goto bail;
+    }
+
     rc = quorum_getquorate(pcmk_quorum_handle, &quorate);
     if (rc != CS_OK) {
         crm_err("Could not obtain the current Quorum API state: %d\n", rc);
@@ -290,12 +338,6 @@ cluster_connect_quorum(gboolean(*dispatch) (unsigned long long, gboolean),
         goto bail;
     }
 
-    rc = quorum_fd_get(pcmk_quorum_handle, &fd);
-    if (rc != CS_OK) {
-        crm_err("Could not obtain the Quorum API connection: %d\n", rc);
-        goto bail;
-    }
-
     mainloop_add_fd("quorum", G_PRIORITY_HIGH, fd, dispatch, &quorum_fd_callbacks);
 
     corosync_initialize_nodelist(NULL, FALSE, NULL);
@@ -486,10 +528,15 @@ gboolean
 corosync_initialize_nodelist(void *cluster, gboolean force_member, xmlNode * xml_parent)
 {
     int lpc = 0;
-    int rc = CS_OK;
+    cs_error_t rc = CS_OK;
     int retries = 0;
     gboolean any = FALSE;
     cmap_handle_t cmap_handle;
+    int fd = -1;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     do {
         rc = cmap_initialize(&cmap_handle);
@@ -507,6 +554,27 @@ corosync_initialize_nodelist(void *cluster, gboolean force_member, xmlNode * xml
         return FALSE;
     }
 
+    rc = cmap_fd_get(cmap_handle, &fd);
+    if (rc != CS_OK) {
+        crm_err("Could not obtain the CMAP API connection: %s (%d)",
+                cs_strerror(rc), rc);
+        goto bail;
+    }
+
+    /* CMAP provider run as root (in given user namespace, anyway)? */
+    if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                            &found_uid, &found_gid))) {
+        crm_err("CMAP provider is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        goto bail;
+    } else if (rv < 0) {
+        crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
+                strerror(-rv), -rv);
+        goto bail;
+    }
+
     crm_peer_init();
     crm_trace("Initializing corosync nodelist");
     for (lpc = 0;; lpc++) {
@@ -563,6 +631,7 @@ corosync_initialize_nodelist(void *cluster, gboolean force_member, xmlNode * xml
 
         free(name);
     }
+bail:
     cmap_finalize(cmap_handle);
     return any;
 }
@@ -572,36 +641,68 @@ corosync_cluster_name(void)
 {
     cmap_handle_t handle;
     char *cluster_name = NULL;
-    int rc = CS_OK;
+    cs_error_t rc = CS_OK;
+    int fd = -1;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     rc = cmap_initialize(&handle);
     if (rc != CS_OK) {
-        crm_info("Failed to initialize the cmap API: %s (%d)", ais_error2text(rc), rc);
+        crm_info("Failed to initialize the cmap API: %s (%d)",
+                 cs_strerror(rc), rc);
         return NULL;
     }
 
+    rc = cmap_fd_get(handle, &fd);
+    if (rc != CS_OK) {
+        crm_err("Could not obtain the CMAP API connection: %s (%d)",
+                cs_strerror(rc), rc);
+        goto bail;
+    }
+
+    /* CMAP provider run as root (in given user namespace, anyway)? */
+    if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                            &found_uid, &found_gid))) {
+        crm_err("CMAP provider is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        goto bail;
+    } else if (rv < 0) {
+        crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
+                strerror(-rv), -rv);
+        goto bail;
+    }
+
     rc = cmap_get_string(handle, "totem.cluster_name", &cluster_name);
     if (rc != CS_OK) {
-        crm_info("Cannot get totem.cluster_name: %s (%d)", ais_error2text(rc), rc);
+        crm_info("Cannot get totem.cluster_name: %s (%d)", cs_strerror(rc), rc);
 
     } else {
         crm_debug("cmap totem.cluster_name = '%s'", cluster_name);
     }
 
+bail:
     cmap_finalize(handle);
-
     return cluster_name;
 }
 
 int
 corosync_cmap_has_config(const char *prefix)
 {
-    int rc = CS_OK;
+    cs_error_t rc = CS_OK;
     int retries = 0;
     static int found = -1;
     cmap_handle_t cmap_handle;
     cmap_iter_handle_t iter_handle;
     char key_name[CMAP_KEYNAME_MAXLEN + 1];
+    int fd = -1;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     if(found != -1) {
         return found;
@@ -624,6 +725,27 @@ corosync_cmap_has_config(const char *prefix)
         return -1;
     }
 
+    rc = cmap_fd_get(cmap_handle, &fd);
+    if (rc != CS_OK) {
+        crm_err("Could not obtain the CMAP API connection: %s (%d)",
+                cs_strerror(rc), rc);
+        goto bail;
+    }
+
+    /* CMAP provider run as root (in given user namespace, anyway)? */
+    if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                            &found_uid, &found_gid))) {
+        crm_err("CMAP provider is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        goto bail;
+    } else if (rv < 0) {
+        crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
+                strerror(-rv), -rv);
+        goto bail;
+    }
+
     rc = cmap_iter_init(cmap_handle, prefix, &iter_handle);
     if (rc != CS_OK) {
         crm_warn("Failed to initialize iteration for corosync cmap '%s': %s (rc=%d)",
diff --git a/lib/cluster/cpg.c b/lib/cluster/cpg.c
index 64cf4cc3a..141efcc54 100644
--- a/lib/cluster/cpg.c
+++ b/lib/cluster/cpg.c
@@ -1,19 +1,10 @@
 /*
- * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2004-2019 the Pacemaker project contributors
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * The version control history for this file may have further details.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
@@ -38,6 +29,8 @@
 
 #include <crm/msg_xml.h>
 
+#include <crm/common/ipc_internal.h>  /* PCMK__SPECIAL_PID* */
+
 cpg_handle_t pcmk_cpg_handle = 0; /* TODO: Remove, use cluster.cpg_handle */
 
 static bool cpg_evicted = FALSE;
@@ -71,11 +64,16 @@ cluster_disconnect_cpg(crm_cluster_t *cluster)
 
 uint32_t get_local_nodeid(cpg_handle_t handle)
 {
-    int rc = CS_OK;
+    cs_error_t rc = CS_OK;
     int retries = 0;
     static uint32_t local_nodeid = 0;
     cpg_handle_t local_handle = handle;
     cpg_callbacks_t cb = { };
+    int fd = -1;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     if(local_nodeid != 0) {
         return local_nodeid;
@@ -92,6 +90,32 @@ uint32_t get_local_nodeid(cpg_handle_t handle)
     if(handle == 0) {
         crm_trace("Creating connection");
         cs_repeat(retries, 5, rc = cpg_initialize(&local_handle, &cb));
+        if (rc != CS_OK) {
+            crm_err("Could not connect to the CPG API: %s (%d)",
+                    cs_strerror(rc), rc);
+            return 0;
+        }
+
+        rc = cpg_fd_get(local_handle, &fd);
+        if (rc != CS_OK) {
+            crm_err("Could not obtain the CPG API connection: %s (%d)",
+                    cs_strerror(rc), rc);
+            goto bail;
+        }
+
+        /* CPG provider run as root (in given user namespace, anyway)? */
+        if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                                &found_uid, &found_gid))) {
+            crm_err("CPG provider is not authentic:"
+                    " process %lld (uid: %lld, gid: %lld)",
+                    (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                    (long long) found_uid, (long long) found_gid);
+            goto bail;
+        } else if (rv < 0) {
+            crm_err("Could not verify authenticity of CPG provider: %s (%d)",
+                    strerror(-rv), -rv);
+            goto bail;
+        }
     }
 
     if (rc == CS_OK) {
@@ -103,6 +127,8 @@ uint32_t get_local_nodeid(cpg_handle_t handle)
     if (rc != CS_OK) {
         crm_err("Could not get local node id from the CPG API: %s (%d)", ais_error2text(rc), rc);
     }
+
+bail:
     if(handle == 0) {
         crm_trace("Closing connection");
         cpg_finalize(local_handle);
@@ -436,12 +462,16 @@ pcmk_cpg_membership(cpg_handle_t handle,
 gboolean
 cluster_connect_cpg(crm_cluster_t *cluster)
 {
-    int rc = -1;
-    int fd = 0;
+    cs_error_t rc;
+    int fd = -1;
     int retries = 0;
     uint32_t id = 0;
     crm_node_t *peer = NULL;
     cpg_handle_t handle = 0;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     struct mainloop_fd_callbacks cpg_fd_callbacks = {
         .dispatch = pcmk_cpg_dispatch,
@@ -466,7 +496,31 @@ cluster_connect_cpg(crm_cluster_t *cluster)
 
     cs_repeat(retries, 30, rc = cpg_initialize(&handle, &cpg_callbacks));
     if (rc != CS_OK) {
-        crm_err("Could not connect to the Cluster Process Group API: %d\n", rc);
+        crm_err("Could not connect to the CPG API: %s (%d)",
+                cs_strerror(rc), rc);
+        goto bail;
+    }
+
+    rc = cpg_fd_get(handle, &fd);
+    if (rc != CS_OK) {
+        crm_err("Could not obtain the CPG API connection: %s (%d)",
+                cs_strerror(rc), rc);
+        goto bail;
+    }
+
+    /* CPG provider run as root (in given user namespace, anyway)? */
+    if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                            &found_uid, &found_gid))) {
+        crm_err("CPG provider is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        rc = CS_ERR_ACCESS;
+        goto bail;
+    } else if (rv < 0) {
+        crm_err("Could not verify authenticity of CPG provider: %s (%d)",
+                strerror(-rv), -rv);
+        rc = CS_ERR_ACCESS;
         goto bail;
     }
 
@@ -485,12 +539,6 @@ cluster_connect_cpg(crm_cluster_t *cluster)
         goto bail;
     }
 
-    rc = cpg_fd_get(handle, &fd);
-    if (rc != CS_OK) {
-        crm_err("Could not obtain the CPG API connection: %d\n", rc);
-        goto bail;
-    }
-
     pcmk_cpg_handle = handle;
     cluster->cpg_handle = handle;
     mainloop_add_fd("corosync-cpg", G_PRIORITY_MEDIUM, fd, cluster, &cpg_fd_callbacks);
diff --git a/lib/common/ipc.c b/lib/common/ipc.c
index 832c430a8..5f5695a4d 100644
--- a/lib/common/ipc.c
+++ b/lib/common/ipc.c
@@ -804,11 +804,18 @@ crm_ipc_new(const char *name, size_t max_size)
  *
  * \param[in] client  Connection instance obtained from crm_ipc_new()
  *
- * \return TRUE on success, FALSE otherwise (in which case errno will be set)
+ * \return TRUE on success, FALSE otherwise (in which case errno will be set;
+ *         specifically, in case of discovering the remote side is not
+ *         authentic, its value is set to ECONNABORTED).
  */
 bool
 crm_ipc_connect(crm_ipc_t * client)
 {
+    static uid_t cl_uid = 0;
+    static gid_t cl_gid = 0;
+    pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
+    int rv;
+
     client->need_reply = FALSE;
     client->ipc = qb_ipcc_connect(client->name, client->buf_size);
 
@@ -819,7 +826,39 @@ crm_ipc_connect(crm_ipc_t * client)
 
     client->pfd.fd = crm_ipc_get_fd(client);
     if (client->pfd.fd < 0) {
-        crm_debug("Could not obtain file descriptor for %s connection: %s (%d)", client->name, pcmk_strerror(errno), errno);
+        rv = errno;
+        /* message already omitted */
+        crm_ipc_close(client);
+        errno = rv;
+        return FALSE;
+    }
+
+    if (!cl_uid && !cl_gid
+            && (rv = crm_user_lookup(CRM_DAEMON_USER, &cl_uid, &cl_gid)) < 0) {
+        errno = -rv;
+        /* message already omitted */
+        crm_ipc_close(client);
+        errno = -rv;
+        return FALSE;
+    }
+
+    if (!(rv = crm_ipc_is_authentic_process(client->pfd.fd, cl_uid, cl_gid,
+                                            &found_pid, &found_uid,
+                                            &found_gid))) {
+        crm_err("Daemon (IPC %s) is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                client->name,  (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        crm_ipc_close(client);
+        errno = ECONNABORTED;
+        return FALSE;
+
+    } else if (rv < 0) {
+        errno = -rv;
+        crm_perror(LOG_ERR, "Could not verify authenticity of daemon (IPC %s)",
+                   client->name);
+        crm_ipc_close(client);
+        errno = -rv;
         return FALSE;
     }
 
diff --git a/mcp/corosync.c b/mcp/corosync.c
index 975b93c41..5573d8181 100644
--- a/mcp/corosync.c
+++ b/mcp/corosync.c
@@ -1,19 +1,10 @@
 /*
- * Copyright (C) 2010 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2010-2019 the Pacemaker project contributors
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * The version control history for this file may have further details.
  *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 #include <crm_internal.h>
 #include <pacemaker.h>
@@ -33,8 +24,11 @@
 #endif
 
 #include <crm/cluster/internal.h>
+#include <crm/common/ipc.h>     /* for crm_ipc_is_authentic_process */
 #include <crm/common/mainloop.h>
 
+#include <crm/common/ipc_internal.h>  /* PCMK__SPECIAL_PID* */
+
 #if SUPPORT_CMAN
 #  include <libcman.h>
 #endif
@@ -111,7 +105,10 @@ gboolean
 cluster_connect_cfg(uint32_t * nodeid)
 {
     cs_error_t rc;
-    int fd = 0, retries = 0;
+    int fd = -1, retries = 0, rv;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
 
     static struct mainloop_fd_callbacks cfg_fd_callbacks = {
         .dispatch = pcmk_cfg_dispatch,
@@ -121,13 +118,27 @@ cluster_connect_cfg(uint32_t * nodeid)
     cs_repeat(retries, 30, rc = corosync_cfg_initialize(&cfg_handle, &cfg_callbacks));
 
     if (rc != CS_OK) {
-        crm_err("corosync cfg init error %d", rc);
+        crm_err("corosync cfg init: %s (%d)", cs_strerror(rc), rc);
         return FALSE;
     }
 
     rc = corosync_cfg_fd_get(cfg_handle, &fd);
     if (rc != CS_OK) {
-        crm_err("corosync cfg fd_get error %d", rc);
+        crm_err("corosync cfg fd_get: %s (%d)", cs_strerror(rc), rc);
+        goto bail;
+    }
+
+    /* CFG provider run as root (in given user namespace, anyway)? */
+    if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                            &found_uid, &found_gid))) {
+        crm_err("CFG provider is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        goto bail;
+    } else if (rv < 0) {
+        crm_err("Could not verify authenticity of CFG provider: %s (%d)",
+                strerror(-rv), -rv);
         goto bail;
     }
 
@@ -264,7 +275,7 @@ get_config_opt(uint64_t unused, cmap_handle_t object_handle, const char *key, ch
 gboolean
 mcp_read_config(void)
 {
-    int rc = CS_OK;
+    cs_error_t rc = CS_OK;
     int retries = 0;
 
     const char *const_value = NULL;
@@ -287,11 +298,16 @@ mcp_read_config(void)
         } else {
             break;
         }
-
     } while (retries < 5);
+
 #elif HAVE_CMAP
     cmap_handle_t local_handle;
     uint64_t config = 0;
+    int fd = -1;
+    uid_t found_uid = 0;
+    gid_t found_gid = 0;
+    pid_t found_pid = 0;
+    int rv;
 
     /* There can be only one (possibility if confdb isn't around) */
     do {
@@ -315,6 +331,30 @@ mcp_read_config(void)
         return FALSE;
     }
 
+    rc = cmap_fd_get(local_handle, &fd);
+    if (rc != CS_OK) {
+        crm_err("Could not obtain the CMAP API connection: %s (%d)",
+                cs_strerror(rc), rc);
+        cmap_finalize(local_handle);
+        return FALSE;
+    }
+
+    /* CMAP provider run as root (in given user namespace, anyway)? */
+    if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
+                                            &found_uid, &found_gid))) {
+        crm_err("CMAP provider is not authentic:"
+                " process %lld (uid: %lld, gid: %lld)",
+                (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
+                (long long) found_uid, (long long) found_gid);
+        cmap_finalize(local_handle);
+        return FALSE;
+    } else if (rv < 0) {
+        crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
+                strerror(-rv), -rv);
+        cmap_finalize(local_handle);
+        return FALSE;
+    }
+
     stack = get_cluster_type();
     crm_info("Reading configure for stack: %s", name_for_cluster_type(stack));
 
