You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by mt...@apache.org on 2010/05/28 16:36:08 UTC

svn commit: r949187 - in /trafficserver/traffic/trunk: ./ libinktomi++/ proxy/ proxy/mgmt2/ proxy/mgmt2/utils/

Author: mturk
Date: Fri May 28 14:36:08 2010
New Revision: 949187

URL: http://svn.apache.org/viewvc?rev=949187&view=rev
Log:
TS-338: Alan's patch for enabling posix capabilities

Modified:
    trafficserver/traffic/trunk/configure.ac
    trafficserver/traffic/trunk/libinktomi++/ink_config.h.in
    trafficserver/traffic/trunk/libinktomi++/ink_string.cc
    trafficserver/traffic/trunk/proxy/Main.cc
    trafficserver/traffic/trunk/proxy/Makefile.am
    trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.cc
    trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.h
    trafficserver/traffic/trunk/proxy/mgmt2/Main.cc
    trafficserver/traffic/trunk/proxy/mgmt2/Makefile.am
    trafficserver/traffic/trunk/proxy/mgmt2/Rollback.cc
    trafficserver/traffic/trunk/proxy/mgmt2/utils/WebMgmtUtils.cc

Modified: trafficserver/traffic/trunk/configure.ac
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/configure.ac?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/configure.ac (original)
+++ trafficserver/traffic/trunk/configure.ac Fri May 28 14:36:08 2010
@@ -302,6 +302,17 @@ AC_ARG_ENABLE([eventfd],
 AC_MSG_RESULT([$enable_eventfd])
 
 #
+# use POSIX capabilities instead of user ID switching.
+#
+AC_MSG_CHECKING([whether to use POSIX capabilities])
+AC_ARG_ENABLE([posix-cap],
+  [AS_HELP_STRING([--disable-posix-cap],[Use user id switching instead of POSIX capabilities])],
+  [],
+  [enable_posix_cap="yes"]
+)
+AC_MSG_RESULT([$enable_posix_cap])
+
+#
 # Installation directories
 # For each var the following is evaluated
 # foo      Standard variable  eg. ${prefix}/foo
@@ -789,6 +800,18 @@ AC_MSG_RESULT([$msg])
 
 AC_SUBST(need_union_semun)
 
+# Check for POSIX capabilities library.
+# If we don't find it, disable checking for header.
+use_posix_cap=0
+AS_IF([test "x$enable_posix_cap" = "xyes"],
+  AC_CHECK_LIB([cap],[cap_set_proc],
+    [AC_SUBST([LIBCAP], ["-lcap"])
+     use_posix_cap=1
+    ],
+    [enable_posix_cap=no]
+  )
+)
+AC_SUBST(use_posix_cap)
 # -----------------------------------------------------------------------------
 # 5. CHECK FOR HEADER FILES
 
@@ -894,6 +917,14 @@ ATS_FLAG_HEADERS([google/profiler.h \
                   ], [], [])
 fi
 
+if test "x${enable_posix_cap}" = "xyes"; then
+  AC_CHECK_HEADERS([sys/capability.h],
+    [],
+    [AC_MSG_FAILURE([POSIX capabilities header not found. Try --disable-posix-cap])],
+    []
+  )
+fi
+
 ATS_CHECK_DEFAULT_IFACE
 ATS_CHECK_GETHOSTBYNAME_R_STYLE
 

Modified: trafficserver/traffic/trunk/libinktomi++/ink_config.h.in
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/libinktomi%2B%2B/ink_config.h.in?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/libinktomi++/ink_config.h.in (original)
+++ trafficserver/traffic/trunk/libinktomi++/ink_config.h.in Fri May 28 14:36:08 2010
@@ -109,6 +109,7 @@
 #define ATS_USE_EPOLL                   @use_epoll@
 #define ATS_USE_KQUEUE                  @use_kqueue@
 #define ATS_USE_PORT                    @use_port@
+#define ATS_USE_POSIX_CAP               @use_posix_cap@
 
 /* OS API definitions */
 #define GETHOSTBYNAME_R_HOSTENT_DATA    @gethostbyname_r_hostent_data@

Modified: trafficserver/traffic/trunk/libinktomi++/ink_string.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/libinktomi%2B%2B/ink_string.cc?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/libinktomi++/ink_string.cc (original)
+++ trafficserver/traffic/trunk/libinktomi++/ink_string.cc Fri May 28 14:36:08 2010
@@ -410,19 +410,22 @@ ink_strndup(const char *str, size_t n)
 #endif
 
 /*
- * Copyright (c) 1998 Todd C. Miller <To...@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+   strlcat and strlcpy are derived from Todd C. Millers's code.
+
+
+   Copyright (c) 1998 Todd C. Miller <To...@courtesan.com>
+
+   Permission to use, copy, modify, and distribute this software for any
+   purpose with or without fee is hereby granted, provided that the above
+   copyright notice and this permission notice appear in all copies.
+
+   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 #if !ATS_HAS_STRLCPY
 size_t

Modified: trafficserver/traffic/trunk/proxy/Main.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/Main.cc?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/Main.cc (original)
+++ trafficserver/traffic/trunk/proxy/Main.cc Fri May 28 14:36:08 2010
@@ -47,6 +47,10 @@ extern "C" int plock(int);
 #include <mcheck.h>
 #endif
 
+#if ATS_USE_POSIX_CAP
+#include <sys/capability.h>
+#endif
+
 #include "Main.h"
 #include "signals.h"
 #include "Error.h"
@@ -1173,6 +1177,23 @@ init_ink_memalign_heap(void)
   }
 }
 
+#if ATS_USE_POSIX_CAP
+// Restore the effective capabilities that we need.
+int
+restoreCapabilities() {
+  int zret = 0; // return value.
+  cap_t cap_set = cap_get_proc(); // current capabilities
+  // Capabilities to restore.
+  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
+  static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
+
+  cap_set_flag(cap_set, CAP_EFFECTIVE, CAP_COUNT, cap_list, CAP_SET);
+  zret = cap_set_proc(cap_set);
+  cap_free(cap_set);
+  return zret;
+}
+#endif
+
 static void
 adjust_sys_settings(void)
 {
@@ -1205,6 +1226,9 @@ adjust_sys_settings(void)
 #endif
 
 #endif  // linux check
+#if ATS_USE_POSIX_CAP
+  restoreCapabilities();
+#endif
 }
 
 struct ShowStats:Continuation

Modified: trafficserver/traffic/trunk/proxy/Makefile.am
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/Makefile.am?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/Makefile.am (original)
+++ trafficserver/traffic/trunk/proxy/Makefile.am Fri May 28 14:36:08 2010
@@ -174,7 +174,7 @@ traffic_server_LDADD = \
   $(top_builddir)/libinktomi++/libinktomi++.a \
   @LIBTHREAD@ @LIBSOCKET@ @LIBNSL@ @LIBRESOLV@ @LIBRT@ \
   @LIBPCRE@ @LIBDB@ @LIBSQLITE3@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
-  @LIBEXPAT@ @LIBDEMANGLE@ @LIBICONV@ \
+  @LIBEXPAT@ @LIBDEMANGLE@ @LIBICONV@ @LIBCAP@ \
   @LIBMLD@ @LIBEXC@ @LIBM@ @LIBEV@ @LIBPROFILER@ @LIBEXECINFO@
 
 traffic_logcat_SOURCES = logcat.cc

Modified: trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.cc?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.cc (original)
+++ trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.cc Fri May 28 14:36:08 2010
@@ -40,6 +40,10 @@
 #include "WebReconfig.h"
 #include "MgmtSocket.h"
 
+#if ATS_USE_POSIX_CAP
+#include <sys/capability.h>
+#endif
+
 int bindProxyPort(int, in_addr_t, int);
 
 bool
@@ -1279,7 +1283,7 @@ LocalManager::listenForProxy()
   if (!run_proxy)
     return;
 
-  // We we are not already bound, bind the port
+  // We are not already bound, bind the port
   for (int i = 0; i < MAX_PROXY_SERVER_PORTS; i++) {
     if (proxy_server_port[i] != -1) {
 
@@ -1307,6 +1311,35 @@ LocalManager::listenForProxy()
   return;
 }                               /* End LocalManager::listenForProxy */
 
+#if ATS_USE_POSIX_CAP
+/** Control file access privileges to bypass DAC.
+    @parm state Use @c true to enable elevated privileges,
+    @c false to disable.
+    @return @c true if successful, @c false otherwise.
+
+    @internal After some pondering I decided that the file access
+    privilege was worth the effort of restricting. Unlike the network
+    privileges this can protect a host system from programming errors
+    by not (usually) permitting such errors to access arbitrary
+    files. This is particularly true since none of the config files
+    current enable this feature so it's not actually called. Still,
+    best to program defensively and have it available.
+ */
+bool
+elevateFileAccess(bool state)
+{
+  bool zret = false; // return value.
+  cap_t cap_state = cap_get_proc(); // current capabilities
+  // Make a list of the capabilities we changed.
+  cap_value_t cap_list[] = { CAP_DAC_OVERRIDE };
+  static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
+
+  cap_set_flag(cap_state, CAP_EFFECTIVE, CAP_COUNT, cap_list, state ? CAP_SET : CAP_CLEAR);
+  zret = (0 == cap_set_proc(cap_state));
+  cap_free(cap_state);
+  return zret;
+}
+#else
 //  bool removeRootPriv()
 //
 //    - Returns true on success
@@ -1316,16 +1349,14 @@ bool
 removeRootPriv(uid_t euid)
 {
   if (seteuid(euid) < 0) {
-    Debug("lm", "[restoreRootPriv] seteuid failed : %s\n", strerror(errno));
+    Debug("lm", "[removeRootPriv] seteuid failed : %s\n", strerror(errno));
     return false;
   }
 
   Debug("lm", "[removeRootPriv] removed root privileges.  Euid is %d\n", euid);
-
   return true;
 }
 
-
 //  bool restoreRootPriv()
 //
 //    - Returns true on success
@@ -1345,6 +1376,7 @@ restoreRootPriv(uid_t *old_euid)
 
   return true;
 }
