Michal Schmidt 14c310
From 9697feabd63b19b4cbcebb8e6a369eb99e684a65 Mon Sep 17 00:00:00 2001
Michal Schmidt 14c310
From: Lennart Poettering <lennart@poettering.net>
Michal Schmidt 14c310
Date: Tue, 13 Mar 2012 02:29:27 +0100
Michal Schmidt 14c310
Subject: [PATCH] util: add brute-force fallback for close_all_fds()
Michal Schmidt 14c310
Michal Schmidt 14c310
If /proc is not available (i.e. in chroot envs) let's fall back to brute
Michal Schmidt 14c310
forcing our way through the fd table.
Michal Schmidt 14c310
Michal Schmidt 14c310
https://bugzilla.redhat.com/show_bug.cgi?id=784921
Michal Schmidt 14c310
(cherry picked from commit b19be9eb9e231ccf350e0e051b687fc425c61904)
Michal Schmidt 14c310
---
Michal Schmidt 14c310
 src/util.c |   54 ++++++++++++++++++++++++++++++++++++++----------------
Michal Schmidt 14c310
 1 files changed, 38 insertions(+), 16 deletions(-)
Michal Schmidt 14c310
Michal Schmidt 14c310
diff --git a/src/util.c b/src/util.c
Michal Schmidt 14c310
index 0c9537e..3a66c3b 100644
Michal Schmidt 14c310
--- a/src/util.c
Michal Schmidt 14c310
+++ b/src/util.c
Michal Schmidt 14c310
@@ -2147,13 +2147,47 @@ int fd_cloexec(int fd, bool cloexec) {
Michal Schmidt 14c310
         return 0;
Michal Schmidt 14c310
 }
Michal Schmidt 14c310
 
Michal Schmidt 14c310
+static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
Michal Schmidt 14c310
+        unsigned i;
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+        assert(n_fdset == 0 || fdset);
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+        for (i = 0; i < n_fdset; i++)
Michal Schmidt 14c310
+                if (fdset[i] == fd)
Michal Schmidt 14c310
+                        return true;
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+        return false;
Michal Schmidt 14c310
+}
Michal Schmidt 14c310
+
Michal Schmidt 14c310
 int close_all_fds(const int except[], unsigned n_except) {
Michal Schmidt 14c310
         DIR *d;
Michal Schmidt 14c310
         struct dirent *de;
Michal Schmidt 14c310
         int r = 0;
Michal Schmidt 14c310
 
Michal Schmidt 14c310
-        if (!(d = opendir("/proc/self/fd")))
Michal Schmidt 14c310
-                return -errno;
Michal Schmidt 14c310
+        assert(n_except == 0 || except);
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+        d = opendir("/proc/self/fd");
Michal Schmidt 14c310
+        if (!d) {
Michal Schmidt 14c310
+                int fd;
Michal Schmidt 14c310
+                struct rlimit rl;
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+                /* When /proc isn't available (for example in chroots)
Michal Schmidt 14c310
+                 * the fallback is brute forcing through the fd
Michal Schmidt 14c310
+                 * table */
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+                assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
Michal Schmidt 14c310
+                for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+                        if (fd_in_set(fd, except, n_except))
Michal Schmidt 14c310
+                                continue;
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+                        if (close_nointr(fd) < 0)
Michal Schmidt 14c310
+                                if (errno != EBADF && r == 0)
Michal Schmidt 14c310
+                                        r = -errno;
Michal Schmidt 14c310
+                }
Michal Schmidt 14c310
+
Michal Schmidt 14c310
+                return r;
Michal Schmidt 14c310
+        }
Michal Schmidt 14c310
 
Michal Schmidt 14c310
         while ((de = readdir(d))) {
Michal Schmidt 14c310
                 int fd = -1;
Michal Schmidt 14c310
@@ -2171,20 +2205,8 @@ int close_all_fds(const int except[], unsigned n_except) {
Michal Schmidt 14c310
                 if (fd == dirfd(d))
Michal Schmidt 14c310
                         continue;
Michal Schmidt 14c310
 
Michal Schmidt 14c310
-                if (except) {
Michal Schmidt 14c310
-                        bool found;
Michal Schmidt 14c310
-                        unsigned i;
Michal Schmidt 14c310
-
Michal Schmidt 14c310
-                        found = false;
Michal Schmidt 14c310
-                        for (i = 0; i < n_except; i++)
Michal Schmidt 14c310
-                                if (except[i] == fd) {
Michal Schmidt 14c310
-                                        found = true;
Michal Schmidt 14c310
-                                        break;
Michal Schmidt 14c310
-                                }
Michal Schmidt 14c310
-
Michal Schmidt 14c310
-                        if (found)
Michal Schmidt 14c310
-                                continue;
Michal Schmidt 14c310
-                }
Michal Schmidt 14c310
+                if (fd_in_set(fd, except, n_except))
Michal Schmidt 14c310
+                        continue;
Michal Schmidt 14c310
 
Michal Schmidt 14c310
                 if (close_nointr(fd) < 0) {
Michal Schmidt 14c310
                         /* Valgrind has its own FD and doesn't want to have it closed */