mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 06:01:28 +00:00
Added safe fd_set operations.
Only FD_SET and FD_CLR were available. Added a FD_ISSET equivalent. Implemented them as static inline instead of macros for consistency. These functions abort() if the FD number is higher than FD_SETSIZE (except on windows where no check is performed).
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
o Added safe fd_set operations. This makes nmap fail gracefully instead of
|
||||||
|
crashing when the number of file descriptors grows over FD_SETSIZE. Jacek
|
||||||
|
Wielemborek reported the crash. [Henri Doreau]
|
||||||
|
|
||||||
o [NSE] Added tls library for functions related to SSLv3 and TLS messages.
|
o [NSE] Added tls library for functions related to SSLv3 and TLS messages.
|
||||||
Existing ssl-enum-ciphers, ssl-date, and tls-nextprotoneg scripts were
|
Existing ssl-enum-ciphers, ssl-date, and tls-nextprotoneg scripts were
|
||||||
|
|||||||
@@ -369,37 +369,41 @@ extern "C" int vsnprintf (char *, size_t, const char *, va_list);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
static inline int checked_fd_isset(int fd, const fd_set *fds) {
|
||||||
#define CHECKED_FD_SET FD_SET
|
#ifndef WIN32
|
||||||
#else
|
if (fd >= FD_SETSIZE) {
|
||||||
#define CHECKED_FD_SET(fd, set) \
|
fprintf(stderr, "Attempt to FD_ISSET fd %d, which is not less than "
|
||||||
do { \
|
"FD_SETSIZE (%d). Try using a lower parallelism.",
|
||||||
if ((fd) < FD_SETSIZE) { \
|
fd, FD_SETSIZE);
|
||||||
FD_SET((fd), (set)); \
|
abort();
|
||||||
} else { \
|
}
|
||||||
fprintf(stderr, "%s:%ld: Attempt to FD_SET fd %d, which is not less than" \
|
|
||||||
" FD_SETSIZE (%d). Try using a lower parallelism.", \
|
|
||||||
__FILE__, (long int) __LINE__, (fd), FD_SETSIZE); \
|
|
||||||
abort(); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
#endif
|
||||||
|
return FD_ISSET(fd, fds);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
static inline void checked_fd_clr(int fd, fd_set *fds) {
|
||||||
#define CHECKED_FD_CLR FD_CLR
|
#ifndef WIN32
|
||||||
#else
|
if (fd >= FD_SETSIZE) {
|
||||||
#define CHECKED_FD_CLR(fd, set) \
|
fprintf(stderr, "Attempt to FD_CLR fd %d, which is not less than "
|
||||||
do { \
|
"FD_SETSIZE (%d). Try using a lower parallelism.",
|
||||||
if ((fd) < FD_SETSIZE) { \
|
fd, FD_SETSIZE);
|
||||||
FD_CLR((fd), (set)); \
|
abort();
|
||||||
} else { \
|
}
|
||||||
fprintf(stderr, "%s:%ld: Attempt to FD_CLR fd %d, which is not less than" \
|
|
||||||
" FD_SETSIZE (%d). Try using a lower parallelism.", \
|
|
||||||
__FILE__, (long int) __LINE__, (fd), FD_SETSIZE); \
|
|
||||||
abort(); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
#endif
|
||||||
|
FD_CLR(fd, fds);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void checked_fd_set(int fd, fd_set *fds) {
|
||||||
|
#ifndef WIN32
|
||||||
|
if (fd >= FD_SETSIZE) {
|
||||||
|
fprintf(stderr, "Attempt to FD_SET fd %d, which is not less than "
|
||||||
|
"FD_SETSIZE (%d). Try using a lower parallelism.",
|
||||||
|
fd, FD_SETSIZE);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
FD_SET(fd, fds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -175,18 +175,18 @@ int select_iod_unregister(mspool *nsp, msiod *iod) {
|
|||||||
if (iod->pcap) {
|
if (iod->pcap) {
|
||||||
int sd = ((mspcap *)iod->pcap)->pcap_desc;
|
int sd = ((mspcap *)iod->pcap)->pcap_desc;
|
||||||
if (sd >= 0) {
|
if (sd >= 0) {
|
||||||
CHECKED_FD_CLR(sd, &sinfo->fds_master_r);
|
checked_fd_clr(sd, &sinfo->fds_master_r);
|
||||||
CHECKED_FD_CLR(sd, &sinfo->fds_results_r);
|
checked_fd_clr(sd, &sinfo->fds_results_r);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CHECKED_FD_CLR(iod->sd, &sinfo->fds_master_r);
|
checked_fd_clr(iod->sd, &sinfo->fds_master_r);
|
||||||
CHECKED_FD_CLR(iod->sd, &sinfo->fds_master_w);
|
checked_fd_clr(iod->sd, &sinfo->fds_master_w);
|
||||||
CHECKED_FD_CLR(iod->sd, &sinfo->fds_master_x);
|
checked_fd_clr(iod->sd, &sinfo->fds_master_x);
|
||||||
CHECKED_FD_CLR(iod->sd, &sinfo->fds_results_r);
|
checked_fd_clr(iod->sd, &sinfo->fds_results_r);
|
||||||
CHECKED_FD_CLR(iod->sd, &sinfo->fds_results_w);
|
checked_fd_clr(iod->sd, &sinfo->fds_results_w);
|
||||||
CHECKED_FD_CLR(iod->sd, &sinfo->fds_results_x);
|
checked_fd_clr(iod->sd, &sinfo->fds_results_x);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sinfo->max_sd == iod->sd)
|
if (sinfo->max_sd == iod->sd)
|
||||||
@@ -210,23 +210,23 @@ int select_iod_modify(mspool *nsp, msiod *iod, int ev_set, int ev_clr) {
|
|||||||
|
|
||||||
/* -- set events -- */
|
/* -- set events -- */
|
||||||
if (ev_set & EV_READ)
|
if (ev_set & EV_READ)
|
||||||
CHECKED_FD_SET(sd, &sinfo->fds_master_r);
|
checked_fd_set(sd, &sinfo->fds_master_r);
|
||||||
|
|
||||||
if (ev_set & EV_WRITE)
|
if (ev_set & EV_WRITE)
|
||||||
CHECKED_FD_SET(sd, &sinfo->fds_master_w);
|
checked_fd_set(sd, &sinfo->fds_master_w);
|
||||||
|
|
||||||
if (ev_set & EV_EXCEPT)
|
if (ev_set & EV_EXCEPT)
|
||||||
CHECKED_FD_SET(sd, &sinfo->fds_master_x);
|
checked_fd_set(sd, &sinfo->fds_master_x);
|
||||||
|
|
||||||
/* -- clear events -- */
|
/* -- clear events -- */
|
||||||
if (ev_clr & EV_READ)
|
if (ev_clr & EV_READ)
|
||||||
CHECKED_FD_CLR(sd, &sinfo->fds_master_r);
|
checked_fd_clr(sd, &sinfo->fds_master_r);
|
||||||
|
|
||||||
if (ev_clr & EV_WRITE)
|
if (ev_clr & EV_WRITE)
|
||||||
CHECKED_FD_CLR(sd, &sinfo->fds_master_w);
|
checked_fd_clr(sd, &sinfo->fds_master_w);
|
||||||
|
|
||||||
if (ev_clr & EV_EXCEPT)
|
if (ev_clr & EV_EXCEPT)
|
||||||
CHECKED_FD_CLR(sd, &sinfo->fds_master_x);
|
checked_fd_clr(sd, &sinfo->fds_master_x);
|
||||||
|
|
||||||
|
|
||||||
/* -- update max_sd -- */
|
/* -- update max_sd -- */
|
||||||
@@ -339,7 +339,7 @@ static inline int get_evmask(const mspool *nsp, const msiod *nsi) {
|
|||||||
#if HAVE_PCAP
|
#if HAVE_PCAP
|
||||||
#ifndef PCAP_CAN_DO_SELECT
|
#ifndef PCAP_CAN_DO_SELECT
|
||||||
if (nsi->pcap) {
|
if (nsi->pcap) {
|
||||||
/* Always assume readable for a non-blocking read. We can't check FD_ISSET
|
/* Always assume readable for a non-blocking read. We can't check checked_fd_isset
|
||||||
because we don't have a pcap_desc. */
|
because we don't have a pcap_desc. */
|
||||||
evmask |= EV_READ;
|
evmask |= EV_READ;
|
||||||
return evmask;
|
return evmask;
|
||||||
@@ -356,11 +356,11 @@ static inline int get_evmask(const mspool *nsp, const msiod *nsi) {
|
|||||||
|
|
||||||
assert(sd >= 0);
|
assert(sd >= 0);
|
||||||
|
|
||||||
if (FD_ISSET(sd, &sinfo->fds_results_r))
|
if (checked_fd_isset(sd, &sinfo->fds_results_r))
|
||||||
evmask |= EV_READ;
|
evmask |= EV_READ;
|
||||||
if (FD_ISSET(sd, &sinfo->fds_results_w))
|
if (checked_fd_isset(sd, &sinfo->fds_results_w))
|
||||||
evmask |= EV_WRITE;
|
evmask |= EV_WRITE;
|
||||||
if (FD_ISSET(sd, &sinfo->fds_results_x))
|
if (checked_fd_isset(sd, &sinfo->fds_results_x))
|
||||||
evmask |= EV_EXCEPT;
|
evmask |= EV_EXCEPT;
|
||||||
|
|
||||||
return evmask;
|
return evmask;
|
||||||
|
|||||||
@@ -1029,10 +1029,10 @@ ConnectScanInfo::~ConnectScanInfo() {}
|
|||||||
watch an SD that was already being watched. */
|
watch an SD that was already being watched. */
|
||||||
bool ConnectScanInfo::watchSD(int sd) {
|
bool ConnectScanInfo::watchSD(int sd) {
|
||||||
assert(sd >= 0);
|
assert(sd >= 0);
|
||||||
if (!FD_ISSET(sd, &fds_read)) {
|
if (!checked_fd_isset(sd, &fds_read)) {
|
||||||
CHECKED_FD_SET(sd, &fds_read);
|
checked_fd_set(sd, &fds_read);
|
||||||
CHECKED_FD_SET(sd, &fds_write);
|
checked_fd_set(sd, &fds_write);
|
||||||
CHECKED_FD_SET(sd, &fds_except);
|
checked_fd_set(sd, &fds_except);
|
||||||
numSDs++;
|
numSDs++;
|
||||||
if (sd > maxValidSD)
|
if (sd > maxValidSD)
|
||||||
maxValidSD = sd;
|
maxValidSD = sd;
|
||||||
@@ -1047,10 +1047,10 @@ bool ConnectScanInfo::watchSD(int sd) {
|
|||||||
there in the first place. */
|
there in the first place. */
|
||||||
bool ConnectScanInfo::clearSD(int sd) {
|
bool ConnectScanInfo::clearSD(int sd) {
|
||||||
assert(sd >= 0);
|
assert(sd >= 0);
|
||||||
if (FD_ISSET(sd, &fds_read)) {
|
if (checked_fd_isset(sd, &fds_read)) {
|
||||||
CHECKED_FD_CLR(sd, &fds_read);
|
checked_fd_clr(sd, &fds_read);
|
||||||
CHECKED_FD_CLR(sd, &fds_write);
|
checked_fd_clr(sd, &fds_write);
|
||||||
CHECKED_FD_CLR(sd, &fds_except);
|
checked_fd_clr(sd, &fds_except);
|
||||||
assert(numSDs > 0);
|
assert(numSDs > 0);
|
||||||
numSDs--;
|
numSDs--;
|
||||||
if (sd == maxValidSD)
|
if (sd == maxValidSD)
|
||||||
@@ -4172,8 +4172,9 @@ static bool do_one_select_round(UltraScanInfo *USI, struct timeval *stime) {
|
|||||||
assert(probe->type == UltraProbe::UP_CONNECT);
|
assert(probe->type == UltraProbe::UP_CONNECT);
|
||||||
sd = probe->CP()->sd;
|
sd = probe->CP()->sd;
|
||||||
/* Let see if anything has happened! */
|
/* Let see if anything has happened! */
|
||||||
if (sd >= 0 && (FD_ISSET(sd, &fds_rtmp) || FD_ISSET(sd, &fds_wtmp) ||
|
if (sd >= 0 && (checked_fd_isset(sd, &fds_rtmp) ||
|
||||||
FD_ISSET(sd, &fds_xtmp))) {
|
checked_fd_isset(sd, &fds_wtmp) ||
|
||||||
|
checked_fd_isset(sd, &fds_xtmp))) {
|
||||||
numGoodSD++;
|
numGoodSD++;
|
||||||
newportstate = PORT_UNKNOWN;
|
newportstate = PORT_UNKNOWN;
|
||||||
if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *) &optval,
|
if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *) &optval,
|
||||||
|
|||||||
Reference in New Issue
Block a user