diff --git a/CHANGES b/CHANGES index 1a31cdea86..105f36f2d1 100644 --- a/CHANGES +++ b/CHANGES @@ -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 * Use unique port for test `scripts.base.utils.active-http` (Benjamin Bannier, Corelight) diff --git a/VERSION b/VERSION index 95e6b96b09..cf88582c49 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.1.0-dev.451 +6.1.0-dev.455 diff --git a/auxil/libunistd b/auxil/libunistd index 2766a0c45a..b38e9c8ebf 160000 --- a/auxil/libunistd +++ b/auxil/libunistd @@ -1 +1 @@ -Subproject commit 2766a0c45a6dbcdcf26cd1209a73a13323854961 +Subproject commit b38e9c8ebff08959a712a5663ba25e0624a3af00 diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 9b06eb3f8b..d95b1e7d50 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -992,23 +992,54 @@ void DNS_Mgr::Resolve() { int nfds = 0; 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_usec = 0; for ( int i = 0; i < MAX_PENDING_REQUESTS; i++ ) { - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - nfds = ares_fds(channel, &read_fds, &write_fds); + int nfds = 0; + int bitmap = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM); + + 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 ) break; + // poll() timeout is in milliseconds. tvp = ares_timeout(channel, &tv, &tv); - int res = select(nfds, &read_fds, &write_fds, NULL, tvp); - if ( res >= 0 ) - ares_process(channel, &read_fds, &write_fds); + int timeout_ms = tvp->tv_sec * 1000 + tvp->tv_usec / 1000; + + 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 ) 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); - FD_ZERO(&write_fds); - int nfds = ares_fds(channel, &read_fds, &write_fds); + // Do we have any sockets that are read or writable? if ( nfds == 0 ) return -1;