1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Check for sd > FD_SETSIZE before it is unrecoverable. Fixes #1857

This commit is contained in:
dmiller
2022-09-29 00:13:10 +00:00
parent de9f84d080
commit b5dd2956dd
3 changed files with 56 additions and 6 deletions

View File

@@ -327,8 +327,7 @@ bool GroupScanStats::sendOK(struct timeval *when) const {
if (when) if (when)
TIMEVAL_MSEC_ADD(*when, USI->now, 1000); TIMEVAL_MSEC_ADD(*when, USI->now, 1000);
if ((USI->scantype == CONNECT_SCAN || USI->ptech.connecttcpscan) if (CSI && !CSI->sendOK())
&& CSI->numSDs >= CSI->maxSocketsAllowed)
return false; return false;
/* We need to stop sending if it has been a long time since /* We need to stop sending if it has been a long time since

View File

@@ -244,11 +244,17 @@ public:
was in the list, false if you tried to clear an sd that wasn't was in the list, false if you tried to clear an sd that wasn't
there in the first place. */ there in the first place. */
bool clearSD(int sd); bool clearSD(int sd);
/* Try to get a socket that's good for select(). Return true if it worked;
* false if it didn't. */
bool sendOK();
int maxValidSD; /* The maximum socket descriptor in any of the fd_sets */ int maxValidSD; /* The maximum socket descriptor in any of the fd_sets */
fd_set fds_read; fd_set fds_read;
fd_set fds_write; fd_set fds_write;
fd_set fds_except; fd_set fds_except;
int numSDs; /* Number of socket descriptors being watched */ int numSDs; /* Number of socket descriptors being watched */
int getSocket();
private:
int nextSD;
int maxSocketsAllowed; /* No more than this many sockets may be created @once */ int maxSocketsAllowed; /* No more than this many sockets may be created @once */
}; };

View File

@@ -88,9 +88,12 @@ void UltraProbe::setConnect(u16 portno) {
ConnectScanInfo::ConnectScanInfo() { ConnectScanInfo::ConnectScanInfo() {
maxValidSD = -1; maxValidSD = -1;
numSDs = 0; numSDs = 0;
nextSD = -1;
if (o.max_parallelism > 0) { if (o.max_parallelism > 0) {
maxSocketsAllowed = o.max_parallelism; maxSocketsAllowed = o.max_parallelism;
} else { }
#ifndef WIN32
else {
/* Subtracting 10 from max_sd accounts for /* Subtracting 10 from max_sd accounts for
stdin stdin
stdout stdout
@@ -106,7 +109,17 @@ ConnectScanInfo::ConnectScanInfo() {
if (maxSocketsAllowed < 5) if (maxSocketsAllowed < 5)
maxSocketsAllowed = 5; maxSocketsAllowed = 5;
} }
/* We can't issue a FD_SET operation with a socket descriptor greater than
* FD_SETSIZE, and we can't stop the OS from handing us ones that are greater
* than that, either, so leave a buffer here. */
maxSocketsAllowed = MIN(maxSocketsAllowed, FD_SETSIZE - 10); maxSocketsAllowed = MIN(maxSocketsAllowed, FD_SETSIZE - 10);
#else
/* Windows does not have an explicit limit, but we have to keep it below
* FD_SETSIZE or select() will fail. Fortunately, it's about the *number* of
* sockets, not the socket descriptor number, so we can run right up to that
* limit. */
maxSocketsAllowed = MIN(maxSocketsAllowed, FD_SETSIZE - 1);
#endif
FD_ZERO(&fds_read); FD_ZERO(&fds_read);
FD_ZERO(&fds_write); FD_ZERO(&fds_write);
FD_ZERO(&fds_except); FD_ZERO(&fds_except);
@@ -115,6 +128,38 @@ ConnectScanInfo::ConnectScanInfo() {
/* Nothing really to do here. */ /* Nothing really to do here. */
ConnectScanInfo::~ConnectScanInfo() {} ConnectScanInfo::~ConnectScanInfo() {}
bool ConnectScanInfo::sendOK() {
if (numSDs >= maxSocketsAllowed)
return false;
if (nextSD > 0)
return true;
nextSD = socket(o.af(), SOCK_STREAM, IPPROTO_TCP);
if (nextSD == -1)
pfatal("Socket creation in %s", __func__);
#ifndef WIN32
/* Check here whether this socket descriptor number will be a problem. If so,
* close it and tell the engine to slow down. Windows doesn't have this
* limit, only maxSocketsAllowed. */
if (nextSD >= FD_SETSIZE) {
if (o.debugging) {
log_write(LOG_STDOUT, "Socket descriptor %d greater than FD_SETSIZE: slow down.\n", nextSD);
}
close(nextSD);
nextSD = -1;
return false;
}
#endif
return true;
}
int ConnectScanInfo::getSocket() {
int sd = nextSD;
nextSD = -1;
return sd;
}
/* Watch a socket descriptor (add to fd_sets and maxValidSD). Returns /* Watch a socket descriptor (add to fd_sets and maxValidSD). Returns
true if the SD was absent from the list, false if you tried to true if the SD was absent from the list, false if you tried to
watch an SD that was already being watched. */ watch an SD that was already being watched. */
@@ -370,15 +415,15 @@ UltraProbe *sendConnectScanProbe(UltraScanInfo *USI, HostScanStats *hss,
#endif #endif
size_t socklen; size_t socklen;
ConnectProbe *CP; ConnectProbe *CP;
ConnectScanInfo *CSI = USI->gstats->CSI;
probe->tryno = tryno; probe->tryno = tryno;
/* First build the probe */ /* First build the probe */
probe->setConnect(destport); probe->setConnect(destport);
CP = probe->CP(); CP = probe->CP();
/* Initiate the connection */ /* Initiate the connection */
CP->sd = socket(o.af(), SOCK_STREAM, IPPROTO_TCP); CP->sd = CSI->getSocket();
if (CP->sd == -1) assert(CP->sd > 0);
pfatal("Socket creation in %s", __func__);
unblock_socket(CP->sd); unblock_socket(CP->sd);
init_socket(CP->sd); init_socket(CP->sd);
set_ttl(CP->sd, o.ttl); set_ttl(CP->sd, o.ttl);