aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-08-04 14:43:26 +0200
committerTobias Brunner <tobias@strongswan.org>2015-08-17 11:19:32 +0200
commitb410d7f8ff39001a3fefa5bebd08de3c295f5c9c (patch)
treed64ec3546ca3ae632de2db70691b1afbaa3c9694
parentcec1fe8c7d426cadb892730ec338cd5d3107d780 (diff)
downloadstrongswan-b410d7f8ff39001a3fefa5bebd08de3c295f5c9c.tar.bz2
strongswan-b410d7f8ff39001a3fefa5bebd08de3c295f5c9c.tar.xz
utils: Don't use directory enumerator to close open FDs in closefrom()
Calling malloc() after fork() is potentially unsafe, so we should avoid it if possible. opendir() will still require an allocation but that's less than the variant using the enumerator wrapper, thus, decreasing the conflict potential. This way we can also avoid closing the FD for the enumerated directory itself. References #990.
-rw-r--r--src/libstrongswan/utils/utils.c60
1 files changed, 36 insertions, 24 deletions
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index 9b516accd..55eab8e14 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -16,15 +16,23 @@
#include "utils.h"
+#include <sys/types.h>
#include <unistd.h>
#include <limits.h>
+#include <ctype.h>
#ifndef WIN32
# include <signal.h>
#endif
+#ifndef HAVE_CLOSEFROM
+# include <dirent.h>
+#endif
+
#include <library.h>
#include <collections/enumerator.h>
+#define FD_DIR "/proc/self/fd"
+
#ifdef WIN32
#include <threading/mutex.h>
@@ -110,43 +118,47 @@ void wait_sigint()
/**
* Described in header.
*/
-void closefrom(int lowfd)
+void closefrom(int low_fd)
{
- char fd_dir[PATH_MAX];
- int maxfd, fd, len;
-
- /* try to close only open file descriptors on Linux... */
- len = snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", getpid());
- if (len > 0 && len < sizeof(fd_dir) && access(fd_dir, F_OK) == 0)
+ DIR *dir;
+ struct dirent *entry;
+ int max_fd, dir_fd, fd;
+
+ /* try to close only open file descriptors on Linux... This is potentially
+ * unsafe when called after fork() in multi-threaded applications. In
+ * particular opendir() will require an allocation. So it depends on how
+ * the malloc() implementation handles such situations */
+ dir = opendir(FD_DIR);
+ if (dir)
{
- enumerator_t *enumerator = enumerator_create_directory(fd_dir);
- if (enumerator)
+ dir_fd = dirfd(dir);
+ while ((entry = readdir(dir)))
{
- char *rel;
- while (enumerator->enumerate(enumerator, &rel, NULL, NULL))
+ if (!isdigit(entry->d_name[0]))
+ {
+ continue;
+ }
+ fd = atoi(entry->d_name);
+ if (fd != dir_fd && fd >= low_fd)
{
- fd = atoi(rel);
- if (fd >= lowfd)
- {
- close(fd);
- }
+ close(fd);
}
- enumerator->destroy(enumerator);
- return;
}
+ closedir(dir);
+ return;
}
/* ...fall back to closing all fds otherwise */
#ifdef WIN32
- maxfd = _getmaxstdio();
+ max_fd = _getmaxstdio();
#else
- maxfd = (int)sysconf(_SC_OPEN_MAX);
+ max_fd = (int)sysconf(_SC_OPEN_MAX);
#endif
- if (maxfd < 0)
+ if (max_fd < 0)
{
- maxfd = 256;
+ max_fd = 256;
}
- for (fd = lowfd; fd < maxfd; fd++)
+ for (fd = low_fd; fd < max_fd; fd++)
{
close(fd);
}