You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2013/10/06 16:58:04 UTC

[19/22] git commit: [TS-2261] Add config option to restore/elevate access to reading files by root when loading plugins

[TS-2261] Add config option to restore/elevate access to reading files by
root when loading plugins


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/fffb60ed
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/fffb60ed
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/fffb60ed

Branch: refs/heads/5.0.x
Commit: fffb60ed3bbc30cf302e0ccf956248cb1ec5cef3
Parents: 4102e98
Author: Bryan Call <bc...@apache.org>
Authored: Thu Oct 3 15:08:04 2013 -0700
Committer: Bryan Call <bc...@apache.org>
Committed: Thu Oct 3 15:08:04 2013 -0700

----------------------------------------------------------------------
 CHANGES                        |  3 ++
 lib/ts/ink_cap.cc              | 81 +++++++++++++++++++++++++++++++++++--
 lib/ts/ink_cap.h               | 47 +++++++++++++++++++++
 mgmt/LocalManager.cc           | 65 +----------------------------
 mgmt/LocalManager.h            |  6 ---
 mgmt/RecordsConfig.cc          |  3 ++
 mgmt/Rollback.cc               |  2 +-
 proxy/Plugin.cc                | 10 ++++-
 proxy/http/remap/UrlMapping.cc | 11 ++++-
 proxy/http/remap/UrlRewrite.cc | 28 ++++++++++---
 10 files changed, 173 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index ee94a4b..cf1bff2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 4.1.0
 
+  *) [TS-2261] Add config option to restore/elevate access to reading files by
+   root when loading plugins
+
   *) [TS-2257] Healthcheck plugin can stop watching some events.
 
   *) [TS-2260] Avoid flooding log when log host is down.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/lib/ts/ink_cap.cc
----------------------------------------------------------------------
diff --git a/lib/ts/ink_cap.cc b/lib/ts/ink_cap.cc
index 038fc2e..e51b730 100644
--- a/lib/ts/ink_cap.cc
+++ b/lib/ts/ink_cap.cc
@@ -65,6 +65,7 @@ PreserveCapabilities() {
 # if TS_USE_POSIX_CAP
     zret = prctl(PR_SET_KEEPCAPS, 1);
 # endif
+  Debug("proxy_priv", "[PreserveCapabilities] zret : %d\n", zret);
   return zret;
 }
 
@@ -75,14 +76,17 @@ RestrictCapabilities() {
 # if TS_USE_POSIX_CAP
     cap_t caps = cap_init(); // start with nothing.
     // Capabilities we need.
-    cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_IPC_LOCK };
-    static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
+    cap_value_t perm_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_IPC_LOCK, CAP_DAC_OVERRIDE};
+    static int const PERM_CAP_COUNT = sizeof(perm_list)/sizeof(*perm_list);
+    cap_value_t eff_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_IPC_LOCK};
+    static int const EFF_CAP_COUNT = sizeof(eff_list)/sizeof(*eff_list);
 
-    cap_set_flag(caps, CAP_PERMITTED, CAP_COUNT, cap_list, CAP_SET);
-    cap_set_flag(caps, CAP_EFFECTIVE, CAP_COUNT, cap_list, CAP_SET);
+    cap_set_flag(caps, CAP_PERMITTED, PERM_CAP_COUNT, perm_list, CAP_SET);
+    cap_set_flag(caps, CAP_EFFECTIVE, EFF_CAP_COUNT, eff_list, CAP_SET);
     zret = cap_set_proc(caps);
     cap_free(caps);
 #  endif
+  Debug("proxy_priv", "[RestrictCapabilities] zret : %d\n", zret);
   return zret;
 }
 
@@ -98,5 +102,74 @@ EnableCoreFile(bool flag) {
       Warning("Call to set PR_DUMPABLE was ineffective");
     }
 # endif  // linux check
+  Debug("proxy_priv", "[EnableCoreFile] zret : %d\n", zret);
   return zret;
 }