+#endif
 
 /*
  * bindProxyPort()
@@ -1357,6 +1389,8 @@ bindProxyPort(int proxy_port, in_addr_t 
   int one = 1;
   struct sockaddr_in proxy_addr;
   int proxy_port_fd = -1;
+
+#if !ATS_USE_POSIX_CAP
   bool privBoost = false;
   uid_t euid = geteuid();
   uid_t saved_euid = 0;
@@ -1370,6 +1404,7 @@ bindProxyPort(int proxy_port, in_addr_t 
       privBoost = true;
     }
   }
+#endif
 
   /* Setup reliable connection, for large config changes */
   if ((proxy_port_fd = socket(AF_INET, type, 0)) < 0) {
@@ -1393,12 +1428,16 @@ bindProxyPort(int proxy_port, in_addr_t 
 
   Debug("lm", "[bindProxyPort] Successfully bound proxy port %d\n", proxy_port);
 
-  if (privBoost == true) {
-    if (removeRootPriv(saved_euid) == false) {
-      mgmt_elog(stderr, "[bindProxyPort] Unable to reset permissions to euid %d.  Exiting...\n", getuid());
-      _exit(1);
+#if !ATS_USE_POSIX_CAP
+  if (proxy_port < 1024 && euid != 0) {
+    if (privBoost == true) {
+      if (removeRootPriv(saved_euid) == false) {
+        mgmt_elog(stderr, "[bindProxyPort] Unable to reset permissions to euid %d.  Exiting...\n", getuid());
+        _exit(1);
+      }
     }
   }
+#endif
   return proxy_port_fd;
 
 }                               /* End bindProxyPort */

Modified: trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.h?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.h (original)
+++ trafficserver/traffic/trunk/proxy/mgmt2/LocalManager.h Fri May 28 14:36:08 2010
@@ -193,8 +193,11 @@ private:
 
 };                              /* End class LocalManager */
 
+#if ATS_USE_POSIX_CAP
+bool elevateFileAccess(bool);
+#else
 bool restoreRootPriv(uid_t *old_euid = NULL);
 bool removeRootPriv(uid_t euid);
-
+#endif
 
 #endif /* _LOCAL_MANAGER_H */

Modified: trafficserver/traffic/trunk/proxy/mgmt2/Main.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt2/Main.cc?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt2/Main.cc (original)
+++ trafficserver/traffic/trunk/proxy/mgmt2/Main.cc Fri May 28 14:36:08 2010
@@ -73,7 +73,9 @@
 #include "P_RecLocal.h"
 #include "P_RecCore.h"
 
-
+#if ATS_USE_POSIX_CAP
+#include <sys/capability.h>
+#endif
 
 #define FD_THROTTLE_HEADROOM (128 + 64) // TODO: consolidate with THROTTLE_FD_HEADROOM
 
@@ -1400,6 +1402,39 @@ fileUpdated(char *fname)
   return;
 }                               /* End fileUpdate */
 
+#if ATS_USE_POSIX_CAP
+/** Restore capabilities after user id change.
+    This manipulates LINUX capabilities so that this process
+    can perform certain privileged operations even if it is
+    no longer running as a privilege user.
+
+    @internal
+    I tried using
+    @code
+    prctl(PR_SET_KEEPCAPS, 1);
+    @endcode
+    but that had no effect even though the call reported succes.
+    Only explicit capability manipulation was effective.
+    
+    It does not appear to be necessary to set the capabilities on the
+    executable if originally run as root. That may be needed if
+    started as a user without that capability.
+ */
+
+int
+restoreCapabilities() {
+  int zret = 0; // return value.
+  cap_t cap_set = cap_get_proc(); // current capabilities
+  // Make a list of the capabilities we want turned on.
+  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
+  static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
+
+  cap_set_flag(cap_set, CAP_EFFECTIVE, CAP_COUNT, cap_list, CAP_SET);
+  zret = cap_set_proc(cap_set);
+  cap_free(cap_set);
+  return zret;
+}
+#endif
 
 //  void runAsUser(...)
 //
@@ -1430,6 +1465,7 @@ runAsUser(char *userName)
       mgmt_elog(stderr, "[runAsUser] Fatal Error: proxy.config.admin.user_id is not set\n", userName, strerror(errno));
       _exit(1);
     }
