Switch the user/group ID to the specified user in order to drop the root privileges, but keep the capability to adjust the clock and bind to a privileged port using the libcap library.
Signed-off-by: Miroslav Lichvar <[email protected]> --- incdefs.sh | 11 ++++++++- makefile | 4 ++++ util.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 9 ++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/incdefs.sh b/incdefs.sh index 19e620e..9889059 100755 --- a/incdefs.sh +++ b/incdefs.sh @@ -19,7 +19,8 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -# Look for functional prototypes in the C library. +# Look for functional prototypes in the C library and development files +# needed for optional features. # user_flags() { @@ -50,6 +51,14 @@ user_flags() fi done done + + # Look for libcap header. + for d in $dirs; do + if test -a $d/sys/capability.h; then + printf " -DHAVE_LIBCAP" + break + fi + done } # diff --git a/makefile b/makefile index 693e75d..ee4793f 100644 --- a/makefile +++ b/makefile @@ -38,6 +38,10 @@ incdefs := $(shell $(srcdir)/incdefs.sh) version := $(shell $(srcdir)/version.sh $(srcdir)) VPATH = $(srcdir) +ifneq (,$(findstring -DHAVE_LIBCAP,$(incdefs))) + LDLIBS += -lcap +endif + prefix = /usr/local sbindir = $(prefix)/sbin mandir = $(prefix)/man diff --git a/util.c b/util.c index 73fb37e..85c5e7b 100644 --- a/util.c +++ b/util.c @@ -24,6 +24,15 @@ #include <stdlib.h> #include <string.h> +#ifdef HAVE_LIBCAP +#include <grp.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/prctl.h> +#include <sys/capability.h> +#include <unistd.h> +#endif + #include "address.h" #include "print.h" #include "sk.h" @@ -651,3 +660,61 @@ int rate_limited(int interval, time_t *last) return 0; } + +int drop_root_privileges(const char *user) +{ +#ifdef HAVE_LIBCAP + struct passwd *pw; + cap_t cap; +#endif + + if (user[0] == '\0') + return 0; + +#ifdef HAVE_LIBCAP + pw = getpwnam(user); + if (!pw) { + pr_err("failed to get user/group ID of %s", user); + return -1; + } + + if (prctl(PR_SET_KEEPCAPS, 1)) { + pr_err("failed to set KEEPCAPS flag"); + return -1; + } + + if (setgroups(0, NULL)) { + pr_err("failed to drop supplementary groups"); + return -1; + } + + if (setgid(pw->pw_gid)) { + pr_err("failed to set group ID"); + return -1; + } + + if (setuid(pw->pw_uid)) { + pr_err("failed to set user ID"); + return -1; + } + + cap = cap_from_text("cap_sys_time,cap_net_bind_service=ep"); + if (!cap) { + pr_err("failed to initialize capabilities"); + return -1; + } + + if (cap_set_proc(cap)) { + pr_err("failed to set process capabilities"); + cap_free(cap); + return -1; + } + + cap_free(cap); + + return 0; +#else + pr_err("cannot drop root privileges without libcap"); + return -1; +#endif +} diff --git a/util.h b/util.h index 1ab1b3f..79a4f7f 100644 --- a/util.h +++ b/util.h @@ -424,4 +424,13 @@ void parray_extend(void ***a, ...); */ int rate_limited(int interval, time_t *last); +/** + * Change the user/group ID in order to drop the root privileges. Keep only the + * capability to set/adjust the clock and bind to a privileged port. + * + * @param user Name of the user. + * @return 0 on success, -1 on error. + */ +int drop_root_privileges(const char *user); + #endif -- 2.17.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Linuxptp-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
