summaryrefslogtreecommitdiff
path: root/src/missing.cc
diff options
context:
space:
mode:
authorChristian Persch <chpe@src.gnome.org>2020-07-18 13:52:55 +0200
committerChristian Persch <chpe@src.gnome.org>2020-07-18 13:52:55 +0200
commite036d389eb198efa85bf35dd8baa2c47220abb8d (patch)
treee6059f27bfbb5e99692e6f90d47446012d530e68 /src/missing.cc
parented78b9e2ec47675a9dccf045caca4d7a0b6c9fe8 (diff)
downloadvte-e036d389eb198efa85bf35dd8baa2c47220abb8d.tar.gz
spawn: Error out when it is impossible to close all file descriptors
When the limit is RLIM_INFINITY, we cannot use the fallback fdwalk that calls close() on all FDs. Instead of potentially leaking some FDs, error out.
Diffstat (limited to 'src/missing.cc')
-rw-r--r--src/missing.cc24
1 files changed, 15 insertions, 9 deletions
diff --git a/src/missing.cc b/src/missing.cc
index 7729943d..dda355e8 100644
--- a/src/missing.cc
+++ b/src/missing.cc
@@ -86,18 +86,17 @@ filename_to_fd (const char *p)
/* This function is called between fork and execve/_exit and so must be
* async-signal-safe; see man:signal-safety(7).
*/
-static int
+static rlim_t
getrlimit_NOFILE_max(void)
{
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rlim;
#ifdef __linux__
- if (prlimit(0 /* this PID */, RLIMIT_NOFILE, nullptr, &rlim) == 0 &&
- rlim.rlim_max != RLIM_INFINITY)
+ if (prlimit(0 /* this PID */, RLIMIT_NOFILE, nullptr, &rlim) == 0)
return rlim.rlim_max;
- /* fallback */
+ return RLIM_INFINITY;
#endif /* __linux__ */
#ifdef __GLIBC__
@@ -106,8 +105,7 @@ getrlimit_NOFILE_max(void)
*
* According to the glibc manual, getrlimit is AS-safe.
*/
- if (getrlimit(RLIMIT_NOFILE, &rlim) == 0 &&
- rlim.rlim_max != RLIM_INFINITY)
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
return rlim.rlim_max;
/* fallback */
@@ -126,8 +124,8 @@ getrlimit_NOFILE_max(void)
/* fallback */
#endif
- /* Hardcoded fallback: the default process hard limit in Linux as of 2020 */
- return 4096;
+ /* couldn't determine, so potentially infinite */
+ return RLIM_INFINITY;
}
/* This function is called between fork and execve/_exit and so must be
@@ -178,7 +176,15 @@ fdwalk(int (*cb)(void *data, int fd),
#endif
auto const open_max = getrlimit_NOFILE_max();
- for (fd = 0; fd < open_max; fd++)
+ if (open_max == RLIM_INFINITY || open_max > G_MAXINT) {
+ /* We cannot close infinitely many FDs, but we also must not
+ * leak any FDs. Return an error.
+ */
+ errno = ENFILE;
+ return -1;
+ }
+
+ for (fd = 0; fd < int(open_max); fd++)
if ((res = cb (data, fd)) != 0)
break;