[chrony-dev] [PATCH] MacOS X - Drop root privileges

[ Thread Index | Date Index | More chrony.tuxfamily.org/chrony-dev Archives ]


When a user is specified to chronyd (command line or config file), chronyd
will drop privileges, restoring them when required for privileged system
calls.
---
 chrony.texi.in |  7 +++--
 configure      |  3 ++
 sys.c          |  2 ++
 sys_macosx.c   | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 sys_macosx.h   |  2 ++
 5 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/chrony.texi.in b/chrony.texi.in
index e26e61c..37dd526 100644
--- a/chrony.texi.in
+++ b/chrony.texi.in
@@ -999,7 +999,8 @@ This option sets the name of the system user to which @code{chronyd} will
 switch after start in order to drop root privileges.  It overrides the
 @code{user} directive (default @code{@DEFAULT_USER@}).  It may be set to a
 non-root user only when @code{chronyd} is compiled with support for Linux
-capabilities (libcap) or on NetBSD with the @code{/dev/clockctl} device.
+capabilities (libcap), on NetBSD with the @code{/dev/clockctl} device or
+on MacOS X.
 @item -F <level>
 This option configures a system call filter when @code{chronyd} is compiled with
 support for the Linux secure computing (seccomp) facility. In level 1 the
@@ -3179,8 +3180,8 @@ Valid measurements with corresponding compensations are logged to the
 The @code{user} directive sets the name of the system user to which
 @code{chronyd} will switch after start in order to drop root privileges.
 It may be set to a non-root user only when @code{chronyd} is compiled with
-support for Linux capabilities (libcap) or on NetBSD with the
-@code{/dev/clockctl} device.
+support for Linux capabilities (libcap), on NetBSD with the
+@code{/dev/clockctl} device and on MacOS X.
 
 The default value is @code{@DEFAULT_USER@}.
 @c }}}
diff --git a/configure b/configure
index abdbf2d..cec6334 100755
--- a/configure
+++ b/configure
@@ -430,6 +430,9 @@ case $SYSTEM in
         EXTRA_LIBS="-lresolv"
         EXTRA_CLI_LIBS="-lresolv"
         add_def MACOSX
+        if [ $feat_droproot = "1" ]; then
+          add_def FEAT_PRIVDROP
+        fi
         echo "Configuring for MacOS X (" $SYSTEM "MacOS X version" $VERSION ")"
     ;;
     SunOS-i86pc* )                                          
diff --git a/sys.c b/sys.c
index c5c4250..1dd4ed7 100644
--- a/sys.c
+++ b/sys.c
@@ -113,6 +113,8 @@ void SYS_DropRoot(uid_t uid, gid_t gid)
 {
 #if defined(LINUX) && defined (FEAT_PRIVDROP)
   SYS_Linux_DropRoot(uid, gid);
+#elif defined(MACOSX) && defined(FEAT_PRIVDROP)
+  SYS_MacOSX_DropRoot(uid, gid);
 #elif defined(NETBSD) && defined(FEAT_PRIVDROP)
   SYS_NetBSD_DropRoot(uid, gid);
 #else
diff --git a/sys_macosx.c b/sys_macosx.c
index 200b62c..77691c5 100644
--- a/sys_macosx.c
+++ b/sys_macosx.c
@@ -96,6 +96,77 @@ static struct timeval Tdrift;
 
 #define NANOS_PER_MSEC (1000000ULL)
 
+/* Effective UID and GID - when privileges are dropped */
+
+static uid_t s_euid = 0;
+static gid_t s_egid = 0;
+
+/* ================================================== */
+
+/* drop root privileges */
+
+static inline void
+priv_disable(void)
+{
+  if (s_egid != 0 && setegid(s_egid) != 0) {
+    LOG_FATAL(LOGF_SysMacOSX, "setegid(%d) failed: %s", s_egid, strerror(errno));
+  }
+
+  if (s_euid != 0 && seteuid(s_euid) != 0) {
+    LOG_FATAL(LOGF_SysMacOSX, "seteuid(%d) failed: %s", s_euid, strerror(errno));
+  }
+}
+
+/* ================================================== */
+
+/* restore root privileges */
+
+static inline void
+priv_enable(void)
+{
+  if (s_euid == 0 && s_egid == 0) {
+    return;
+  }
+
+  if (seteuid(0) != 0) {
+    LOG_FATAL(LOGF_SysMacOSX, "seteuid(%d) failed: %s", 0, strerror(errno));
+  }
+
+  if (setegid(0) != 0) {
+    LOG_FATAL(LOGF_SysMacOSX, "setegid(%d) failed: %s", 0, strerror(errno));
+  }
+}
+
+/* ================================================== */
+
+/* adjtime() wrapper  - regain root privileges and drop on completion */
+
+static inline int
+mac_adjtime(const struct timeval *delta, struct timeval *olddelta)
+{
+  int ret;
+
+  priv_enable();
+  ret = adjtime(delta, olddelta);
+  priv_disable();
+  return ret;
+}
+
+/* ================================================== */
+
+/* settimeofday() wrapper  - regain root privileges and drop on completion */
+
+static inline int
+mac_settimeofday(const struct timeval *tp, const struct timezone *tzp)
+{
+  int ret;
+
+  priv_enable();
+  ret = settimeofday(tp, tzp);
+  priv_disable();
+  return ret;
+}
+
 /* ================================================== */
 
 static void
@@ -117,7 +188,7 @@ clock_initialise(void)
   newadj.tv_sec = 0;
   newadj.tv_usec = 0;
 
-  if (adjtime(&newadj, &oldadj) < 0) {
+  if (mac_adjtime(&newadj, &oldadj) < 0) {
     LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
   }
 }
@@ -169,7 +240,7 @@ start_adjust(void)
   UTI_TimevalToDouble(&newadj, &adjustment_requested);
   rounding_error = adjust_required - adjustment_requested;
 
-  if (adjtime(&newadj, &oldadj) < 0) {
+  if (mac_adjtime(&newadj, &oldadj) < 0) {
     LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
   }
 
@@ -193,7 +264,7 @@ stop_adjust(void)
   zeroadj.tv_sec = 0;
   zeroadj.tv_usec = 0;
 
-  if (adjtime(&zeroadj, &remadj) < 0) {
+  if (mac_adjtime(&zeroadj, &remadj) < 0) {
     LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
   }
 
@@ -244,7 +315,7 @@ apply_step_offset(double offset)
 
   UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
 
-  if (settimeofday(&new_time, NULL) < 0) {
+  if (mac_settimeofday(&new_time, NULL) < 0) {
     DEBUG_LOG(LOGF_SysMacOSX, "settimeofday() failed");
     return 0;
   }
@@ -431,4 +502,14 @@ SYS_MacOSX_Finalise(void)
 
 /* ================================================== */
 
+void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid)
+{
+  s_euid = uid;
+  s_egid = gid;
+
+  priv_disable();
+}
+
+/* ================================================== */
+
 #endif
diff --git a/sys_macosx.h b/sys_macosx.h
index 707700d..fbe3527 100644
--- a/sys_macosx.h
+++ b/sys_macosx.h
@@ -34,4 +34,6 @@ void SYS_MacOSX_SetScheduler(int SchedPriority);
 void SYS_MacOSX_Initialise(void);
 void SYS_MacOSX_Finalise(void);
 
+void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid);
+
 #endif
-- 
2.3.2 (Apple Git-55)


-- 
To unsubscribe email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "unsubscribe" in the subject.
For help email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "help" in the subject.
Trouble?  Email listmaster@xxxxxxxxxxxxxxxxxxxx.


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/