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:
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user