From bdf63b2c329f12b4cdfcc04122f4547aad6bfa35 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 4 Apr 2013 11:32:51 -0400 Subject: Further restrict become_user drop of privileges. We never need to regain root after we call become_user() so tighten up even further our privilege drop. Add a setgroups() call to remove all secondary groups root may have been given for whateve reason. Then use the setres[ug]id function to also drop the saved uid/gid so the process cannot regain back root id. Capabilities are also implicitly dropped here, no more CAP_SETUID so this is a Point of No Return, once changed to non-root the process can't get back. Remove redefinition of sys/types.h and unistd.h, they are already defined in util.h and they need to be included after _GNU_SOURCE/_BSD_SOURCE is defined or the prototypes for setres[ug]id will not be found. Add grp.h after util.h for the same reason. --- src/providers/krb5/krb5_become_user.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'src/providers/krb5/krb5_become_user.c') diff --git a/src/providers/krb5/krb5_become_user.c b/src/providers/krb5/krb5_become_user.c index 082d1415..70bc5630 100644 --- a/src/providers/krb5/krb5_become_user.c +++ b/src/providers/krb5/krb5_become_user.c @@ -22,45 +22,48 @@ along with this program. If not, see . */ -#include -#include - #include "util/util.h" +#include errno_t become_user(uid_t uid, gid_t gid) { + uid_t cuid; int ret; DEBUG(SSSDBG_FUNC_DATA, ("Trying to become user [%d][%d].\n", uid, gid)); - ret = setgid(gid); - if (ret == -1) { - ret = errno; - DEBUG(SSSDBG_CRIT_FAILURE, - ("setgid failed [%d][%s].\n", ret, strerror(ret))); - return ret; + + /* skip call if we already are the requested user */ + cuid = geteuid(); + if (uid == cuid) { + DEBUG(SSSDBG_FUNC_DATA, ("Already user [%d].\n", uid)); + return EOK; } - ret = setuid(uid); + /* drop supplmentary groups first */ + ret = setgroups(0, NULL); if (ret == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, - ("setuid failed [%d][%s].\n", ret, strerror(ret))); + ("setgroups failed [%d][%s].\n", ret, strerror(ret))); return ret; } - ret = setegid(gid); + /* change gid so that root cannot be regained (changes saved gid too) */ + ret = setresgid(gid, gid, gid); if (ret == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, - ("setegid failed [%d][%s].\n", ret, strerror(ret))); + ("setresgid failed [%d][%s].\n", ret, strerror(ret))); return ret; } - ret = seteuid(uid); + /* change uid so that root cannot be regained (changes saved uid too) */ + /* this call also takes care of dropping CAP_SETUID, so this is a PNR */ + ret = setresuid(uid, uid, uid); if (ret == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, - ("seteuid failed [%d][%s].\n", ret, strerror(ret))); + ("setresuid failed [%d][%s].\n", ret, strerror(ret))); return ret; } -- cgit