[bug#75810,v5,01/14] daemon: Use ‘close_range’ where available.

Message ID 8ae666d03ea7b1d96fbf3c3ff928b920f98df06a.1741973869.git.ludo@gnu.org
State New
Headers
Series Rootless guix-daemon |

Commit Message

Ludovic Courtès March 14, 2025, 5:47 p.m. UTC
  * 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(-)
  

Patch

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 */
+    }
 }