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

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


Run chronyd as a non-privileged user, using the privops helper to
perform adjtime(), settimeofday() and bind() functions on its behalf.
---
 chrony.texi.in | 13 ++++++++++---
 chronyd.8.in   |  8 +++++++-
 configure      |  8 ++++++++
 ntp_io.c       |  3 ++-
 sys.c          |  2 ++
 sys_macosx.c   | 32 ++++++++++++++++++++++++++++----
 sys_macosx.h   |  1 +
 7 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/chrony.texi.in b/chrony.texi.in
index 18ebfce..06f24ff 100644
--- a/chrony.texi.in
+++ b/chrony.texi.in
@@ -978,7 +978,14 @@ 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
+Mac OS X.
+
+In the Mac OS X implementation chronyd forks into two processes. The
+child process retains root privilege but can only perform a very limited range
+of privileged system calls on behalf of the parent. The parent process drops
+root privilege to run as the specified system user. Both processes are visible
+in the list of running processes.
 @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
@@ -3169,8 +3176,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 or on MaxOS X.
 
 The default value is @code{@DEFAULT_USER@}.
 @c }}}
diff --git a/chronyd.8.in b/chronyd.8.in
index b5b0882..a2889d2 100644
--- a/chronyd.8.in
+++ b/chronyd.8.in
@@ -103,7 +103,13 @@ This option sets the name of the system user to which \fBchronyd\fR will switch
 after start in order to drop root privileges.  It overrides the \fBuser\fR
 directive (default \fB@DEFAULT_USER@\fR).  It may be set to a non-root user
 only when \fBchronyd\fR is compiled with support for Linux capabilities
-(libcap) or on NetBSD with the \fB/dev/clockctl\fR device.
+(libcap), on NetBSD with the \fB/dev/clockctl\fR device or on Mac OS X.
+
+In the Mac OS X implementation chronyd forks into two processes. The child
+process retains root privilege but can only perform a very limited range of
+privileged system calls on behalf of the parent. The parent process drops
+root privilege to run as the specified system user. Both processes are visible
+in the list of running processes.
 .TP
 \fB\-F\fR \fIlevel\fR
 This option configures a system call filter when \fBchronyd\fR is compiled with
diff --git a/configure b/configure
index 16fdf8d..5a52abf 100755
--- a/configure
+++ b/configure
@@ -392,6 +392,14 @@ case $OPERATINGSYSTEM in
         EXTRA_LIBS="-lresolv"
         EXTRA_CLI_LIBS="-lresolv"
         add_def MACOSX
+        if [ $feat_droproot = "1" ]; then
+          EXTRA_OBJECTS="$EXTRA_OBJECTS privops.o"
+          add_def PRIVOPS_ADJUSTTIME
+          add_def PRIVOPS_SETTIME
+          add_def PRIVOPS_BINDSOCKET
+          add_def PRIVOPS_HELPER
+          add_def FEAT_PRIVDROP
+        fi
         echo "Configuring for MacOS X (" $SYSTEM "MacOS X version" $VERSION ")"
     ;;
     SunOS)
diff --git a/ntp_io.c b/ntp_io.c
index 24b1190..4c250ae 100644
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -37,6 +37,7 @@
 #include "local.h"
 #include "logging.h"
 #include "conf.h"
+#include "privops.h"
 #include "util.h"
 
 #define INVALID_SOCK_FD -1
@@ -221,7 +222,7 @@ prepare_socket(int family, int port_number, int client_only)
 #endif
 
   /* Bind the socket if a port or address was specified */
