diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2004-08-20T15·22+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2004-08-20T15·22+0000 |
commit | e77fbe0fa2f7c2cfaee734dba049f0d8dd3dae15 (patch) | |
tree | 614c425a989b33c357387c04155e613db47b7f4a | |
parent | 2d35116c13e0c11210cb712f9ce6e8a38058f350 (diff) |
* On systems that have the setresuid() and setresgid() system calls to
set the real uid and gid to the effective uid and gid, the Nix binaries can be installed as owned by the Nix user and group instead of root, so no root involvement of any kind is necessary. Linux and FreeBSD have these functions.
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/libmain/shared.cc | 29 |
3 files changed, 32 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac index 5dab9847ad8f..2ba8e92384a9 100644 --- a/configure.ac +++ b/configure.ac @@ -151,6 +151,12 @@ if test "$setuid_hack" = "yes"; then AC_DEFINE(SETUID_HACK, 1, [whether to install Nix setuid]) fi +AC_CHECK_FUNC(setresuid, [HAVE_SETRESUID=1], [HAVE_SETRESUID=]) +AM_CONDITIONAL(HAVE_SETRESUID, test "$HAVE_SETRESUID" = "1") +if test "$HAVE_SETRESUID" = "1"; then + AC_DEFINE(HAVE_SETRESUID, 1, [whether we have setresuid()]) +fi + AC_ARG_WITH(nix-user, AC_HELP_STRING([--with-nix-user=USER], [user for Nix setuid binaries]), NIX_USER=$withval, NIX_USER=nix) diff --git a/src/Makefile.am b/src/Makefile.am index 6c3e5ee209ae..5637382172a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,5 +4,10 @@ SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \ SETUID_PROGS = nix-store nix-instantiate nix-env install-exec-hook: if SETUID_HACK +if HAVE_SETRESUID + cd $(DESTDIR)$(bindir) && chown @NIX_USER@ $(SETUID_PROGS) \ + && chgrp @NIX_GROUP@ $(SETUID_PROGS) && chmod ug+s $(SETUID_PROGS) +else cd $(DESTDIR)$(bindir) && chown root $(SETUID_PROGS) && chmod u+s $(SETUID_PROGS) endif +endif diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 068c126596e7..df56a77cf832 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -163,6 +163,16 @@ static void initAndRun(int argc, char * * argv) } +#if HAVE_SETRESUID +#define _setuid(uid) setresuid(uid, uid, uid) +#define _setgid(gid) setresgid(gid, gid, gid) +#else +/* Only works properly when run by root. */ +#define _setuid(uid) setuid(uid) +#define _setgid(gid) setgid(gid) +#endif + + void switchToNixUser() { #if SETUID_HACK @@ -186,6 +196,13 @@ void switchToNixUser() exit(1); } + /* !!! Apparently it is unspecified whether getgroups() includes + the effective gid. In that case the following test is always + true *if* the program is installed setgid (which we do when we + have setresuid()). On Linux this doesn't appear to be the + case, but we should switch to the real gid before doing this + test, and then switch back to the saved gid. */ + /* Check that the current user is a member of the Nix group. */ bool found = false; for (int i = 0; i < nrGids; ++i) @@ -196,15 +213,15 @@ void switchToNixUser() if (!found) { /* Not in the Nix group - drop all root/Nix privileges. */ - setgid(getgid()); - setuid(getuid()); + _setgid(getgid()); + _setuid(getuid()); return; } /* Set the real, effective and saved gids to gr->gr_gid. Also make very sure that this succeeded. We switch the gid first because we cannot do it after we have dropped root uid. */ - if (setgid(gr->gr_gid) != 0 || + if (_setgid(gr->gr_gid) != 0 || getgid() != gr->gr_gid || getegid() != gr->gr_gid) { @@ -222,7 +239,7 @@ void switchToNixUser() /* This will drop all root privileges, setting the real, effective and saved uids to pw->pw_uid. Also make very sure that this succeeded.*/ - if (setuid(pw->pw_uid) != 0 || + if (_setuid(pw->pw_uid) != 0 || getuid() != pw->pw_uid || geteuid() != pw->pw_uid) { @@ -240,11 +257,7 @@ int main(int argc, char * * argv) { /* If we are setuid root, we have to get rid of the excess privileges ASAP. */ - printMsg(lvlError, format("%1% %2% %3% %4%\n") % getuid() % geteuid() - % getgid() % getegid()); switchToNixUser(); - printMsg(lvlError, format("%1% %2% %3% %4%\n") % getuid() % geteuid() - % getgid() % getegid()); /* ATerm setup. */ ATerm bottomOfStack; |