summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@ev0ke.net>2015-06-03 13:56:01 -0400
committerNick Mathewson <nickm@torproject.org>2015-06-25 11:30:47 -0400
commit699acd8d54bd685b135d3a8e758d05dd0802b820 (patch)
tree6be18bc59cf99c0b73095097c4849f679ad063a7 /src/common
parent64bdf040f021ca3ccb661c4056ee857e2ed44a4e (diff)
downloadtor-699acd8d54bd685b135d3a8e758d05dd0802b820.tar.gz
tor-699acd8d54bd685b135d3a8e758d05dd0802b820.zip
Validate the open file limit when creating a socket
Fixes #16288 Signed-off-by: David Goulet <dgoulet@ev0ke.net>
Diffstat (limited to 'src/common')
-rw-r--r--src/common/compat.c47
-rw-r--r--src/common/compat.h4
2 files changed, 42 insertions, 9 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index 8da7ef3f69..ac4732179e 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -131,6 +131,11 @@
#include "strlcat.c"
#endif
+/* When set_max_file_descriptors() is called, update this with the max file
+ * descriptor value so we can use it to check the limit when opening a new
+ * socket. Default value is what Debian sets as the default hard limit. */
+static int max_sockets = 1024;
+
/** As open(path, flags, mode), but return an fd with the close-on-exec mode
* set. */
int
@@ -1187,6 +1192,18 @@ tor_open_socket_with_extensions(int domain, int type, int protocol,
int cloexec, int nonblock)
{
tor_socket_t s;
+
+ /* We are about to create a new file descriptor so make sure we have
+ * enough of them. */
+ if (get_n_open_sockets() >= max_sockets - 1) {
+#ifdef _WIN32
+ WSASetLastError(WSAEMFILE);
+#else
+ errno = EMFILE;
+#endif
+ return TOR_INVALID_SOCKET;
+ }
+
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
(nonblock ? SOCK_NONBLOCK : 0);
@@ -1258,6 +1275,18 @@ tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr,
socklen_t *len, int cloexec, int nonblock)
{
tor_socket_t s;
+
+ /* We are about to create a new file descriptor so make sure we have
+ * enough of them. */
+ if (get_n_open_sockets() >= max_sockets - 1) {
+#ifdef _WIN32
+ WSASetLastError(WSAEMFILE);
+#else
+ errno = EMFILE;
+#endif
+ return TOR_INVALID_SOCKET;
+ }
+
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
(nonblock ? SOCK_NONBLOCK : 0);
@@ -1553,6 +1582,12 @@ tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
int
set_max_file_descriptors(rlim_t limit, int *max_out)
{
+ if (limit < ULIMIT_BUFFER) {
+ log_warn(LD_CONFIG,
+ "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
+ return -1;
+ }
+
/* Define some maximum connections values for systems where we cannot
* automatically determine a limit. Re Cygwin, see
* http://archives.seul.org/or/talk/Aug-2006/msg00210.html
@@ -1592,7 +1627,7 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
limit = rlim.rlim_max;
if (limit > INT_MAX)
limit = INT_MAX;
- *max_out = (int)limit - ULIMIT_BUFFER;
+ *max_out = max_sockets = (int)limit - ULIMIT_BUFFER;
return 0;
}
if (rlim.rlim_max < limit) {
@@ -1606,6 +1641,9 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
(unsigned long)rlim.rlim_cur, (unsigned long)rlim.rlim_max);
}
+ /* Set the current limit value so if the attempt to set the limit to the
+ * max fails at least we'll have a valid value of maximum sockets. */
+ max_sockets = rlim.rlim_cur - ULIMIT_BUFFER;
rlim.rlim_cur = rlim.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
@@ -1639,15 +1677,10 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
limit = rlim.rlim_cur;
#endif /* HAVE_GETRLIMIT */
- if (limit < ULIMIT_BUFFER) {
- log_warn(LD_CONFIG,
- "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
- return -1;
- }
if (limit > INT_MAX)
limit = INT_MAX;
tor_assert(max_out);
- *max_out = (int)limit - ULIMIT_BUFFER;
+ *max_out = max_sockets = (int)limit - ULIMIT_BUFFER;
return 0;
}
diff --git a/src/common/compat.h b/src/common/compat.h
index 5189b7e056..acf5ffd1ae 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -580,7 +580,7 @@ int network_init(void);
#define ERRNO_IS_ACCEPT_EAGAIN(e) ERRNO_IS_EAGAIN(e)
/** Return true if e is EMFILE or another error indicating that a call to
* accept() has failed because we're out of fds or something. */
-#define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \
+#define ERRNO_IS_RESOURCE_LIMIT(e) \
((e) == WSAEMFILE || (e) == WSAENOBUFS)
/** Return true if e is EADDRINUSE or the local equivalent. */
#define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE)
@@ -598,7 +598,7 @@ const char *tor_socket_strerror(int e);
#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS || 0)
#define ERRNO_IS_ACCEPT_EAGAIN(e) \
(ERRNO_IS_EAGAIN(e) || (e) == ECONNABORTED)
-#define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \
+#define ERRNO_IS_RESOURCE_LIMIT(e) \
((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM)
#define ERRNO_IS_EADDRINUSE(e) (((e) == EADDRINUSE) || 0)
#define tor_socket_errno(sock) (errno)