diff options
| author | Julian Andres Klode <jak@debian.org> | 2025-10-20 16:11:37 +0000 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2025-10-20 16:11:37 +0000 |
| commit | 683214eed4aced71f94f12a0cc70509bdb473c82 (patch) | |
| tree | cd51616b1f6b42c7d3e53a39f1400e292b6ea476 | |
| parent | 86be82f9877e29cb27de98c8680026df28e99af4 (diff) | |
| parent | 6aca3716f051b5b6bff63d51fff68b9c7ebc7474 (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.cc | 34 | ||||
| -rw-r--r-- | doc/examples/configure-index | 1 | ||||
| -rwxr-xr-x | test/integration/test-close-range | 25 |
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 |
