[chrony-dev] chronyd systemd ehancement patch submition

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


Hi,

Chrony is currently designed as a classic system daemon that drops its privileges once its working environment has been set up.

Linux distributions that use systemd can delegate those security tasks to systemd unit configuration rules.

 ```
 User=chrony

 AmbientCapabilities=CAP_SYS_TIME
 CapabilityBoundingSet=CAP_SYS_TIME
 ```

Those indicative and non exhaustive configuration options ensure chrony is directly executed as unprivileged user, therefore reducing the attack surface.

I have attached to this email a patch with the following changes:

'-S' runtime option that:
    - sets no-fork mode
    - avoids the superuser check
    - avoids pid file creation and uses
    - sets the user from uid
    - avoids privileges dropping

Those changes were initially created for the CLIP OS project (https://clip-os.org) but may be of interest for systemd based Linux distribution.

Any feedback welcome,
Thanks

diff --git a/conf.c b/conf.c
index a5525ce..149f9d2 100644
--- a/conf.c
+++ b/conf.c
@@ -323,7 +323,7 @@ check_number_of_args(char *line, int num)
 /* ================================================== */
 
 void
-CNF_Initialise(int r, int client_only)
+CNF_Initialise(int r, int client_only, int systemd)
 {
   restarted = r;
 
@@ -341,12 +341,26 @@ CNF_Initialise(int r, int client_only)
   logdir = Strdup("");
   rtc_device = Strdup(DEFAULT_RTC_DEVICE);
   hwclock_file = Strdup(DEFAULT_HWCLOCK_FILE);
-  user = Strdup(DEFAULT_USER);
-
+  if (!systemd) {
+    user = Strdup(DEFAULT_USER);
+  }
   if (client_only) {
     cmd_port = ntp_port = 0;
     bind_cmd_path = Strdup("");
     pidfile = Strdup("");
+  } else if (systemd) {
+      struct passwd *pw;
+      uid_t uid;
+
+      uid = geteuid();
+      pw = getpwuid(uid);
+      if (pw) {
+        user = Strdup(pw->pw_name);
+      } else {
+        LOG_FATAL("Could not get username for UID %u", uid);
+      }
+      bind_cmd_path = Strdup(DEFAULT_COMMAND_SOCKET);
+      pidfile = Strdup("");
   } else {
     bind_cmd_path = Strdup(DEFAULT_COMMAND_SOCKET);
     pidfile = Strdup(DEFAULT_PID_FILE);
diff --git a/conf.h b/conf.h
index 43217fc..2a37421 100644
--- a/conf.h
+++ b/conf.h
@@ -31,7 +31,7 @@
 #include "addressing.h"
 #include "reference.h"
 
-extern void CNF_Initialise(int restarted, int client_only);
+extern void CNF_Initialise(int restarted, int client_only, int systemd);
 extern void CNF_Finalise(void);
 
 extern char *CNF_GetRtcDevice(void);
diff --git a/main.c b/main.c
index e0b5c48..04768b8 100644
--- a/main.c
+++ b/main.c
@@ -409,6 +409,7 @@ int main
   int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
   int clock_control = 1, system_log = 1, log_severity = LOGS_INFO;
   int config_args = 0;
+  int systemd = 0;
 
   do_platform_checks();
 
@@ -428,7 +429,7 @@ int main
   optind = 1;
 
   /* Parse short command-line options */
-  while ((opt = getopt(argc, argv, "46df:F:hl:L:mnP:qQrRst:u:vx")) != -1) {
+  while ((opt = getopt(argc, argv, "46df:F:hl:L:mnP:qQrRsSt:u:vx")) != -1) {
     switch (opt) {
       case '4':
       case '6':
@@ -482,6 +483,10 @@ int main
       case 's':
         do_init_rtc = 1;
         break;
+      case 'S':
+	systemd = 1;
+	nofork = 1;
+	break ;
       case 't':
         timeout = parse_int_arg(optarg);
         break;
@@ -500,7 +505,7 @@ int main
     }
   }
 
-  if (getuid() && !client_only)
+  if (getuid() && !client_only && !systemd)
     LOG_FATAL("Not superuser");
 
   /* Turn into a daemon */
@@ -520,7 +525,7 @@ int main
 
   DNS_SetAddressFamily(address_family);
 
-  CNF_Initialise(restarted, client_only);
+  CNF_Initialise(restarted, client_only, systemd);
 
   /* Parse the config file or the remaining command line arguments */
   config_args = argc - optind;
@@ -532,7 +537,8 @@ int main
   }
 
   /* Check whether another chronyd may already be running */
-  check_pidfile();
+  if (!systemd)
+    check_pidfile();
 
   if (!user)
     user = CNF_GetUser();
@@ -545,7 +551,8 @@ int main
   CNF_CreateDirs(pw->pw_uid, pw->pw_gid);
 
   /* Write our pidfile to prevent other instances from running */
-  write_pidfile();
+  if (!systemd)
+    write_pidfile();
 
   PRV_Initialise();
   LCL_Initialise();
@@ -576,7 +583,7 @@ int main
   }
 
   /* Drop root privileges if the specified user has a non-zero UID */
-  if (!geteuid() && (pw->pw_uid || pw->pw_gid))
+  if ((!geteuid() && (pw->pw_uid || pw->pw_gid)) && !systemd)
     SYS_DropRoot(pw->pw_uid, pw->pw_gid);
 
   REF_Initialise();


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