+
+#if TS_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)
+{
+  Debug("proxy_priv", "[elevateFileAccess] state : %d\n", 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);
+  Debug("proxy_priv", "[elevateFileAccess] zret : %d\n", zret);
+  return zret;
+}
+#else
+//  bool removeRootPriv()
+//
+//    - Returns true on success
+//      and false on failure
+bool
+removeRootPriv(uid_t euid)
+{
+  if (seteuid(euid) < 0) {
+    Debug("proxy_priv", "[removeRootPriv] seteuid failed : %s\n", strerror(errno));
+    return false;
+  }
+
+  Debug("proxy_priv", "[removeRootPriv] removed root privileges.  Euid is %d\n", euid);
+  return true;
+}
+
+//  bool restoreRootPriv()
+//
+//    - Returns true on success
+//      and false on failure
+bool
+restoreRootPriv(uid_t *old_euid)
+{
+  if (old_euid)
+    *old_euid = geteuid();
+  if (seteuid(0) < 0) {
+    Debug("proxy_priv", "[restoreRootPriv] seteuid root failed : %s\n", strerror(errno));
+    return false;
+  }
+
+  Debug("proxy_priv", "[restoreRootPriv] restored root privileges.  Euid is %d\n", 0);
+
+  return true;
+}
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/lib/ts/ink_cap.h
----------------------------------------------------------------------
diff --git a/lib/ts/ink_cap.h b/lib/ts/ink_cap.h
index a457737..e29acea 100644
--- a/lib/ts/ink_cap.h
+++ b/lib/ts/ink_cap.h
@@ -44,4 +44,51 @@ extern int EnableCoreFile(
   bool flag ///< New enable state.
 );
 
+
+
+#if TS_USE_POSIX_CAP
+bool elevateFileAccess(bool);
+#else
+bool restoreRootPriv(uid_t *old_euid = NULL);
+bool removeRootPriv(uid_t euid);
+#endif
+
+
+class ElevateAccess {
+public:
+  ElevateAccess(const bool state): elevated(false), saved_uid(0) {
+    if (state == true) {
+      elevate();
+    }
+  }
+
+  void elevate() {
+#if TS_USE_POSIX_CAP
+    elevateFileAccess(true);
+#else
+    restoreRootPriv(&saved_uid);
+#endif
+    elevated = true;
+  }
+
+  void demote() {
+#if TS_USE_POSIX_CAP
+    elevateFileAccess(false);
+#else
+    removeRootPriv(saved_uid);
+#endif
+    elevated = false;
+  }
+
+  ~ElevateAccess() {
+    if (elevated == true) {
+      demote();
+    }
+  }
+
+private:
+  bool elevated;
+  uid_t saved_uid;
+};
+
 #endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/mgmt/LocalManager.cc
----------------------------------------------------------------------
diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc
index 7b2799b..b7feeca 100644
--- a/mgmt/LocalManager.cc
+++ b/mgmt/LocalManager.cc
@@ -29,6 +29,7 @@
 #include "Compatability.h"
 #include "LocalManager.h"
 #include "MgmtSocket.h"
+#include "ink_cap.h"
 
 #if TS_USE_POSIX_CAP
 #include <sys/capability.h>
@@ -1084,70 +1085,6 @@ LocalManager::listenForProxy()
   return;
 }
 