+
 // this is behaving weird.  refer to getpwnam(3C) sparc -jcoates
 // this looks like the POSIX getpwnam_r
 
@@ -1471,6 +1507,13 @@ runAsUser(char *userName)
       mgmt_elog(stderr, "[runAsUser] Fatal Error: Failed to switch to user %s\n", userName);
       _exit(1);
     }
+
+#if ATS_USE_POSIX_CAP
+    if (restoreCapabilities()) {
+      mgmt_elog(stderr, "[runAsUser] Error: Failed to restore capabilities after switch to user %s.\n", userName);
+    }
+#endif
+
   }
 }                               /* End runAsUser() */
 

Modified: trafficserver/traffic/trunk/proxy/mgmt2/Makefile.am
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt2/Makefile.am?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt2/Makefile.am (original)
+++ trafficserver/traffic/trunk/proxy/mgmt2/Makefile.am Fri May 28 14:36:08 2010
@@ -117,4 +117,4 @@ traffic_manager_LDADD = \
   @LIBEXPAT@ @LIBPCRE@ \
   @LIBSSL@ @LIBDB@ @LIBSQLITE3@ @LIBTCL@ @LIBICONV@ \
   @LIBM@ @LIBDL@ @LIBSOCKET@ @LIBNSL@ @LIBRESOLV@ \
