From 7b6435b2b8bab7d0ef05d10395d5d732ebbd0ca3 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 25 Aug 2015 12:15:58 +0200 Subject: [PATCH] sys_netbsd: allow running without root privileges On NetBSD programs with write access to /dev/clockctl can adjust or set the system clock without the root privileges. Add a function to drop the privileges and check if the process has write access to the device to get a more descriptive error message when the chrony uid/gid doesn't match the owner of the device. --- configure | 8 ++++++++ sys.c | 2 ++ sys_netbsd.c | 24 ++++++++++++++++++++++++ sys_netbsd.h | 2 ++ 4 files changed, 36 insertions(+) diff --git a/configure b/configure index dcc7367..3959b04 100755 --- a/configure +++ b/configure @@ -215,6 +215,7 @@ feat_rtc=1 try_rtc=0 feat_droproot=1 try_libcap=0 +try_clockctl=0 readline_lib="" readline_inc="" ncurses_lib="" @@ -405,6 +406,7 @@ case $SYSTEM in NetBSD-* ) EXTRA_OBJECTS="sys_netbsd.o" EXTRA_LIBS="-lkvm" + try_clockctl=1 add_def NETBSD echo "Configuring for $SYSTEM" ;; @@ -590,6 +592,12 @@ then EXTRA_LIBS="$EXTRA_LIBS -lcap" fi +if [ $feat_droproot = "1" ] && [ $try_clockctl = "1" ] && \ + test_code '' 'sys/clockctl.h' '' '' '' +then + add_def FEAT_PRIVDROP +fi + if [ $feat_rtc = "1" ] && [ $try_rtc = "1" ] && \ test_code '' 'sys/ioctl.h linux/rtc.h' '' '' \ 'ioctl(1, RTC_UIE_ON&RTC_UIE_OFF&RTC_RD_TIME&RTC_SET_TIME, 0&RTC_UF);' diff --git a/sys.c b/sys.c index 9de9ee1..918db4b 100644 --- a/sys.c +++ b/sys.c @@ -113,6 +113,8 @@ void SYS_DropRoot(uid_t uid, gid_t gid) { #if defined(LINUX) && defined (FEAT_PRIVDROP) SYS_Linux_DropRoot(uid, gid); +#elif defined(NETBSD) && defined(FEAT_PRIVDROP) + SYS_NetBSD_DropRoot(uid, gid); #else LOG_FATAL(LOGF_Sys, "dropping root privileges not supported"); #endif diff --git a/sys_netbsd.c b/sys_netbsd.c index 9c3e1ef..2d73629 100644 --- a/sys_netbsd.c +++ b/sys_netbsd.c @@ -324,5 +324,29 @@ SYS_NetBSD_Finalise(void) /* ================================================== */ +#ifdef FEAT_PRIVDROP +void +SYS_NetBSD_DropRoot(uid_t uid, gid_t gid) +{ + int fd; + + if (setgroups(0, NULL)) + LOG_FATAL(LOGF_SysNetBSD, "setgroups() failed : %s", strerror(errno)); + + if (setgid(gid)) + LOG_FATAL(LOGF_SysNetBSD, "setgid(%d) failed : %s", gid, strerror(errno)); + + if (setuid(uid)) + LOG_FATAL(LOGF_SysNetBSD, "setuid(%d) failed : %s", uid, strerror(errno)); + + DEBUG_LOG(LOGF_SysNetBSD, "Root dropped to uid %d gid %d", uid, gid); + + /* Check if we have write access to /dev/clockctl */ + fd = open("/dev/clockctl", O_WRONLY); + if (fd < 0) + LOG_FATAL(LOGF_SysNetBSD, "Can't write to /dev/clockctl"); + close(fd); +} +#endif #endif /* NETBSD */ diff --git a/sys_netbsd.h b/sys_netbsd.h index a697304..052f5b7 100644 --- a/sys_netbsd.h +++ b/sys_netbsd.h @@ -32,4 +32,6 @@ void SYS_NetBSD_Initialise(void); void SYS_NetBSD_Finalise(void); +void SYS_NetBSD_DropRoot(uid_t uid, gid_t gid); + #endif