summaryrefslogtreecommitdiff
path: root/src/basic/fd-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-05-07 17:54:59 +0200
committerLennart Poettering <lennart@poettering.net>2018-05-17 20:40:04 +0200
commit37bc14de5bd74a056d55ec14f63dc9ec999e974e (patch)
treeddad4bfcee8389c85ac20c739883e05dd270b550 /src/basic/fd-util.c
parent1752d69a8bd2fed951b0298806440fbd2dbb07f8 (diff)
downloadsystemd-37bc14de5bd74a056d55ec14f63dc9ec999e974e.tar.gz
basic: be more careful when closing fds based on RLIMIT_NOFILE
Let's make sure we properly handle cases where RLIMIT_NOFILE is set to infinity, zero or values outside of the "int" range.
Diffstat (limited to 'src/basic/fd-util.c')
-rw-r--r--src/basic/fd-util.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index 4b3e7ed557..9536a50b74 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -199,15 +199,22 @@ int close_all_fds(const int except[], size_t n_except) {
d = opendir("/proc/self/fd");
if (!d) {
- int fd;
struct rlimit rl;
+ int fd, max_fd;
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
+ /* 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 (rl.rlim_max == 0)
+ return -EINVAL;
+
+ /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range
+ * of 'int'. Let's avoid implicit overflows. */
+ max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1);
+
+ for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
int q;
if (fd_in_set(fd, except, n_except))