summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2025-10-20 16:11:37 +0000
committerJulian Andres Klode <jak@debian.org>2025-10-20 16:11:37 +0000
commit683214eed4aced71f94f12a0cc70509bdb473c82 (patch)
treecd51616b1f6b42c7d3e53a39f1400e292b6ea476 /apt-pkg
parent86be82f9877e29cb27de98c8680026df28e99af4 (diff)
parent6aca3716f051b5b6bff63d51fff68b9c7ebc7474 (diff)
Merge branch 'close-range' into 'main'
ExecFork: Use close_range() if available See merge request apt-team/apt!524
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/contrib/fileutl.cc34
1 files changed, 32 insertions, 2 deletions
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 85997275c..50b983924 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -85,6 +85,7 @@
#include <endian.h>
#if __gnu_linux__
+#include <linux/close_range.h>
#include <sys/prctl.h>
#endif
@@ -919,8 +920,37 @@ pid_t ExecFork(std::set<int> KeepFDs)
signal(SIGCONT,SIG_DFL);
signal(SIGTSTP,SIG_DFL);
- DIR *dir = opendir("/proc/self/fd");
- if (dir != NULL)
+#ifdef CLOSE_RANGE_CLOEXEC
+ // Close all our file descriptors using close_range() if available. This is substantially
+ // faster than the naive method and may be faster than the /proc/self/fd one.
+ {
+ // Used for testing.
+ auto DebugCloseRange = _config->FindB("Debug::CloseRange", false);
+ int first = 3;
+ for (auto keep : KeepFDs)
+ {
+ if (keep > first)
+ {
+ if (DebugCloseRange)
+ std::clog << "close_range(" << first << ", " << keep - 1 << ")" << std::endl;
+ if (close_range(first, keep - 1, CLOSE_RANGE_CLOEXEC))
+ goto err;
+ }
+ first = keep + 1;
+ }
+ if (DebugCloseRange)
+ std::clog << "close_range(" << first << ", " << ~0U << ")" << std::endl;
+ if (close_range(first, ~0U, CLOSE_RANGE_CLOEXEC))
+ goto err;
+
+ return Process;
+ err:
+ if (DebugCloseRange)
+ std::clog << "close_range() failed" << std::endl;
+ // fallthrough
+ }
+#endif
+ if (DIR *dir = opendir("/proc/self/fd"))
{
struct dirent *ent;
while ((ent = readdir(dir)))