about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/build.cc63
-rw-r--r--src/nix-setuid-helper/main.cc37
2 files changed, 69 insertions, 31 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 7ae0dd4ec459..03a708b7477c 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -351,6 +351,8 @@ public:
     void acquire();
     void release();
 
+    void kill();
+
     string getUser() { return user; }
     uid_t getUID() { return uid; }
     uid_t getGID() { return gid; }
@@ -452,29 +454,8 @@ void UserLock::release()
 }
 
 
-bool amPrivileged()
-{
-    return geteuid() == 0;
-}
-
-
-bool haveBuildUsers()
-{
-    return querySetting("build-users-group", "") != "";
-}
-
-
-static void killUserWrapped(uid_t uid)
-{
-    if (amPrivileged())
-        killUser(uid);
-    else
-        /* !!! TODO */
-        printMsg(lvlError, "must kill");
-}
-
-
-void getOwnership(const Path & path)
+static void runSetuidHelper(const string & command,
+    const string & arg)
 {
     string program = nixLibexecDir + "/nix-setuid-helper";
             
@@ -491,8 +472,8 @@ void getOwnership(const Path & path)
             std::vector<const char *> args; /* careful with c_str()!
                                                */
             args.push_back(program.c_str());
-            args.push_back("get-ownership");
-            args.push_back(path.c_str());
+            args.push_back(command.c_str());
+            args.push_back(arg.c_str());
             args.push_back(0);
 
             execve(program.c_str(), (char * *) &args[0], 0);
@@ -514,6 +495,34 @@ void getOwnership(const Path & path)
 }
 
 
+void UserLock::kill()
+{
+    assert(enabled());
+    if (amPrivileged())
+        killUser(uid);
+    else
+        runSetuidHelper("kill", user);
+}
+
+
+bool amPrivileged()
+{
+    return geteuid() == 0;
+}
+
+
+bool haveBuildUsers()
+{
+    return querySetting("build-users-group", "") != "";
+}
+
+
+void getOwnership(const Path & path)
+{
+    runSetuidHelper("get-ownership", path);
+}
+
+
 static void deletePathWrapped(const Path & path)
 {
     /* When using build users and we're not root, we may not have
@@ -850,7 +859,7 @@ void DerivationGoal::buildDone()
        open and modifies them after they have been chown'ed to
        root. */
     if (buildUser.enabled())
-        killUserWrapped(buildUser.getUID());
+        buildUser.kill();
 
     /* Close the read side of the logger pipe. */
     logPipe.readSide.close();
@@ -1332,7 +1341,7 @@ void DerivationGoal::startBuilder()
 
         /* Make sure that no other processes are executing under this
            uid. */
-        killUserWrapped(buildUser.getUID());
+        buildUser.kill();
         
         /* Change ownership of the temporary build directory, if we're
            root.  If we're not root, then the setuid helper will do it
diff --git a/src/nix-setuid-helper/main.cc b/src/nix-setuid-helper/main.cc
index e9ffcfd02323..dc0b2cd6cbd5 100644
--- a/src/nix-setuid-helper/main.cc
+++ b/src/nix-setuid-helper/main.cc
@@ -66,6 +66,15 @@ static uid_t nameToUid(const string & userName)
 }
 
 
+static void checkIfBuildUser(const StringSet & buildUsers,
+    const string & userName)
+{
+    if (buildUsers.find(userName) == buildUsers.end())
+        throw Error(format("user `%1%' is not a member of the build users group")
+            % userName);
+}
+
+
 /* Run `program' under user account `targetUser'.  `targetUser' should
    be a member of `buildUsersGroup'.  The ownership of the current
    directory is changed from the Nix user (uidNix) to the target
@@ -80,10 +89,9 @@ static void runBuilder(uid_t uidNix, gid_t gidBuildUsers,
     if (uidTargetUser == 0)
         throw Error("won't setuid to root");
 
-    /* Verify that the target user is a member of that group. */
-    if (buildUsers.find(targetUser) == buildUsers.end())
-        throw Error(format("user `%1%' is not a member of the build users group")
-            % targetUser);
+    /* Verify that the target user is a member of the build users
+       group. */
+    checkIfBuildUser(buildUsers, targetUser);
     
     /* Chown the current directory, *if* it is owned by the Nix
        account.  The idea is that the current directory is the
@@ -118,6 +126,21 @@ static void runBuilder(uid_t uidNix, gid_t gidBuildUsers,
 }
 
 
+void killBuildUser(gid_t gidBuildUsers,
+    const StringSet & buildUsers, const string & userName)
+{
+    uid_t uid = nameToUid(userName);
+    
+    /* Verify that the user whose processes we are to kill is a member
+       of the build users group. */
+    checkIfBuildUser(buildUsers, userName);
+
+    assert(uid != 0);
+
+    killUser(uid);
+}
+
+
 #ifndef NIX_SETUID_CONFIG_FILE
 #define NIX_SETUID_CONFIG_FILE "/etc/nix-setuid.conf"
 #endif
@@ -204,6 +227,12 @@ static void run(int argc, char * * argv)
         secureChown(-1, gidBuildUsers, uidNix, gidBuildUsers, argv[2]);
     }
 
+    else if (command == "kill") {
+        /* Syntax: nix-setuid-helper kill <username> */
+        if (argc != 3) throw Error("missing user name");
+        killBuildUser(gidBuildUsers, buildUsers, argv[2]);
+    }
+
     else throw Error ("invalid command");
 }