Linux capabilities support

Attached is a patch adding a linux capabilities support to chronyd. It
adds -u option which can be used to specify the user which chronyd
should switch to.
This commit is contained in:
Miroslav Lichvar 2008-11-05 23:50:48 +00:00 committed by Richard P. Curnow
parent 8336f14680
commit be42b4eeea
8 changed files with 95 additions and 6 deletions

View file

@ -1089,6 +1089,9 @@ to work well, it relies on @code{chronyd} having been able to determine
accurate statistics for the difference between the real time clock and accurate statistics for the difference between the real time clock and
system clock last time the computer was on. 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 @item -v
This option displays @code{chronyd's} version number to the terminal and This option displays @code{chronyd's} version number to the terminal and
exits. exits.

View file

@ -79,6 +79,10 @@ been able to determine accurate statistics for the difference
between the real time clock and system clock last time the between the real time clock and system clock last time the
computer was on. computer was on.
.TP .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 .B \-v
This option displays \fBchronyd\fR's version number to the terminal and exits This option displays \fBchronyd\fR's version number to the terminal and exits

9
configure vendored
View file

@ -134,6 +134,7 @@ For better control, use the options below.
--readline-lib-dir=DIR Specify where readline lib directory is --readline-lib-dir=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is --with-ncurses-library=DIR Specify where ncurses lib directory is
--disable-rtc Don't include RTC even on Linux --disable-rtc Don't include RTC even on Linux
--enable-linuxcaps Enable Linux capabilities support
Fine tuning of the installation directories: Fine tuning of the installation directories:
--infodir=DIR info documentation [PREFIX/info] --infodir=DIR info documentation [PREFIX/info]
@ -174,6 +175,7 @@ SYSDEFS=""
# Support for readline (on by default) # Support for readline (on by default)
feat_readline=1 feat_readline=1
feat_rtc=1 feat_rtc=1
feat_linuxcaps=0
readline_lib="" readline_lib=""
readline_inc="" readline_inc=""
ncurses_lib="" ncurses_lib=""
@ -211,6 +213,9 @@ do
--disable-rtc) --disable-rtc)
feat_rtc=0 feat_rtc=0
;; ;;
--enable-linuxcaps)
feat_linuxcaps=1
;;
--help | -h ) --help | -h )
usage usage
exit 0 exit 0
@ -248,6 +253,10 @@ case $SYSTEM in
EXTRA_OBJECTS+=" rtc_linux.o" EXTRA_OBJECTS+=" rtc_linux.o"
EXTRA_DEFS+=" -DFEAT_RTC=1" EXTRA_DEFS+=" -DFEAT_RTC=1"
fi fi
if [ $feat_linuxcaps -eq 1 ] ; then
EXTRA_DEFS+=" -DFEAT_LINUXCAPS=1"
EXTRA_LIBS="-lcap"
fi
SYSDEFS="-DLINUX" SYSDEFS="-DLINUX"
echo "Configuring for " $SYSTEM echo "Configuring for " $SYSTEM
if [ "${MACHINE}" = "alpha" ]; then if [ "${MACHINE}" = "alpha" ]; then

20
main.c
View file

@ -83,19 +83,19 @@ MAI_CleanupAndExit(void)
SRC_DumpSources(); SRC_DumpSources();
} }
RTC_Finalise();
MNL_Finalise(); MNL_Finalise();
ACQ_Finalise(); ACQ_Finalise();
CAM_Finalise();
KEY_Finalise(); KEY_Finalise();
CLG_Finalise(); CLG_Finalise();
NIO_Finalise();
NSR_Finalise(); NSR_Finalise();
NCR_Finalise(); NCR_Finalise();
BRD_Finalise(); BRD_Finalise();
SRC_Finalise(); SRC_Finalise();
SST_Finalise(); SST_Finalise();
REF_Finalise(); REF_Finalise();
RTC_Finalise();
CAM_Finalise();
NIO_Finalise();
SYS_Finalise(); SYS_Finalise();
SCH_Finalise(); SCH_Finalise();
LCL_Finalise(); LCL_Finalise();
@ -206,6 +206,7 @@ int main
(int argc, char **argv) (int argc, char **argv)
{ {
char *conf_file = NULL; char *conf_file = NULL;
char *user = NULL;
int debug = 0; int debug = 0;
int do_init_rtc = 0; int do_init_rtc = 0;
int other_pid; int other_pid;
@ -220,6 +221,9 @@ int main
conf_file = *argv; conf_file = *argv;
} else if (!strcmp("-r", *argv)) { } else if (!strcmp("-r", *argv)) {
reload = 1; reload = 1;
} else if (!strcmp("-u", *argv)) {
++argv, --argc;
user = *argv;
} else if (!strcmp("-s", *argv)) { } else if (!strcmp("-s", *argv)) {
do_init_rtc = 1; do_init_rtc = 1;
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) { } else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
@ -269,19 +273,23 @@ int main
LCL_Initialise(); LCL_Initialise();
SCH_Initialise(); SCH_Initialise();
SYS_Initialise(); SYS_Initialise();
NIO_Initialise();
CAM_Initialise();
RTC_Initialise();
if (user)
SYS_DropRoot(user);
REF_Initialise(); REF_Initialise();
SST_Initialise(); SST_Initialise();
SRC_Initialise(); SRC_Initialise();
BRD_Initialise(); BRD_Initialise();
NCR_Initialise(); NCR_Initialise();
NSR_Initialise(); NSR_Initialise();
NIO_Initialise();
CLG_Initialise(); CLG_Initialise();
KEY_Initialise(); KEY_Initialise();
CAM_Initialise();
ACQ_Initialise(); ACQ_Initialise();
MNL_Initialise(); MNL_Initialise();
RTC_Initialise();
/* From now on, it is safe to do finalisation on exit */ /* From now on, it is safe to do finalisation on exit */
initialised = 1; initialised = 1;

8
sys.c
View file

@ -97,6 +97,14 @@ SYS_Finalise(void)
} }
/* ================================================== */ /* ================================================== */
void SYS_DropRoot(char *user)
{
#if defined(LINUX) && defined (FEAT_LINUXCAPS)
SYS_Linux_DropRoot(user);
#endif
}
/* ================================================== */ /* ================================================== */
/* ================================================== */ /* ================================================== */

3
sys.h
View file

@ -39,4 +39,7 @@ extern void SYS_Initialise(void);
/* Called at the end of the run to do final clean-up */ /* Called at the end of the run to do final clean-up */
extern void SYS_Finalise(void); extern void SYS_Finalise(void);
/* Drop root privileges to the specified user */
extern void SYS_DropRoot(char *user);
#endif /* GOT_SYS_H */ #endif /* GOT_SYS_H */

View file

@ -39,6 +39,14 @@
#include <assert.h> #include <assert.h>
#include <sys/utsname.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 "localp.h"
#include "sys_linux.h" #include "sys_linux.h"
#include "sched.h" #include "sched.h"
@ -831,6 +839,50 @@ SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel)
/* ================================================== */ /* ================================================== */
#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 */ #endif /* LINUX */
/* vim:ts=8 /* vim:ts=8

View file

@ -37,4 +37,6 @@ extern void SYS_Linux_Finalise(void);
extern void SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel); extern void SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel);
extern void SYS_Linux_DropRoot(char *user);
#endif /* GOT_SYS_LINUX_H */ #endif /* GOT_SYS_LINUX_H */