aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Krahmer <krahmer@suse.com>2015-09-16 12:38:01 +0200
committerJiri Pirko <jiri@resnulli.us>2015-09-16 14:38:28 +0200
commita6e7faccf949c1650c4f3da765459a113c454b19 (patch)
treecb964372907eea438249178c4ca2fe8b5186043c
parent0b770e3bf238f507f4c29eab0e352bb4c8a8ef01 (diff)
downloadlibteam-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.ac25
-rw-r--r--teamd/teamd.c100
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");