-  if (my_addr_len > 0 && bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
+  if (my_addr_len > 0 && PRV_BindSocket(sock_fd, &my_addr.u, my_addr_len) < 0) {
     LOG(LOGS_ERR, LOGF_NtpIO, "Could not bind %s NTP socket : %s",
         UTI_SockaddrFamilyToString(family), strerror(errno));
     close(sock_fd);
diff --git a/sys.c b/sys.c
index 4009796..613ef74 100644
--- a/sys.c
+++ b/sys.c
@@ -92,6 +92,8 @@ void SYS_DropRoot(uid_t uid, gid_t gid)
   SYS_Linux_DropRoot(uid, gid);
 #elif defined(NETBSD) && defined(FEAT_PRIVDROP)
   SYS_NetBSD_DropRoot(uid, gid);
+#elif defined(MACOSX) && defined(FEAT_PRIVDROP)
+  SYS_MaxOSX_DropRoot(uid, gid);
 #else
   LOG_FATAL(LOGF_Sys, "dropping root privileges not supported");
 #endif
diff --git a/sys_macosx.c b/sys_macosx.c
index d1b620f..fc52702 100644
--- a/sys_macosx.c
+++ b/sys_macosx.c
@@ -50,6 +50,7 @@
 #include "localp.h"
 #include "sched.h"
 #include "logging.h"
+#include "privops.h"
 #include "util.h"
 
 /* ================================================== */
@@ -117,7 +118,7 @@ clock_initialise(void)
   newadj.tv_sec = 0;
   newadj.tv_usec = 0;
 
-  if (adjtime(&newadj, &oldadj) < 0) {
+  if (PRV_AdjustTime(&newadj, &oldadj) < 0) {
     LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
   }
 }
@@ -169,7 +170,7 @@ start_adjust(void)
   UTI_TimevalToDouble(&newadj, &adjustment_requested);
   rounding_error = adjust_required - adjustment_requested;
 
-  if (adjtime(&newadj, &oldadj) < 0) {
+  if (PRV_AdjustTime(&newadj, &oldadj) < 0) {
     LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
   }
 
@@ -193,7 +194,7 @@ stop_adjust(void)
   zeroadj.tv_sec = 0;
   zeroadj.tv_usec = 0;
 
-  if (adjtime(&zeroadj, &remadj) < 0) {
+  if (PRV_AdjustTime(&zeroadj, &remadj) < 0) {
     LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
   }
 
@@ -244,7 +245,7 @@ apply_step_offset(double offset)
 
   UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
 
-  if (settimeofday(&new_time, NULL) < 0) {
+  if (PRV_SetTime(&new_time, NULL) < 0) {
     DEBUG_LOG(LOGF_SysMacOSX, "settimeofday() failed");
     return 0;
   }
@@ -400,6 +401,26 @@ SYS_MacOSX_SetScheduler(int SchedPriority)
 
 /* ================================================== */
 
+#ifdef FEAT_PRIVDROP
+void SYS_MaxOSX_DropRoot(uid_t uid, gid_t gid)
+{
+  PRV_Initialise();
+
+  if (setgroups(0, NULL))
+    LOG_FATAL(LOGF_SysMacOSX, "setgroups() failed : %s", strerror(errno));
+
+  if (setgid(gid))
+    LOG_FATAL(LOGF_SysMacOSX, "setgid(%d) failed : %s", gid, strerror(errno));
+
+  if (setuid(uid))
+    LOG_FATAL(LOGF_SysMacOSX, "setuid(%d) failed : %s", uid, strerror(errno));
+
+  DEBUG_LOG(LOGF_SysMacOSX, "Root dropped to uid %d gid %d", uid, gid);
+}
+#endif
+
+/* ================================================== */
+
 void
 SYS_MacOSX_Initialise(void)
 {
@@ -423,6 +444,9 @@ SYS_MacOSX_Finalise(void)
   SCH_RemoveTimeout(drift_removal_id);
 
   clock_finalise();
+#ifdef FEAT_PRIVDROP
+  PRV_Finalise();
+#endif
 }
 
 /* ================================================== */
diff --git a/sys_macosx.h b/sys_macosx.h
index 707700d..b9ae905 100644
--- a/sys_macosx.h
+++ b/sys_macosx.h
@@ -31,6 +31,7 @@
 #define GOT_SYS_MACOSX_H
 
 void SYS_MacOSX_SetScheduler(int SchedPriority);
+void SYS_MaxOSX_DropRoot(uid_t uid, gid_t gid);
 void SYS_MacOSX_Initialise(void);
 void SYS_MacOSX_Finalise(void);
 
-- 
2.4.9 (Apple Git-60)


-- 
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/