Subject: [PATCH] daemon: Use the actual overflow UID and GID in /etc/passwd.

From: Ludovic Courtès <[email-masked]>
Date: Mon, 5 May 2025 10:59:34 +0200

Partly fixes <https://issues.guix.gnu.org/77862>.

* nix/libstore/build.cc (fileContent, overflowUID, overflowGID): New
functions.
(DerivationGoal::startBuilder): Use them to populate /etc/passwd when
‘buildUser.enabled()’ is false.

Reported-by: keinflue <[email-masked]>
Change-Id: I695c697629c739d096933274c1c8a70d08468d4a
---
 nix/libstore/build.cc | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index a1f39d9a8b..773dcf1a01 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -13,6 +13,7 @@
 #include <map>
 #include <sstream>
 #include <algorithm>
+#include <iostream>
 
 #include <limits.h>
 #include <time.h>
@@ -1646,6 +1647,36 @@ static void initializeUserNamespace(pid_t child,
 	      (format("%d %d 1") % guestGID % hostGID).str());
 }
 
+/* Return the content of FILE as an integer, or DFLT if FILE could not be
+   opened or parsed.  */
+static unsigned int fileContent(const std::string &file, int dflt)
+{
+    AutoCloseFD fd;
+    fd = open(file.c_str(), O_RDONLY|O_CLOEXEC);
+    if (fd == -1)
+	return dflt;
+    else {
+	char buf[64];
+	ssize_t count = read (fd, buf, sizeof buf);
+	if (count <= 0) return dflt;
+
+	unsigned int result = dflt;
+	std::string str = buf;
+	try { result = std::stoi(str); } catch (...) {};
+	return result;
+    }
+}
+
+static uid_t overflowUID()
+{
+    return fileContent("/proc/sys/kernel/overflowuid", 65534);
+}
+
+static gid_t overflowGID()
+{
+    return fileContent("/proc/sys/kernel/overflowgid", 65534);
+}
+
 void DerivationGoal::startBuilder()
 {
     auto f = format(
@@ -1846,9 +1877,11 @@ void DerivationGoal::startBuilder()
         writeFile(chrootRootDir + "/etc/passwd",
             (format(
                 "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n"
-                "nobody:x:65534:65534:Nobody:/:/noshell\n")
+                "nobody:x:%3%:%4%:Nobody:/:/noshell\n")
                 % (buildUser.enabled() ? buildUser.getUID() : guestUID)
-                % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str());
+                % (buildUser.enabled() ? buildUser.getGID() : guestGID)
+	        % (buildUser.enabled() ? 65534 : overflowUID())
+	        % (buildUser.enabled() ? 65534 : overflowGID())).str());
 
         /* Declare the build user's group so that programs get a consistent
            view of the system (e.g., "id -gn"). */

base-commit: c2c4bc8758616ebc0148e1bce9311a80658ace88
-- 
2.49.0