Subject: [PATCH v8 01/16] daemon: Use ‘close_range’ where available.

From: Ludovic Courtès <[email-masked]>
Date: Sun, 23 Mar 2025 15:24:54 +0100

* nix/libutil/util.cc (closeMostFDs) [HAVE_CLOSE_RANGE]: Use
‘close_range’ when ‘exceptions’ is empty.
* config-daemon.ac: Check for <linux/close_range.h> and the
‘close_range’ symbol.

Change-Id: I12fa3bde58b003fcce5ea5a1fee1dcf9a92c0359
---
 config-daemon.ac    |  5 +++--
 nix/libutil/util.cc | 23 +++++++++++++++++------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/config-daemon.ac b/config-daemon.ac
index 6731c68bc3..4e949bc88a 100644
--- a/config-daemon.ac
+++ b/config-daemon.ac
@@ -78,7 +78,8 @@ if test "x$guix_build_daemon" = "xyes"; then
 
   dnl Chroot support.
   AC_CHECK_FUNCS([chroot unshare])
-  AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h])
+  AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \
+    linux/close_range.h])
 
   if test "x$ac_cv_func_chroot" != "xyes"; then
     AC_MSG_ERROR(['chroot' function missing, bailing out])
@@ -95,7 +96,7 @@ if test "x$guix_build_daemon" = "xyes"; then
   dnl strsignal: for error reporting.
   dnl statx: fine-grain 'stat' call, new in glibc 2.28.
   AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \
-     statvfs nanosleep strsignal statx])
+     statvfs nanosleep strsignal statx close_range])
 
   dnl Check for <locale>.
   AC_LANG_PUSH(C++)
diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc
index 3206dea11b..eb2d16e1cc 100644
--- a/nix/libutil/util.cc
+++ b/nix/libutil/util.cc
@@ -23,6 +23,10 @@
 #include <sys/prctl.h>
 #endif
 
+#ifdef HAVE_LINUX_CLOSE_RANGE_H
+# include <linux/close_range.h>
+#endif
+
 
 extern char * * environ;
 
@@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, const Strings & args)
 
 void closeMostFDs(const set<int> & exceptions)
 {
-    int maxFD = 0;
-    maxFD = sysconf(_SC_OPEN_MAX);
-    for (int fd = 0; fd < maxFD; ++fd)
-        if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO
-            && exceptions.find(fd) == exceptions.end())
-            close(fd); /* ignore result */
+#ifdef HAVE_CLOSE_RANGE
+    if (exceptions.empty())
+	 close_range(3, ~0U, 0);
+    else
+#endif
+    {
+	 int maxFD = 0;
+	 maxFD = sysconf(_SC_OPEN_MAX);
+	 for (int fd = 0; fd < maxFD; ++fd)
+	      if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO
+		  && exceptions.find(fd) == exceptions.end())
+		   close(fd); /* ignore result */
+    }
 }

-- 
2.48.1