Merge remote-tracking branch 'origin/topic/awelzel/3309-dns-mgr-fd-set-size-1024'

* origin/topic/awelzel/3309-dns-mgr-fd-set-size-1024:
  auxil/libunistd: Bump for poll() inclusion
  DNS_Mgr: Replace ares_fds() with ares_getsock()
This commit is contained in:
Arne Welzel 2023-09-26 18:42:20 +02:00
commit c6486e70ef
4 changed files with 64 additions and 14 deletions

14
CHANGES
View file

@ -1,3 +1,17 @@
6.1.0-dev.455 | 2023-09-26 18:42:20 +0200
* auxil/libunistd: Bump for poll() inclusion (Arne Welzel, Corelight)
* GH-3309: DNS_Mgr: Replace ares_fds() with ares_getsock() (Arne Welzel, Corelight)
On Slack, a user reported "fortify source" aborts within ares_fds() due
to the FDs used by c-ares exceeding 1024 and thereby larger than the
maximum fd value that a fd_set can hold.
Switch to ares_get_socks() and poll() to avoid this.
Closes #3309.
6.1.0-dev.451 | 2023-09-26 16:14:24 +0200 6.1.0-dev.451 | 2023-09-26 16:14:24 +0200
* Use unique port for test `scripts.base.utils.active-http` (Benjamin Bannier, Corelight) * Use unique port for test `scripts.base.utils.active-http` (Benjamin Bannier, Corelight)

View file

@ -1 +1 @@
6.1.0-dev.451 6.1.0-dev.455

@ -1 +1 @@
Subproject commit 2766a0c45a6dbcdcf26cd1209a73a13323854961 Subproject commit b38e9c8ebff08959a712a5663ba25e0624a3af00

View file

@ -6,7 +6,7 @@
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/select.h> #include <sys/poll.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
@ -992,23 +992,54 @@ void DNS_Mgr::Resolve()
{ {
int nfds = 0; int nfds = 0;
struct timeval *tvp, tv; struct timeval *tvp, tv;
fd_set read_fds, write_fds; struct pollfd pollfds[ARES_GETSOCK_MAXNUM];
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
tv.tv_sec = DNS_TIMEOUT; tv.tv_sec = DNS_TIMEOUT;
tv.tv_usec = 0; tv.tv_usec = 0;
for ( int i = 0; i < MAX_PENDING_REQUESTS; i++ ) for ( int i = 0; i < MAX_PENDING_REQUESTS; i++ )
{ {
FD_ZERO(&read_fds); int nfds = 0;
FD_ZERO(&write_fds); int bitmap = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
nfds = ares_fds(channel, &read_fds, &write_fds);
for ( int i = 0; i < ARES_GETSOCK_MAXNUM; i++ )
{
bool rd = ARES_GETSOCK_READABLE(bitmap, i);
bool wr = ARES_GETSOCK_WRITABLE(bitmap, i);
if ( rd || wr )
{
pollfds[nfds].fd = socks[i];
pollfds[nfds].events = rd ? POLLIN : 0;
pollfds[nfds].events |= wr ? POLLOUT : 0;
++nfds;
}
}
// Do we have any sockets that are read or writable?
if ( nfds == 0 ) if ( nfds == 0 )
break; break;
// poll() timeout is in milliseconds.
tvp = ares_timeout(channel, &tv, &tv); tvp = ares_timeout(channel, &tv, &tv);
int res = select(nfds, &read_fds, &write_fds, NULL, tvp); int timeout_ms = tvp->tv_sec * 1000 + tvp->tv_usec / 1000;
if ( res >= 0 )
ares_process(channel, &read_fds, &write_fds); int res = poll(pollfds, nfds, timeout_ms);
if ( res > 0 )
{
for ( int i = 0; i < nfds; i++ )
{
int rdfd = pollfds[i].revents | POLLIN ? pollfds[i].fd : ARES_SOCKET_BAD;
int wrfd = pollfds[i].revents | POLLOUT ? pollfds[i].fd : ARES_SOCKET_BAD;
if ( rdfd != ARES_SOCKET_BAD || wrfd != ARES_SOCKET_BAD )
ares_process_fd(channel, rdfd, wrfd);
}
}
else if ( res == 0 )
// Do timeout processing when poll() timed out.
ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
} }
} }
@ -1442,11 +1473,16 @@ double DNS_Mgr::GetNextTimeout()
if ( asyncs_pending == 0 ) if ( asyncs_pending == 0 )
return -1; return -1;
fd_set read_fds, write_fds; int nfds = 0;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
int bitmap = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
for ( int i = 0; i < ARES_GETSOCK_MAXNUM; i++ )
{
if ( ARES_GETSOCK_READABLE(bitmap, i) || ARES_GETSOCK_WRITABLE(bitmap, i) )
++nfds;
}
FD_ZERO(&read_fds); // Do we have any sockets that are read or writable?
FD_ZERO(&write_fds);
int nfds = ares_fds(channel, &read_fds, &write_fds);
if ( nfds == 0 ) if ( nfds == 0 )
return -1; return -1;