diff options
author | Sebastian Krahmer <krahmer@suse.com> | 2015-09-16 12:38:01 +0200 |
---|---|---|
committer | Jiri Pirko <jiri@resnulli.us> | 2015-09-16 14:38:28 +0200 |
commit | a6e7faccf949c1650c4f3da765459a113c454b19 (patch) | |
tree | cb964372907eea438249178c4ca2fe8b5186043c | |
parent | 0b770e3bf238f507f4c29eab0e352bb4c8a8ef01 (diff) | |
download | libteam-a6e7faccf949c1650c4f3da765459a113c454b19.tar.gz |
drop privileges to usr/grp specified at build time
Signed-off-by: Sebastian Krahmer <krahmer@suse.com>
Signed-off-by: Pawel Wieczorkiewicz <pwieczorkiewicz@suse.de>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
-rw-r--r-- | configure.ac | 25 | ||||
-rw-r--r-- | teamd/teamd.c | 100 |
2 files changed, 121 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index 302a11a..f459f4e 100644 --- a/configure.ac +++ b/configure.ac @@ -77,6 +77,31 @@ AS_IF([test "x$enable_debug" = "xyes"], [ AC_DEFINE(ENABLE_DEBUG, [1], [Debug messages.]) ]) +user=root +AC_ARG_WITH([user], + [AS_HELP_STRING([--with-user@<:@=username@:>@], [Set default daemon user @<:@default=root@:>@])], + [case "$withval" in + yes|no|"") ;; + *) user="$withval" ;; + esac] +) +AC_DEFINE_UNQUOTED(TEAMD_USER, "${user}", [TEAMD USER.]) + +group=root +AC_ARG_WITH([group], + [AS_HELP_STRING([--with-group@<:@=groupname@:>@], [Specify the system group @<:@default=root@:>@])], + [case "$withval" in + yes|no|"") ;; + *) group="$withval" ;; + esac] +) +AC_DEFINE_UNQUOTED(TEAMD_GROUP, "${group}", [TEAMD GROUP.]) + +AM_CONDITIONAL([LIBCAP], [test "x$user" != "xroot" -o "x$group" != "xroot"]) +AM_COND_IF([LIBCAP], + [AC_CHECK_LIB([cap], [cap_init],, + AC_MSG_ERROR([*** Non-root daemon support requested but libcap-devel library not found]))]) + have_dbus=no AC_ARG_ENABLE([dbus], AS_HELP_STRING([--disable-dbus], [disable D-Bus API @<:@default=enabled@:>@])) diff --git a/teamd/teamd.c b/teamd/teamd.c index cdf1fc3..391b981 100644 --- a/teamd/teamd.c +++ b/teamd/teamd.c @@ -1447,10 +1447,8 @@ static int teamd_start(struct teamd_context *ctx, enum teamd_exit_code *p_ret) pid_t pid; int err = 0; - if (getuid() != 0) { - teamd_log_err("This program is intended to be run as root."); - return -EPERM; - } + if (getuid() == 0) + teamd_log_warn("This program is not intended to be run as root."); if (daemon_reset_sigs(-1) < 0) { teamd_log_err("Failed to reset all signal handlers."); @@ -1666,6 +1664,96 @@ static void teamd_context_fini(struct teamd_context *ctx) free(ctx); } + +#ifdef HAVE_LIBCAP +#include <sys/prctl.h> +#include <sys/capability.h> +#include <sys/types.h> +#include <pwd.h> +#include <grp.h> + +#ifndef TEAMD_USER +#define TEAMD_USER "root" +#endif +#ifndef TEAMD_GROUP +#define TEAMD_GROUP "root" +#endif + +static int teamd_drop_privileges() +{ + cap_value_t cv[] = {CAP_NET_ADMIN, CAP_NET_BIND_SERVICE}; + cap_t my_caps; + struct passwd *pw = NULL; + struct group *grpent = NULL; + + if ((pw = getpwnam(TEAMD_USER)) == NULL) { + fprintf(stderr, "Error reading user %s entry (%m)\n", TEAMD_USER); + goto error; + } + + if (pw->pw_uid == 0) + return 0; + + if ((grpent = getgrnam(TEAMD_GROUP)) == NULL) { + fprintf(stderr, "Error reading group %s entry (%m)\n", TEAMD_GROUP); + goto error; + } + + if (pw->pw_gid != grpent->gr_gid) { + fprintf(stderr, "%s GID (%u) does not match %s GID (%u)\n", + TEAMD_USER, pw->pw_gid, TEAMD_GROUP, grpent->gr_gid); + goto error; + } + + if (chown(TEAMD_RUN_DIR, pw->pw_uid, pw->pw_gid) < 0) { + fprintf(stderr, "Unable to change ownership of %s to %s/%s (%m)\n", + TEAMD_RUN_DIR, TEAMD_USER, TEAMD_GROUP); + goto error; + } + + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) + goto error; + + if (setgid(pw->pw_gid) < 0) { + fprintf(stderr, "Unable to set process GID to %u (%m)\n", pw->pw_gid); + goto error; + } + + if (initgroups(TEAMD_USER, pw->pw_gid) < 0) { + fprintf(stderr, "Unable to initialize the group access list for %s user with GID %u (%m)\n", + TEAMD_USER, pw->pw_gid); + goto error; + } + if (setuid(pw->pw_uid) < 0) { + fprintf(stderr, "Unable to set UID to %u (%m)\n", pw->pw_uid); + goto error; + } + + if ((my_caps = cap_init()) == NULL) + goto error; + if (cap_set_flag(my_caps, CAP_EFFECTIVE, 2, cv, CAP_SET) < 0) + goto error; + if (cap_set_flag(my_caps, CAP_PERMITTED, 2, cv, CAP_SET) < 0) + goto error; + if (cap_set_proc(my_caps) < 0) + goto error; + cap_free(my_caps); + + return 0; +error: + fprintf(stderr, "Failed to drop privileges\n"); + return -EINVAL; +} + +#else + +static int teamd_drop_privileges() +{ + return 0; +} + +#endif + int main(int argc, char **argv) { enum teamd_exit_code ret = TEAMD_EXIT_FAILURE; @@ -1676,6 +1764,10 @@ int main(int argc, char **argv) if (err) return ret; + err = teamd_drop_privileges(); + if (err) + return ret; + err = teamd_context_init(&ctx); if (err) { fprintf(stderr, "Failed to init daemon context\n"); |