summaryrefslogtreecommitdiff
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
parent86be82f9877e29cb27de98c8680026df28e99af4 (diff)
parent6aca3716f051b5b6bff63d51fff68b9c7ebc7474 (diff)
Merge branch 'close-range' into 'main'
ExecFork: Use close_range() if available See merge request apt-team/apt!524
-rw-r--r--apt-pkg/contrib/fileutl.cc34
-rw-r--r--doc/examples/configure-index1
-rwxr-xr-xtest/integration/test-close-range25
3 files changed, 58 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)))
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index c36f922b6..65b5032bc 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -642,6 +642,7 @@ APT::FTPArchive::release
Version "<STRING>";
};
+Debug::CloseRange "<BOOL>";
Debug::NoDropPrivs "<BOOL>";
APT::Sandbox
{
diff --git a/test/integration/test-close-range b/test/integration/test-close-range
new file mode 100755
index 000000000..977c4cf0a
--- /dev/null
+++ b/test/integration/test-close-range
@@ -0,0 +1,25 @@
+#!/bin/sh
+set -e
+
+TESTDIR="$(readlink -f "$(dirname "$0")")"
+. "$TESTDIR/framework"
+
+setupenvironment
+configarchitecture 'amd64'
+
+
+testsuccessequal "close_range(3, 4294967295)" apthelper drop-privs -o Debug::CloseRange=1 true
+
+
+testsuccessequal "close_range(4, 4294967295)" apthelper drop-privs -o APT::Keep-Fds::=3 -o Debug::CloseRange=1 true
+
+
+testsuccessequal "close_range(3, 4)
+close_range(6, 4294967295)" apthelper drop-privs -o APT::Keep-Fds::=5 -o Debug::CloseRange=1 true
+
+
+testsuccessequal "close_range(4, 4)
+close_range(6, 4294967295)" apthelper drop-privs -o APT::Keep-Fds::=3 -o APT::Keep-Fds::=5 -o Debug::CloseRange=1 true
+
+testsuccessequal "close_range(4, 4)
+close_range(7, 4294967295)" apthelper drop-privs -o APT::Keep-Fds::=3 -o APT::Keep-Fds::=5 -o APT::Keep-Fds::=6 -o Debug::CloseRange=1 true