-#if TS_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
-//      and false on failure
-bool
-removeRootPriv(uid_t euid)
-{
-  if (seteuid(euid) < 0) {
-    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
-//      and false on failure
-bool
-restoreRootPriv(uid_t *old_euid)
-{
-  if (old_euid)
-    *old_euid = geteuid();
-  if (seteuid(0) < 0) {
-    Debug("lm", "[restoreRootPriv] seteuid root failed : %s\n", strerror(errno));
-    return false;
-  }
-
-  Debug("lm", "[restoreRootPriv] restored root privileges.  Euid is %d\n", 0);
-
-  return true;
-}
-#endif
 
 /*
  * bindProxyPort()

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/mgmt/LocalManager.h
----------------------------------------------------------------------
diff --git a/mgmt/LocalManager.h b/mgmt/LocalManager.h
index 7b677d8..9ea4158 100644
--- a/mgmt/LocalManager.h
+++ b/mgmt/LocalManager.h
@@ -159,11 +159,5 @@ private:
 
 extern LocalManager *lmgmt;
 
-#if TS_USE_POSIX_CAP
-bool elevateFileAccess(bool);
-#else
-bool restoreRootPriv(uid_t *old_euid = NULL);
-bool removeRootPriv(uid_t euid);
-#endif
 
 #endif /* _LOCAL_MANAGER_H */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/mgmt/RecordsConfig.cc
----------------------------------------------------------------------
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 4a73f19..647174f 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1340,6 +1340,9 @@ RecordElement RecordsConfig[] = {
   ,
   {RECT_CONFIG, "proxy.config.plugin.plugin_mgmt_dir", RECD_STRING, TS_BUILD_SYSCONFDIR "/plugins_mgmt", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.plugin.load_elevated", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, "[0-1]", RECA_NULL}
+  ,
+
 
   //##############################################################################
   //#

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/mgmt/Rollback.cc
----------------------------------------------------------------------
diff --git a/mgmt/Rollback.cc b/mgmt/Rollback.cc
index e27a745..0399523 100644
--- a/mgmt/Rollback.cc
+++ b/mgmt/Rollback.cc
@@ -29,7 +29,7 @@
 #include "MgmtUtils.h"
 #include "ExpandingArray.h"
 #include "MgmtSocket.h"
-
+#include "ink_cap.h"
 
 #define MAX_VERSION_DIGITS 11
 #define DEFAULT_BACKUPS 2

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/proxy/Plugin.cc
----------------------------------------------------------------------
diff --git a/proxy/Plugin.cc b/proxy/Plugin.cc
index 1908199..5b2b19e 100644
--- a/proxy/Plugin.cc
+++ b/proxy/Plugin.cc
@@ -35,6 +35,7 @@
 #include "InkAPIInternal.h"
 #include "Main.h"
 #include "Plugin.h"
+#include "ink_cap.h"
 
 // HPUX:
 //   LD_SHAREDCMD=ld -b
@@ -136,7 +137,14 @@ plugin_load(int argc, char *argv[])
     abort();
   }
 
-  init(argc, argv);
+  // elevate the access to read files as root if compiled with capabilities, if not
+  // change the effective user to root
+  {
+    uint32_t elevate_access = 0;
+    REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
+    ElevateAccess access(elevate_access != 0);
+    init(argc, argv);
+  } // done elevating access
 
   plugin_reg_list.push(plugin_reg_current);
   plugin_reg_current = NULL;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/proxy/http/remap/UrlMapping.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/UrlMapping.cc b/proxy/http/remap/UrlMapping.cc
index c96b9b5..d5b00d1 100644
--- a/proxy/http/remap/UrlMapping.cc
+++ b/proxy/http/remap/UrlMapping.cc
@@ -23,7 +23,8 @@
 
 #include "ink_defs.h"
 #include "UrlMapping.h"
-
+#include "I_RecCore.h"
+#include "ink_cap.h"
 /**
  *
 **/
@@ -77,8 +78,14 @@ url_mapping::delete_instance(unsigned int index)
   void *ih = get_instance(index);
   remap_plugin_info* p = get_plugin(index);
 
-  if (ih && p && p->fp_tsremap_delete_instance)
+  if (ih && p && p->fp_tsremap_delete_instance) {
+    // elevate the access to read files as root if compiled with capabilities, if not
+    // change the effective user to root
+    uint32_t elevate_access = 0;
+    REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
+    ElevateAccess access(elevate_access != 0);
     p->fp_tsremap_delete_instance(ih);
+  } // done elevating access
 }
 
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fffb60ed/proxy/http/remap/UrlRewrite.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc
index 8b51897..f88df84 100644
--- a/proxy/http/remap/UrlRewrite.cc
+++ b/proxy/http/remap/UrlRewrite.cc
@@ -34,6 +34,7 @@
 #include "UrlMappingPathIndex.h"
 
 #include "ink_string.h"
+#include "ink_cap.h"
 
 
 unsigned long
@@ -1699,10 +1700,18 @@ UrlRewrite::load_remap_plugin(char *argv[], int argc, url_mapping *mp, char *err
     ri.size = sizeof(ri);
     ri.tsremap_version = TSREMAP_VERSION;
 
-    if (pi->fp_tsremap_init(&ri, tmpbuf, sizeof(tmpbuf) - 1) != TS_SUCCESS) {
-      Warning("Failed to initialize plugin %s (non-zero retval) ... bailing out", pi->path);
-      return -5;
-    }
+    // elevate the access to read files as root if compiled with capabilities, if not
+    // change the effective user to root
+    {
+      uint32_t elevate_access = 0;
+      REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
+      ElevateAccess access(elevate_access != 0);
+
+      if (pi->fp_tsremap_init(&ri, tmpbuf, sizeof(tmpbuf) - 1) != TS_SUCCESS) {
+        Warning("Failed to initialize plugin %s (non-zero retval) ... bailing out", pi->path);
+        return -5;
+      }
+    } // done elevating access
     Debug("remap_plugin", "Remap plugin \"%s\" - initialization completed", c);
   }
 
@@ -1756,7 +1765,16 @@ UrlRewrite::load_remap_plugin(char *argv[], int argc, url_mapping *mp, char *err
   void* ih;
 
   Debug("remap_plugin", "creating new plugin instance");
-  TSReturnCode res = pi->fp_tsremap_new_instance(parc, parv, &ih, tmpbuf, sizeof(tmpbuf) - 1);
+
+  TSReturnCode res = TS_ERROR;
+  // elevate the access to read files as root if compiled with capabilities, if not
+  // change the effective user to root
+  {
+    uint32_t elevate_access = 0;
+    REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
+    ElevateAccess access(elevate_access != 0);
+    res = pi->fp_tsremap_new_instance(parc, parv, &ih, tmpbuf, sizeof(tmpbuf) - 1);
+  } // done elevating access
 
   Debug("remap_plugin", "done creating new plugin instance");