diff options
Diffstat (limited to 'nix')
-rw-r--r-- | nix/libstore/build.cc | 34 | ||||
-rw-r--r-- | nix/libstore/globals.hh | 6 | ||||
-rw-r--r-- | nix/libstore/optimise-store.cc | 4 | ||||
-rw-r--r-- | nix/local.mk | 24 | ||||
-rw-r--r-- | nix/nix-daemon/nix-daemon.cc | 19 |
5 files changed, 67 insertions, 20 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 889ee3d2bd..38048ceebc 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1680,7 +1680,11 @@ void DerivationGoal::startBuilder() % drv.platform % settings.thisSystem % drvPath); } - useChroot = settings.useChroot; + /* Note: built-in builders are *not* running in a chroot environment so + that we can easily implement them in Guile without having it as a + derivation input (they are running under a separate build user, + though). */ + useChroot = settings.useChroot && !isBuiltin(drv); /* Construct the environment passed to the builder. */ env.clear(); @@ -2048,12 +2052,7 @@ void DerivationGoal::runChild() commonChildInit(builderOut); #if CHROOT_ENABLED - /* Note: built-in builders are *not* running in a chroot environment - so that we can easily implement them in Guile without having it as - a derivation input (they are running under a separate build user, - though). */ - - if (useChroot && !isBuiltin(drv)) { + if (useChroot) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); if (fd == -1) throw SysError("cannot open IP socket"); @@ -2631,6 +2630,21 @@ void DerivationGoal::closeLogFile() } +static void _chown(const Path & path, uid_t uid, gid_t gid) +{ + checkInterrupt(); + + if (lchown(path.c_str(), uid, gid) == -1) { + throw SysError(format("change owner and group of `%1%'") % path); + } + struct stat st = lstat(path); + if (S_ISDIR(st.st_mode)) { + for (auto & i : readDirectory(path)) + _chown(path + "/" + i.name, uid, gid); + } +} + + void DerivationGoal::deleteTmpDir(bool force) { if (tmpDir != "") { @@ -2639,6 +2653,12 @@ void DerivationGoal::deleteTmpDir(bool force) format("note: keeping build directory `%2%'") % drvPath % tmpDir); chmod(tmpDir.c_str(), 0755); + // Change the ownership if clientUid is set. Never change the + // ownership or the group to "root" for security reasons. + if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { + _chown(tmpDir, settings.clientUid, + settings.clientGid != 0 ? settings.clientGid : -1); + } } else deletePath(tmpDir); diff --git a/nix/libstore/globals.hh b/nix/libstore/globals.hh index 8c07e360f2..7beb1a55ca 100644 --- a/nix/libstore/globals.hh +++ b/nix/libstore/globals.hh @@ -70,6 +70,12 @@ struct Settings { subgoal of the same goal) fails. */ bool keepGoing; + /* User and groud id of the client issuing the build request. Used to set + the owner and group of the kept temporary directories of failed + builds. */ + uid_t clientUid; + gid_t clientGid; + /* Whether, if we cannot realise the known closure corresponding to a derivation, we should try to normalise the derivation instead. */ diff --git a/nix/libstore/optimise-store.cc b/nix/libstore/optimise-store.cc index 565c62ca83..9bed371c70 100644 --- a/nix/libstore/optimise-store.cc +++ b/nix/libstore/optimise-store.cc @@ -5,6 +5,7 @@ #include "globals.hh" #include <cstdlib> +#include <cstring> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -159,7 +160,8 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa /* On ext4, that probably means the directory index is full. When that happens, it's fine to ignore it: we just effectively disable deduplication of this file. */ - printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %m") % linkPath % path); + printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %3%") + % linkPath % path % strerror(ENOSPC)); return; default: diff --git a/nix/local.mk b/nix/local.mk index 79667ed49e..eb70d266fb 100644 --- a/nix/local.mk +++ b/nix/local.mk @@ -22,7 +22,7 @@ # BUILT_SOURCES += %D%/libstore/schema.sql.hh -CLEANFILES += $(BUILT_SOURCES) etc/guix-daemon.service etc/guix-daemon.conf +CLEANFILES += $(BUILT_SOURCES) noinst_LIBRARIES = libformat.a libutil.a libstore.a @@ -189,9 +189,9 @@ nodist_systemdservice_DATA = etc/guix-daemon.service etc/guix-publish.service etc/guix-%.service: etc/guix-%.service.in \ $(top_builddir)/config.status - $(AM_V_GEN)$(MKDIR_P) "`dirname $@`"; \ - $(SED) -e 's|@''bindir''@|$(bindir)|' < \ - "$(srcdir)/$<" > "$@.tmp"; \ + $(AM_V_GEN)$(MKDIR_P) "`dirname $@`"; \ + $(SED) -e 's|@''bindir''@|$(bindir)|' < \ + "$<" > "$@.tmp"; \ mv "$@.tmp" "$@" # The '.conf' jobs for Upstart. @@ -200,17 +200,23 @@ nodist_upstartjob_DATA = etc/guix-daemon.conf etc/guix-publish.conf etc/guix-%.conf: etc/guix-%.conf.in \ $(top_builddir)/config.status - $(AM_V_GEN)$(MKDIR_P) "`dirname $@`"; \ - $(SED) -e 's|@''bindir''@|$(bindir)|' < \ - "$(srcdir)/$<" > "$@.tmp"; \ + $(AM_V_GEN)$(MKDIR_P) "`dirname $@`"; \ + $(SED) -e 's|@''bindir''@|$(bindir)|' < \ + "$<" > "$@.tmp"; \ mv "$@.tmp" "$@" +CLEANFILES += \ + $(nodist_systemdservice_DATA) \ + $(nodist_upstartjob_DATA) + EXTRA_DIST += \ %D%/libstore/schema.sql \ %D%/AUTHORS \ %D%/COPYING \ - etc/guix-daemon.service.in \ - etc/guix-daemon.conf.in + etc/guix-daemon.service.in \ + etc/guix-daemon.conf.in \ + etc/guix-publish.service.in \ + etc/guix-publish.conf.in if CAN_RUN_TESTS diff --git a/nix/nix-daemon/nix-daemon.cc b/nix/nix-daemon/nix-daemon.cc index 9b29b3e91d..47b67d5863 100644 --- a/nix/nix-daemon/nix-daemon.cc +++ b/nix/nix-daemon/nix-daemon.cc @@ -203,11 +203,11 @@ static void stopWork(bool success = true, const string & msg = "", unsigned int } -struct TunnelSink : Sink +struct TunnelSink : BufferedSink { Sink & to; - TunnelSink(Sink & to) : to(to) { } - virtual void operator () (const unsigned char * data, size_t len) + TunnelSink(Sink & to) : BufferedSink(64 * 1024), to(to) { } + virtual void write(const unsigned char * data, size_t len) { writeInt(STDERR_WRITE, to); writeString(data, len, to); @@ -433,6 +433,7 @@ static void performOp(bool trusted, unsigned int clientVersion, startWork(); TunnelSink sink(to); store->exportPath(path, sign, sink); + sink.flush(); stopWork(); writeInt(1, to); break; @@ -959,6 +960,18 @@ static void daemonLoop() strncpy(argvSaved[1], processName.c_str(), strlen(argvSaved[1])); } +#if defined(SO_PEERCRED) + /* Store the client's user and group for this connection. This + has to be done in the forked process since it is per + connection. */ + settings.clientUid = cred.uid; + settings.clientGid = cred.gid; +#else + /* Setting these to -1 means: do not change */ + settings.clientUid = (uid_t) -1; + settings.clientGid = (gid_t) -1; +#endif + /* Handle the connection. */ from.fd = remote; to.fd = remote; |