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 /src | |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/libmain/shared.cc | 29 |
2 files changed, 26 insertions, 8 deletions
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; |