accurate statistics for the difference between the real time clock and
system clock last time the computer was on.
+@item -u <user>
+When this option is used, chronyd will drop root privileges to the specified
+user. So far, it works only on Linux when compiled with capabilities support.
@item -v
This option displays @code{chronyd's} version number to the terminal and
exits.
between the real time clock and system clock last time the
computer was on.
.TP
+\fB\-u\fR \fIuser\fR
+When this option is used, chronyd will drop root privileges to the specified
+user. So far, it works only on Linux when compiled with capabilities support.
+.TP
.B \-v
This option displays \fBchronyd\fR's version number to the terminal and exits
--readline-lib-dir=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is
--disable-rtc Don't include RTC even on Linux
+ --enable-linuxcaps Enable Linux capabilities support
Fine tuning of the installation directories:
--infodir=DIR info documentation [PREFIX/info]
# Support for readline (on by default)
feat_readline=1
feat_rtc=1
+feat_linuxcaps=0
readline_lib=""
readline_inc=""
ncurses_lib=""
--disable-rtc)
feat_rtc=0
;;
+ --enable-linuxcaps)
+ feat_linuxcaps=1
+ ;;
--help | -h )
usage
exit 0
EXTRA_OBJECTS+=" rtc_linux.o"
EXTRA_DEFS+=" -DFEAT_RTC=1"
fi
+ if [ $feat_linuxcaps -eq 1 ] ; then
+ EXTRA_DEFS+=" -DFEAT_LINUXCAPS=1"
+ EXTRA_LIBS="-lcap"
+ fi
SYSDEFS="-DLINUX"
echo "Configuring for " $SYSTEM
if [ "${MACHINE}" = "alpha" ]; then
SRC_DumpSources();
}
- RTC_Finalise();
MNL_Finalise();
ACQ_Finalise();
- CAM_Finalise();
KEY_Finalise();
CLG_Finalise();
- NIO_Finalise();
NSR_Finalise();
NCR_Finalise();
BRD_Finalise();
SRC_Finalise();
SST_Finalise();
REF_Finalise();
+ RTC_Finalise();
+ CAM_Finalise();
+ NIO_Finalise();
SYS_Finalise();
SCH_Finalise();
LCL_Finalise();
(int argc, char **argv)
{
char *conf_file = NULL;
+ char *user = NULL;
int debug = 0;
int do_init_rtc = 0;
int other_pid;
conf_file = *argv;
} else if (!strcmp("-r", *argv)) {
reload = 1;
+ } else if (!strcmp("-u", *argv)) {
+ ++argv, --argc;
+ user = *argv;
} else if (!strcmp("-s", *argv)) {
do_init_rtc = 1;
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
LCL_Initialise();
SCH_Initialise();
SYS_Initialise();
+ NIO_Initialise();
+ CAM_Initialise();
+ RTC_Initialise();
+
+ if (user)
+ SYS_DropRoot(user);
+
REF_Initialise();
SST_Initialise();
SRC_Initialise();
BRD_Initialise();
NCR_Initialise();
NSR_Initialise();
- NIO_Initialise();
CLG_Initialise();
KEY_Initialise();
- CAM_Initialise();
ACQ_Initialise();
MNL_Initialise();
- RTC_Initialise();
/* From now on, it is safe to do finalisation on exit */
initialised = 1;
}
/* ================================================== */
+
+void SYS_DropRoot(char *user)
+{
+#if defined(LINUX) && defined (FEAT_LINUXCAPS)
+ SYS_Linux_DropRoot(user);
+#endif
+}
+
/* ================================================== */
/* ================================================== */
/* Called at the end of the run to do final clean-up */
extern void SYS_Finalise(void);
+/* Drop root privileges to the specified user */
+extern void SYS_DropRoot(char *user);
+
#endif /* GOT_SYS_H */
#include <assert.h>
#include <sys/utsname.h>
+#ifdef FEAT_LINUXCAPS
+#include <sys/types.h>
+#include <pwd.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <grp.h>
+#endif
+
#include "localp.h"
#include "sys_linux.h"
#include "sched.h"
/* ================================================== */
+#ifdef FEAT_LINUXCAPS
+void
+SYS_Linux_DropRoot(char *user)
+{
+ struct passwd *pw;
+ cap_t cap;
+
+ if (user == NULL)
+ return;
+
+ if ((pw = getpwnam(user)) == NULL) {
+ LOG_FATAL(LOGF_SysLinux, "getpwnam(%s) failed", user);
+ }
+
+ if (prctl(PR_SET_KEEPCAPS, 1)) {
+ LOG_FATAL(LOGF_SysLinux, "prcap() failed");
+ }
+
+ if (setgroups(0, NULL)) {
+ LOG_FATAL(LOGF_SysLinux, "setgroups() failed");
+ }
+
+ if (setgid(pw->pw_gid)) {
+ LOG_FATAL(LOGF_SysLinux, "setgid(%d) failed", pw->pw_gid);
+ }
+
+ if (setuid(pw->pw_uid)) {
+ LOG_FATAL(LOGF_SysLinux, "setuid(%d) failed", pw->pw_uid);
+ }
+
+ if ((cap = cap_from_text("cap_sys_time=ep")) == NULL) {
+ LOG_FATAL(LOGF_SysLinux, "cap_from_text() failed");
+ }
+
+ if (cap_set_proc(cap)) {
+ LOG_FATAL(LOGF_SysLinux, "cap_set_proc() failed");
+ }
+
+ LOG(LOGS_INFO, LOGF_SysLinux, "Privileges dropped to user %s", user);
+}
+#endif
+
+/* ================================================== */
+
#endif /* LINUX */
/* vim:ts=8
extern void SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel);
+extern void SYS_Linux_DropRoot(char *user);
+
#endif /* GOT_SYS_LINUX_H */