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
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.

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
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

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
--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]
@ -174,6 +175,7 @@ SYSDEFS=""
# Support for readline (on by default)
feat_readline=1
feat_rtc=1
feat_linuxcaps=0
readline_lib=""
readline_inc=""
ncurses_lib=""
@ -211,6 +213,9 @@ do
--disable-rtc)
feat_rtc=0
;;
--enable-linuxcaps)
feat_linuxcaps=1
;;
--help | -h )
usage
exit 0
@ -248,6 +253,10 @@ case $SYSTEM in
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

20
main.c
View file

@ -83,19 +83,19 @@ MAI_CleanupAndExit(void)
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();
@ -206,6 +206,7 @@ int main
(int argc, char **argv)
{
char *conf_file = NULL;
char *user = NULL;
int debug = 0;
int do_init_rtc = 0;
int other_pid;
@ -220,6 +221,9 @@ int main
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)) {
@ -269,19 +273,23 @@ int main
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;

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 */
extern void SYS_Finalise(void);
/* Drop root privileges to the specified user */
extern void SYS_DropRoot(char *user);
#endif /* GOT_SYS_H */

View file

@ -39,6 +39,14 @@
#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"
@ -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 */
/* 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_DropRoot(char *user);
#endif /* GOT_SYS_LINUX_H */