diff options
author | David Goulet <dgoulet@ev0ke.net> | 2015-06-03 13:56:01 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-06-25 11:30:47 -0400 |
commit | 699acd8d54bd685b135d3a8e758d05dd0802b820 (patch) | |
tree | 6be18bc59cf99c0b73095097c4849f679ad063a7 /src/common/compat.c | |
parent | 64bdf040f021ca3ccb661c4056ee857e2ed44a4e (diff) | |
download | tor-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/compat.c')
-rw-r--r-- | src/common/compat.c | 47 |
1 files changed, 40 insertions, 7 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; } |