-  @LIBTHREAD@ @LIBRT@ @LIBEXECINFO@
+  @LIBTHREAD@ @LIBRT@ @LIBEXECINFO@ @LIBCAP@

Modified: trafficserver/traffic/trunk/proxy/mgmt2/Rollback.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt2/Rollback.cc?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt2/Rollback.cc (original)
+++ trafficserver/traffic/trunk/proxy/mgmt2/Rollback.cc Fri May 28 14:36:08 2010
@@ -286,20 +286,37 @@ Rollback::statFile(version_t version, st
 {
   char *filePath;
   int statResult;
+#if !ATS_USE_POSIX_CAP
   uid_t saved_euid = 0;
+#endif
 
   if (version == this->currentVersion) {
     version = ACTIVE_VERSION;
   }
   filePath = createPathStr(version);
+  
   if (root_access_needed) {
-    if (restoreRootPriv(&saved_euid) != true) {
+    if (
+#if ATS_USE_POSIX_CAP
+	elevateFileAccess(true)
+#else
+	restoreRootPriv(&saved_euid)
+#endif
+	!= true) {
       mgmt_log(stderr, "[Rollback] Unable to acquire root privileges.\n");
     }
   }
+
   statResult = stat(filePath, buf);
+
   if (root_access_needed) {
-    if (removeRootPriv(saved_euid) != true) {
+    if (
+#if ATS_USE_POSIX_CAP
+	elevateFileAccess(false)
+#else
+	removeRootPriv(saved_euid)
+#endif
+	!= true) {
       mgmt_log(stderr, "[Rollback] Unable to restore non-root privileges.\n");
     }
   }
@@ -318,21 +335,37 @@ Rollback::openFile(version_t version, in
 {
   char *filePath;
   int fd;
+#if !ATS_USE_POSIX_CAP
   uid_t saved_euid = 0;
+#endif
 
   filePath = createPathStr(version);
 
   if (root_access_needed) {
-    if (restoreRootPriv(&saved_euid) != true) {
+    if (
+#if ATS_USE_POSIX_CAP
+	elevateFileAccess(true)
+#else
+	restoreRootPriv(&saved_euid)
+#endif
+	!= true) {
       mgmt_log(stderr, "[Rollback] Unable to acquire root privileges.\n");
     }
   }
+
   fd = mgmt_open_mode(filePath, oflags, 0644);
   if (root_access_needed) {
-    if (removeRootPriv(saved_euid) != true) {
+    if (
+#if ATS_USE_POSIX_CAP
+	elevateFileAccess(false)
+#else
+	removeRootPriv(saved_euid)
+#endif
+	!= true) {
       mgmt_log(stderr, "[Rollback] Unable to restore non-root privileges.\n");
     }
   }
+
   if (fd < 0) {
     if (errnoPtr != NULL) {
       *errnoPtr = errno;

Modified: trafficserver/traffic/trunk/proxy/mgmt2/utils/WebMgmtUtils.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt2/utils/WebMgmtUtils.cc?rev=949187&r1=949186&r2=949187&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt2/utils/WebMgmtUtils.cc (original)
+++ trafficserver/traffic/trunk/proxy/mgmt2/utils/WebMgmtUtils.cc Fri May 28 14:36:08 2010
@@ -1518,7 +1518,9 @@ processSpawn(const char *args[],
   long total;
   bool cutoff;
   const char *too_large_msg = "\nfile too large, truncated here...";
+#if !ATS_USE_POSIX_CAP
   uid_t saved_euid = 0;
+#endif
 
   if (pipe(stdinPipe) == -1)
     mgmt_elog(stderr, "[processSpawn] unable to create stdin pipe\n");
@@ -1538,6 +1540,27 @@ processSpawn(const char *args[],
     for (int i = 0; i < MAX_PROXY_SERVER_PORTS && lmgmt->proxy_server_fd[i] >= 0; i++) {
       close_socket(lmgmt->proxy_server_fd[i]);
     }
+#if ATS_USE_POSIX_CAP
+    /* There is no point in saving the current euid in order to
+       restore it because at this point the process will either exec
+       or exit. The thread of execution will neither linger nor return
+       here.
+
+       I don't understand what the point in the original code was of
+       setuid(geteuid()) after reverting to root euid. If the latter
+       works, you don't need the former, and if the latter doesn't
+       work, the former won't work either. Is it some sort of error
+       checking? But why not just check the return value of
+       restoreRootPriv?
+
+       AFAICT this code is used only by the web interface which is
+       currently non-functional. If that interface is recovered it
+       would be worthwhile to look at why, exactly, it needs to have
+       processes run as root.
+    */
+    if (-1 == seteuid(0))
+        mgmt_elog(stderr, "[processSpawn] unable to set effective user id to 0");
+#else
     // set uid to be the effective uid if it's run as root
     if (run_as_root) {
       restoreRootPriv(&saved_euid);
@@ -1545,6 +1568,7 @@ processSpawn(const char *args[],
         mgmt_elog(stderr, "[processSpawn] unable to set uid to euid");
       }
     }
+#endif
     if (nowait) {
       // nowait - detach from parent process
       if (setsid() == (pid_t) - 1) {
@@ -1630,9 +1654,11 @@ processSpawn(const char *args[],
     }
   }
 
+#if !ATS_USE_POSIX_CAP
   if (run_as_root) {
     removeRootPriv(saved_euid);
   }
+#endif
 #endif // _WIN32
   return status;
 }