[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();