* Remove --enable-setuid, --with-nix-user and --with-nix-group.

Rather, setuid support is now always compiled in (at least on
  platforms that have the setresuid system call, e.g., Linux and
  FreeBSD), but it must enabled by chowning/chmodding the Nix
  binaries.
This commit is contained in:
Eelco Dolstra 2006-11-29 21:06:58 +00:00
parent c6a97e3b74
commit 71e867c5f5
4 changed files with 52 additions and 60 deletions

View file

@ -20,10 +20,11 @@ install-data-local: init-state
fi
if INIT_STATE
if SETUID_HACK
INIT_FLAGS = -g @NIX_GROUP@ -o @NIX_USER@
GROUP_WRITABLE = -m 775
endif
# For setuid operation, you can enable the following:
# INIT_FLAGS = -g @NIX_GROUP@ -o @NIX_USER@
# GROUP_WRITABLE = -m 775
init-state:
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/db
@ -40,6 +41,7 @@ init-state:
$(INSTALL) $(INIT_FLAGS) -m 1777 -d $(DESTDIR)$(prefix)/store
$(INSTALL) $(INIT_FLAGS) $(GROUP_WRITABLE) -d $(DESTDIR)$(localstatedir)/nix/manifests
# $(bindir)/nix-store --init
else
init-state:
endif

View file

@ -237,33 +237,13 @@ AM_CONDITIONAL(INIT_STATE, test "$init_state" = "yes")
# Setuid installations.
AC_ARG_ENABLE(setuid, AC_HELP_STRING([--enable-setuid],
[install Nix setuid]),
setuid_hack=$enableval, setuid_hack=no)
AM_CONDITIONAL(SETUID_HACK, test "$setuid_hack" = "yes")
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)
AC_SUBST(NIX_USER)
AC_DEFINE_UNQUOTED(NIX_USER, ["$NIX_USER"], [Nix user])
AC_ARG_WITH(nix-group, AC_HELP_STRING([--with-nix-group=USER],
[group for Nix setuid binaries]),
NIX_GROUP=$withval, NIX_GROUP=nix)
AC_SUBST(NIX_GROUP)
AC_DEFINE_UNQUOTED(NIX_GROUP, ["$NIX_GROUP"], [Nix group])
# This is needed if ATerm, Berkeley DB or bzip2 are static libraries,
# and the Nix libraries are dynamic.
if test "$(uname)" = "Darwin"; then

View file

@ -3,13 +3,4 @@ SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
EXTRA_DIST = aterm-helper.pl
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
#SETUID_PROGS = nix-store nix-instantiate nix-env

View file

@ -911,7 +911,7 @@ static gid_t savedGid, nixGid;
SwitchToOriginalUser::SwitchToOriginalUser()
{
#if SETUID_HACK && HAVE_SETRESUID
#if HAVE_SETRESUID
/* Temporarily switch the effective uid/gid back to the saved
uid/gid (which is the uid/gid of the user that executed the Nix
program; it's *not* the real uid/gid, since we changed that to
@ -928,7 +928,7 @@ SwitchToOriginalUser::SwitchToOriginalUser()
SwitchToOriginalUser::~SwitchToOriginalUser()
{
#if SETUID_HACK && HAVE_SETRESUID
#if HAVE_SETRESUID
/* Switch the effective uid/gid back to the Nix user. */
if (haveSwitched) {
if (setuid(nixUid) == -1)
@ -942,21 +942,43 @@ SwitchToOriginalUser::~SwitchToOriginalUser()
void switchToNixUser()
{
#if SETUID_HACK
fprintf(stderr, "real = %d/%d, effective = %d/%d\n",
getuid(), geteuid(), getgid(), getegid());
/* Note: we require setresuid for now since I don't want to think
to deeply about whether this works on systems that don't have
setresuid. It's already hard enough. */
#if HAVE_SETRESUID
/* Setuid Nix operation works as follows:
- The Nix binaries are owned by a Nix user and group, e.g.,
nix.nix, and must setuid and setgid, e.g.,
rwsrwsr-x nix.nix
- Users (say alice.users) are only allowed to run (most) Nix
operations if they are in the Nix group. If they aren't,
some read-only operations (like nix-env -qa) may still work.
- We run mostly under the Nix user/group, but we switch back to
the calling user/group for some work, like reading Nix
expressions.
*/
/* Don't do anything if this is not a setuid binary. */
if (getuid() == geteuid() && getgid() == getegid()) return;
/* Here we set the uid and gid to the Nix user and group,
respectively, IF the current (real) user is a member of the Nix
group. Otherwise we just drop all privileges. */
/* Lookup the Nix gid. */
struct group * gr = getgrnam(NIX_GROUP);
if (!gr) {
std::cerr << format("missing group `%1%'\n") % NIX_GROUP;
exit(1);
}
group. (The Nix group is the group of the current executable,
i.e., the current effective gid.) Otherwise we just drop all
privileges. */
nixGid = geteuid();
/* Get the supplementary group IDs for the current user. */
int maxGids = 512, nrGids;
@ -976,7 +998,7 @@ void switchToNixUser()
/* Check that the current user is a member of the Nix group. */
bool found = false;
for (int i = 0; i < nrGids; ++i)
if (gids[i] == gr->gr_gid) {
if (gids[i] == nixGid) {
found = true;
break;
}
@ -988,31 +1010,29 @@ void switchToNixUser()
return;
}
/* Save the uid/gid of the caller so the we can switch back to
that uid/gid for temporary work, like accessing files, in
SwitchToOriginaluser. */
savedUid = getuid();
savedGid = getgid();
/* 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. */
nixGid = gr->gr_gid;
/* Set the real and effective gids to nixGid. 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(nixGid) != 0 || getgid() != nixGid || getegid() != nixGid) {
std::cerr << format("unable to set gid to `%1%'\n") % NIX_GROUP;
std::cerr << format("unable to set gid to `%1%'\n") % nixGid;
exit(1);
}
/* Lookup the Nix uid. */
struct passwd * pw = getpwnam(NIX_USER);
if (!pw) {
std::cerr << format("missing user `%1%'\n") % NIX_USER;
exit(1);
}
/* The Nix uid is the effective uid of the owner of the current
executable, i.e., the current effective uid. */
nixUid = geteuid();
/* This will drop all root privileges, setting the real, effective
and saved uids to pw->pw_uid. Also make very sure that this
succeeded.*/
nixUid = pw->pw_uid;
if (_setuid(nixUid) != 0 || getuid() != nixUid || geteuid() != nixUid) {
std::cerr << format("unable to set uid to `%1%'\n") % NIX_USER;
std::cerr << format("unable to set uid to `%1%'\n") % nixUid;
exit(1);
}
@ -1022,7 +1042,6 @@ void switchToNixUser()
*/
haveSwitched = true;
#endif
}