From 3cf6acdf24f6212d88ac096d255a9a8be7ab408c Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 8 Dec 2015 17:16:45 +0100 Subject: [PATCH] util: add function for dropping root privileges Share the code for dropping supplementary groups and setting effective, saved, and real user UID/GID between system drivers. --- sys_linux.c | 16 ++-------------- sys_macosx.c | 11 +---------- sys_netbsd.c | 11 +---------- sysincl.h | 1 + util.c | 20 ++++++++++++++++++++ util.h | 3 +++ 6 files changed, 28 insertions(+), 34 deletions(-) diff --git a/sys_linux.c b/sys_linux.c index 1a3f1be..98de5b4 100644 --- a/sys_linux.c +++ b/sys_linux.c @@ -45,7 +45,6 @@ #ifdef FEAT_PRIVDROP #include #include -#include #endif #ifdef FEAT_SCFILTER @@ -66,6 +65,7 @@ #include "sys_timex.h" #include "conf.h" #include "logging.h" +#include "util.h" /* Frequency scale to convert from ppm to the timex freq */ #define FREQ_SCALE (double)(1 << 16) @@ -409,17 +409,7 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid) LOG_FATAL(LOGF_SysLinux, "prctl() failed"); } - if (setgroups(0, NULL)) { - LOG_FATAL(LOGF_SysLinux, "setgroups() failed"); - } - - if (setgid(gid)) { - LOG_FATAL(LOGF_SysLinux, "setgid(%d) failed", gid); - } - - if (setuid(uid)) { - LOG_FATAL(LOGF_SysLinux, "setuid(%d) failed", uid); - } + UTI_DropRoot(uid, gid); if ((cap = cap_from_text("cap_net_bind_service,cap_sys_time=ep")) == NULL) { LOG_FATAL(LOGF_SysLinux, "cap_from_text() failed"); @@ -430,8 +420,6 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid) } cap_free(cap); - - DEBUG_LOG(LOGF_SysLinux, "Root dropped to uid %d gid %d", uid, gid); } #endif diff --git a/sys_macosx.c b/sys_macosx.c index fb2a70e..46e439e 100644 --- a/sys_macosx.c +++ b/sys_macosx.c @@ -419,16 +419,7 @@ void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid) { PRV_StartHelper(); - if (setgroups(0, NULL)) - LOG_FATAL(LOGF_SysMacOSX, "setgroups() failed : %s", strerror(errno)); - - if (setgid(gid)) - LOG_FATAL(LOGF_SysMacOSX, "setgid(%d) failed : %s", gid, strerror(errno)); - - if (setuid(uid)) - LOG_FATAL(LOGF_SysMacOSX, "setuid(%d) failed : %s", uid, strerror(errno)); - - DEBUG_LOG(LOGF_SysMacOSX, "Root dropped to uid %d gid %d", uid, gid); + UTI_DropRoot(uid, gid); } #endif diff --git a/sys_netbsd.c b/sys_netbsd.c index 7a95d3f..e0b5b50 100644 --- a/sys_netbsd.c +++ b/sys_netbsd.c @@ -127,16 +127,7 @@ SYS_NetBSD_DropRoot(uid_t uid, gid_t gid) PRV_StartHelper(); - 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); + UTI_DropRoot(uid, gid); /* Check if we have write access to /dev/clockctl */ fd = open("/dev/clockctl", O_WRONLY); diff --git a/sysincl.h b/sysincl.h index 7dbc8f2..2132f82 100644 --- a/sysincl.h +++ b/sysincl.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/util.c b/util.c index b01b936..313bb29 100644 --- a/util.c +++ b/util.c @@ -1118,6 +1118,26 @@ UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid) /* ================================================== */ +void +UTI_DropRoot(uid_t uid, gid_t gid) +{ + /* Drop supplementary groups */ + if (setgroups(0, NULL)) + LOG_FATAL(LOGF_Util, "setgroups() failed : %s", strerror(errno)); + + /* Set effective, saved and real group ID */ + if (setgid(gid)) + LOG_FATAL(LOGF_Util, "setgid(%d) failed : %s", gid, strerror(errno)); + + /* Set effective, saved and real user ID */ + if (setuid(uid)) + LOG_FATAL(LOGF_Util, "setuid(%d) failed : %s", uid, strerror(errno)); + + DEBUG_LOG(LOGF_Util, "Dropped root privileges: UID %d GID %d", uid, gid); +} + +/* ================================================== */ + #define DEV_URANDOM "/dev/urandom" void diff --git a/util.h b/util.h index ebd0d20..69caae1 100644 --- a/util.h +++ b/util.h @@ -145,6 +145,9 @@ extern int UTI_CreateDirAndParents(const char *path, mode_t mode, uid_t uid, gid permissions and its uid/gid must match the specified values. */ extern int UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid); +/* Set process user/group IDs and drop supplementary groups */ +extern void UTI_DropRoot(uid_t uid, gid_t gid); + /* Fill buffer with random bytes */ extern void UTI_GetRandomBytes(void *buf, unsigned int len);