From 5a73027642b826793658774df8a0536975120b19 Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Fri, 11 Oct 2019 08:59:41 -0400 Subject: [PATCH] Fix: libcrmservice: try not to spam close() file descriptors With large file descriptor limits, action_launch_child can close millions of non-existent file descriptors. Instead, try to read open file descriptors from /proc or /dev/fd and close only those which are open. See rhbz#1762025 --- lib/services/services_linux.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c index 90c1f44..464fc5b 100644 --- a/lib/services/services_linux.c +++ b/lib/services/services_linux.c @@ -445,6 +445,7 @@ static void action_launch_child(svc_action_t *op) { int lpc; + DIR *dir; /* SIGPIPE is ignored (which is different from signal blocking) by the gnutls library. * Depending on the libqb version in use, libqb may set SIGPIPE to be ignored as well. @@ -476,8 +477,29 @@ action_launch_child(svc_action_t *op) setpgid(0, 0); // Close all file descriptors except stdin/stdout/stderr - for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) { - close(lpc); +#if SUPPORT_PROCFS + dir = opendir("/proc/self/fd"); +#else + dir = opendir("/dev/fd"); +#endif + if (dir == NULL) { /* /proc or /dev/fd not available */ + /* Iterate over all possible fds, might be slow */ + for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) { + close(lpc); + } + } else { + /* Iterate over fds obtained from /proc or /dev/fd */ + struct dirent *entry; + int dir_fd = dirfd(dir); + + while ((entry = readdir(dir)) != NULL) { + lpc = atoi(entry->d_name); + if (lpc > STDERR_FILENO && lpc != dir_fd) { + close(lpc); + } + } + + closedir(dir); } #if SUPPORT_CIBSECRETS -- 1.8.3.1