]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sys_macosx: drop root privileges
authorBryan Christianson <bryan@whatroute.net>
Tue, 24 Nov 2015 08:01:59 +0000 (21:01 +1300)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 24 Nov 2015 08:29:22 +0000 (09:29 +0100)
Run chronyd as a non-privileged user, using the privops helper to
perform adjtime(), settimeofday() and bind() functions on its behalf.

chrony.texi.in
chronyd.8.in
configure
ntp_io.c
sys.c
sys_macosx.c
sys_macosx.h

index 18ebfce9cb4caaa3d845d1083f8dcefc9ba6ff11..895b9d51a6ad92a98108ba9599fb70cf9c0524b1 100644 (file)
@@ -978,7 +978,13 @@ 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 @code{chronyd} forks into two processes.  The
+child process retains root privileges but can only perform a very limited range
+of privileged system calls on behalf of the parent.  The parent process drops
+root privileges to run as the specified system user.
 @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 +3175,13 @@ 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 Mac OS X.
+
+In the Mac OS X implementation @code{chronyd} forks into two processes.  The
+child process retains root privileges but can only perform a very limited range
+of privileged system calls on behalf of the parent.  The parent process drops
+root privileges to run as the specified system user.
 
 The default value is @code{@DEFAULT_USER@}.
 @c }}}
index b5b0882c066d46bce4ccdb42b6d139ec9465e845..0a10d01799e759d55749bd7edd2d6f89b8c42fd7 100644 (file)
@@ -103,7 +103,12 @@ 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 \fBchronyd\fR forks into two processes.  The
+child process retains root privileges but can only perform a very limited range
+of privileged system calls on behalf of the parent.  The parent process drops
+root privileges to run as the specified system user.
 .TP
 \fB\-F\fR \fIlevel\fR
 This option configures a system call filter when \fBchronyd\fR is compiled with
index 16fdf8dc9222e426c2fb87d822d05ee43deb5e37..5a52abf1fedcbb5fedfb9d8a20f7277b704acdaf 100755 (executable)
--- 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)
index 24b119027af6efcc10e78e2a062f50a033c68bab..4c250aeb3d20605e0b837b5306bfb70ba5a94759 100644 (file)
--- 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 400979660b3124aac409b00328bc5e1cccba4a89..f3844c64060a49ad6f0a21c65b34fde1ce91c802 100644 (file)
--- 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_MacOSX_DropRoot(uid, gid);
 #else
   LOG_FATAL(LOGF_Sys, "dropping root privileges not supported");
 #endif
index d1b620faf2f163ed05a6826449bf7b7fe2187380..bda73085cd6c8c9f5660b352f20216183ac57895 100644 (file)
@@ -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_MacOSX_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
 }
 
 /* ================================================== */
index 707700db45dc3c008b0898d66c1d831e654ecbb4..b9114ff7465a717bc605a15ea67b813359f18d2b 100644 (file)
@@ -31,6 +31,7 @@
 #define GOT_SYS_MACOSX_H
 
 void SYS_MacOSX_SetScheduler(int SchedPriority);
+void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid);
 void SYS_MacOSX_Initialise(void);
 void SYS_MacOSX_Finalise(void);