TS-3145: minimally enhance ElevateAccess for different privileges

ElevateAccess only elevates the file access privilege. Add an
explicit notion of privilege so that we can use capabilities to
elevate other kinds of privilege (specifically, process tracing).


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

Branch: refs/heads/master
Commit: d27b31b63d09f23ac6b6104d0ceaa68832da8c3d
Parents: 1906c8b
Author: James Peach <[email protected]>
Authored: Tue Oct 7 09:13:03 2014 -0700
Committer: James Peach <[email protected]>
Committed: Sat Oct 18 12:24:19 2014 -0700

----------------------------------------------------------------------
 lib/ts/ink_cap.cc | 30 +++++++++++++++++++++---------
 lib/ts/ink_cap.h  | 10 +++++++++-
 2 files changed, 30 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d27b31b6/lib/ts/ink_cap.cc
----------------------------------------------------------------------
diff --git a/lib/ts/ink_cap.cc b/lib/ts/ink_cap.cc
index 228d027..e49ec6f 100644
--- a/lib/ts/ink_cap.cc
+++ b/lib/ts/ink_cap.cc
@@ -327,16 +327,28 @@ EnableDeathSignal(int signum)
     best to program defensively and have it available.
  */
 static void
-elevateFileAccess(bool state)
+elevateFileAccess(unsigned level, bool state)
 {
   Debug("privileges", "[elevateFileAccess] state : %d\n", state);
 
   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);
+  unsigned cap_count = 0;
+  cap_value_t cap_list[2];
+
+  if (level & ElevateAccess::FILE_PRIVILEGE) {
+    cap_list[cap_count] = CAP_DAC_OVERRIDE;
+    ++cap_count;
+  }
+
+  if (level & ElevateAccess::TRACE_PRIVILEGE) {
+    cap_list[cap_count] = CAP_SYS_PTRACE;
+    ++cap_count;
+  }
+
+  ink_release_assert(cap_count <= sizeof(cap_list));
+
+  cap_set_flag(cap_state, CAP_EFFECTIVE, cap_count, cap_list, state ? CAP_SET 
: CAP_CLEAR);
   if (cap_set_proc(cap_state) != 0) {
     Fatal("failed to %s privileged capabilities: %s", state ? "acquire" : 
"release", strerror(errno));
   }
@@ -345,8 +357,8 @@ elevateFileAccess(bool state)
 }
 #endif
 
-ElevateAccess::ElevateAccess(const bool state)
-  : elevated(false), saved_uid(geteuid())
+ElevateAccess::ElevateAccess(const bool state, unsigned lvl)
+  : elevated(false), saved_uid(geteuid()), level(lvl)
 {
   if (state == true) {
     elevate();
@@ -372,7 +384,7 @@ void
 ElevateAccess::elevate()
 {
 #if TS_USE_POSIX_CAP
-  elevateFileAccess(true);
+  elevateFileAccess(level, true);
 #else
   // Since we are setting a process-wide credential, we have to block any 
other thread
   // attempting to elevate until this one demotes.
@@ -386,7 +398,7 @@ void
 ElevateAccess::demote()
 {
 #if TS_USE_POSIX_CAP
-  elevateFileAccess(false);
+  elevateFileAccess(level, false);
 #else
   ImpersonateUserID(saved_uid, IMPERSONATE_EFFECTIVE);
   ink_mutex_release(&lock);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d27b31b6/lib/ts/ink_cap.h
----------------------------------------------------------------------
diff --git a/lib/ts/ink_cap.h b/lib/ts/ink_cap.h
index 344c5fe..f763316 100644
--- a/lib/ts/ink_cap.h
+++ b/lib/ts/ink_cap.h
@@ -56,7 +56,13 @@ void ImpersonateUserID(uid_t user, ImpersonationLevel level);
 
 class ElevateAccess {
 public:
-  ElevateAccess(const bool state);
+
+  typedef enum {
+    FILE_PRIVILEGE  = 0x1u, // Access filesystem objects with privilege
+    TRACE_PRIVILEGE = 0x2u  // Trace other processes with privilege
+  } privilege_level;
+
+  ElevateAccess(const bool state, unsigned level = FILE_PRIVILEGE);
   ~ElevateAccess();
 
   void elevate();
@@ -65,6 +71,8 @@ public:
 private:
   bool elevated;
   uid_t saved_uid;
+  unsigned level;
+
 #if !TS_USE_POSIX_CAP
   static ink_mutex lock; // only one thread at a time can elevate
 #endif

Reply via email to