diff options
author | Lennart Poettering <lennart@poettering.net> | 2012-03-13 02:29:27 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-03-13 02:29:27 +0100 |
commit | b19be9eb9e231ccf350e0e051b687fc425c61904 (patch) | |
tree | fe1b39bc5a1b56e1d5c04c1dcde031c0b2c54cc3 /src | |
parent | 7f2c63cbf47c89ec56f50469f6551df473dd65d8 (diff) |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/util.c | 54 |
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 */ |