summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r--apt-pkg/contrib/fileutl.cc50
1 files changed, 19 insertions, 31 deletions
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 7f785f21c..fc4e047a5 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -920,38 +920,24 @@ pid_t ExecFork(std::set<int> KeepFDs)
signal(SIGWINCH,SIG_DFL);
signal(SIGCONT,SIG_DFL);
signal(SIGTSTP,SIG_DFL);
+ auto safeSetCloseExec = [](int fd, bool close)
+ {
+ if (fcntl(fd, F_SETFD, close ? FD_CLOEXEC : 0) == 0 || errno == EBADF)
+ return;
+ cerr << "FATAL -> Could not set close on exec " << strerror(errno) << endl;
+ _Exit(100);
+ };
-#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.
+// If we don't have it, make the close_range() expression a failure; avoids #if inside the if/else
+#ifndef CLOSE_RANGE_CLOEXEC
+#define close_range(...) -1
+#endif
+ if (close_range(3, ~0U, CLOSE_RANGE_CLOEXEC) == 0)
{
- // 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
+ safeSetCloseExec(keep, false);
}
-#endif
- if (DIR *dir = opendir("/proc/self/fd"))
+ else if (DIR *dir = opendir("/proc/self/fd"))
{
struct dirent *ent;
while ((ent = readdir(dir)))
@@ -959,16 +945,18 @@ pid_t ExecFork(std::set<int> KeepFDs)
int fd = atoi(ent->d_name);
// If fd > 0, it was a fd number and not . or ..
if (fd >= 3 && KeepFDs.find(fd) == KeepFDs.end())
- fcntl(fd,F_SETFD,FD_CLOEXEC);
+ safeSetCloseExec(fd, true);
}
closedir(dir);
- } else {
+ }
+ else
+ {
long ScOpenMax = sysconf(_SC_OPEN_MAX);
// Close all of our FDs - just in case
for (int K = 3; K != ScOpenMax; K++)
{
if(KeepFDs.find(K) == KeepFDs.end())
- fcntl(K,F_SETFD,FD_CLOEXEC);
+ safeSetCloseExec(K, true);
}
}
}