summary refs log tree commit diff
path: root/nix
diff options
context:
space:
mode:
Diffstat (limited to 'nix')
-rw-r--r--nix/libstore/build.cc34
-rw-r--r--nix/libstore/globals.hh6
-rw-r--r--nix/libstore/optimise-store.cc4
-rw-r--r--nix/local.mk24
-rw-r--r--nix/nix-daemon/nix-daemon.cc19
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;