summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-03-13 02:29:27 +0100
committerLennart Poettering <lennart@poettering.net>2012-03-13 02:29:27 +0100
commitb19be9eb9e231ccf350e0e051b687fc425c61904 (patch)
treefe1b39bc5a1b56e1d5c04c1dcde031c0b2c54cc3
parent7f2c63cbf47c89ec56f50469f6551df473dd65d8 (diff)
downloadsystemd-b19be9eb9e231ccf350e0e051b687fc425c61904.tar.gz
util: add brute-force fallback for close_all_fds()
If /proc is not available (i.e. in chroot envs) let's fall back to brute forcing our way through the fd table. https://bugzilla.redhat.com/show_bug.cgi?id=784921
-rw-r--r--src/util.c54
1 files changed, 38 insertions, 16 deletions
diff --git a/src/util.c b/src/util.c
index 3a855c1be4..73481abee6 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2207,13 +2207,47 @@ int fd_cloexec(int fd, bool cloexec) {
return 0;
}
+static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
+ unsigned i;
+
+ assert(n_fdset == 0 || fdset);
+
+ for (i = 0; i < n_fdset; i++)
+ if (fdset[i] == fd)
+ return true;
+
+ return false;
+}
+
int close_all_fds(const int except[], unsigned n_except) {
DIR *d;
struct dirent *de;
int r = 0;
- if (!(d = opendir("/proc/self/fd")))
- return -errno;
+ assert(n_except == 0 || except);
+
+ d = opendir("/proc/self/fd");
+ if (!d) {
+ int fd;
+ struct rlimit rl;
+
+ /* When /proc isn't available (for example in chroots)
+ * the fallback is brute forcing through the fd
+ * table */
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
+ for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+
+ if (fd_in_set(fd, except, n_except))
+ continue;
+
+ if (close_nointr(fd) < 0)
+ if (errno != EBADF && r == 0)
+ r = -errno;
+ }
+
+ return r;
+ }
while ((de = readdir(d))) {
int fd = -1;
@@ -2231,20 +2265,8 @@ int close_all_fds(const int except[], unsigned n_except) {
if (fd == dirfd(d))
continue;
- if (except) {
- bool found;
- unsigned i;
-
- found = false;
- for (i = 0; i < n_except; i++)
- if (except[i] == fd) {
- found = true;
- break;
- }
-
- if (found)
- continue;
- }
+ if (fd_in_set(fd, except, n_except))
+ continue;
if (close_nointr(fd) < 0) {
/* Valgrind has its own FD and doesn't want to have it closed */