[nmap/f20] fix unexpected crash when too much paralelism is used (#1057912)

Michal Hlavinka mhlavink at fedoraproject.org
Wed Apr 9 15:37:18 UTC 2014


commit d53527ee91059955ea05a524d12f761d58b58502
Author: Michal Hlavinka <mhlavink at redhat.com>
Date:   Wed Apr 9 17:37:07 2014 +0200

    fix unexpected crash when too much paralelism is used (#1057912)

 nmap-6.40-fdsafe.patch |  202 ++++++++++++++++++++++++++++++++++++++++++++++++
 nmap.spec              |    7 ++-
 2 files changed, 208 insertions(+), 1 deletions(-)
---
diff --git a/nmap-6.40-fdsafe.patch b/nmap-6.40-fdsafe.patch
new file mode 100644
index 0000000..be30ab9
--- /dev/null
+++ b/nmap-6.40-fdsafe.patch
@@ -0,0 +1,202 @@
+diff -up nmap-6.40/nbase/nbase.h.fdsafe nmap-6.40/nbase/nbase.h
+--- nmap-6.40/nbase/nbase.h.fdsafe	2013-07-29 00:08:48.000000000 +0200
++++ nmap-6.40/nbase/nbase.h	2014-04-09 17:30:19.579033118 +0200
+@@ -369,37 +369,41 @@ extern "C" int vsnprintf (char *, size_t
+ #endif
+ 
+ 
+-#ifdef WIN32
+-#define CHECKED_FD_SET FD_SET
+-#else
+-#define CHECKED_FD_SET(fd, set) \
+-  do { \
+-    if ((fd) < FD_SETSIZE) { \
+-      FD_SET((fd), (set)); \
+-    } 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)
++static inline int checked_fd_isset(int fd, const fd_set *fds) {
++#ifndef WIN32
++  if (fd >= FD_SETSIZE) {
++    fprintf(stderr, "Attempt to FD_ISSET fd %d, which is not less than "
++                    "FD_SETSIZE (%d). Try using a lower parallelism.",
++                    fd, FD_SETSIZE);
++    abort();
++  }
+ #endif
++  return FD_ISSET(fd, fds);
++}
+ 
+-#ifdef WIN32
+-#define CHECKED_FD_CLR FD_CLR
+-#else
+-#define CHECKED_FD_CLR(fd, set) \
+-  do { \
+-    if ((fd) < FD_SETSIZE) { \
+-      FD_CLR((fd), (set)); \
+-    } 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)
++static inline void checked_fd_clr(int fd, fd_set *fds) {
++#ifndef WIN32
++  if (fd >= FD_SETSIZE) {
++    fprintf(stderr, "Attempt to FD_CLR fd %d, which is not less than "
++                    "FD_SETSIZE (%d). Try using a lower parallelism.",
++                    fd, FD_SETSIZE);
++    abort();
++  }
+ #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
+diff -up nmap-6.40/nsock/src/engine_select.c.fdsafe nmap-6.40/nsock/src/engine_select.c
+--- nmap-6.40/nsock/src/engine_select.c.fdsafe	2013-07-29 00:08:48.000000000 +0200
++++ nmap-6.40/nsock/src/engine_select.c	2014-04-09 17:30:19.579033118 +0200
+@@ -174,18 +174,18 @@ int select_iod_unregister(mspool *nsp, m
+     if (iod->pcap) {
+       int sd = ((mspcap *)iod->pcap)->pcap_desc;
+       if (sd >= 0) {
+-        CHECKED_FD_CLR(sd, &sinfo->fds_master_r);
+-        CHECKED_FD_CLR(sd, &sinfo->fds_results_r);
++        checked_fd_clr(sd, &sinfo->fds_master_r);
++        checked_fd_clr(sd, &sinfo->fds_results_r);
+       }
+     } else
+ #endif
+     {
+-      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_x);
+-      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_x);
++      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_x);
++      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_x);
+     }
+ 
+     if (sinfo->max_sd == iod->sd)
+@@ -209,23 +209,23 @@ int select_iod_modify(mspool *nsp, msiod
+ 
+   /* -- set events -- */
+   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)
+-    CHECKED_FD_SET(sd, &sinfo->fds_master_w);
++    checked_fd_set(sd, &sinfo->fds_master_w);
+ 
+   if (ev_set & EV_EXCEPT)
+-    CHECKED_FD_SET(sd, &sinfo->fds_master_x);
++    checked_fd_set(sd, &sinfo->fds_master_x);
+ 
+   /* -- clear events -- */
+   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)
+-    CHECKED_FD_CLR(sd, &sinfo->fds_master_w);
++    checked_fd_clr(sd, &sinfo->fds_master_w);
+ 
+   if (ev_clr & EV_EXCEPT)
+-    CHECKED_FD_CLR(sd, &sinfo->fds_master_x);
++    checked_fd_clr(sd, &sinfo->fds_master_x);
+ 
+ 
+   /* -- update max_sd -- */
+@@ -335,7 +335,7 @@ static inline int get_evmask(const mspoo
+ #if HAVE_PCAP
+ #ifndef PCAP_CAN_DO_SELECT
+   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. */
+     evmask |= EV_READ;
+     return evmask;
+@@ -352,11 +352,11 @@ static inline int get_evmask(const mspoo
+ 
+   assert(sd >= 0);
+ 
+-  if (FD_ISSET(sd, &sinfo->fds_results_r))
++  if (checked_fd_isset(sd, &sinfo->fds_results_r))
+     evmask |= EV_READ;
+-  if (FD_ISSET(sd, &sinfo->fds_results_w))
++  if (checked_fd_isset(sd, &sinfo->fds_results_w))
+     evmask |= EV_WRITE;
+-  if (FD_ISSET(sd, &sinfo->fds_results_x))
++  if (checked_fd_isset(sd, &sinfo->fds_results_x))
+     evmask |= EV_EXCEPT;
+ 
+   return evmask;
+diff -up nmap-6.40/scan_engine.cc.fdsafe nmap-6.40/scan_engine.cc
+--- nmap-6.40/scan_engine.cc.fdsafe	2013-07-29 00:08:48.000000000 +0200
++++ nmap-6.40/scan_engine.cc	2014-04-09 17:30:19.580033127 +0200
+@@ -1006,10 +1006,10 @@ ConnectScanInfo::~ConnectScanInfo() {}
+    watch an SD that was already being watched. */
+ bool ConnectScanInfo::watchSD(int sd) {
+   assert(sd >= 0);
+-  if (!FD_ISSET(sd, &fds_read)) {
+-    CHECKED_FD_SET(sd, &fds_read);
+-    CHECKED_FD_SET(sd, &fds_write);
+-    CHECKED_FD_SET(sd, &fds_except);
++  if (!checked_fd_isset(sd, &fds_read)) {
++    checked_fd_set(sd, &fds_read);
++    checked_fd_set(sd, &fds_write);
++    checked_fd_set(sd, &fds_except);
+     numSDs++;
+     if (sd > maxValidSD)
+       maxValidSD = sd;
+@@ -1024,10 +1024,10 @@ bool ConnectScanInfo::watchSD(int sd) {
+    there in the first place. */
+ bool ConnectScanInfo::clearSD(int sd) {
+   assert(sd >= 0);
+-  if (FD_ISSET(sd, &fds_read)) {
+-    CHECKED_FD_CLR(sd, &fds_read);
+-    CHECKED_FD_CLR(sd, &fds_write);
+-    CHECKED_FD_CLR(sd, &fds_except);
++  if (checked_fd_isset(sd, &fds_read)) {
++    checked_fd_clr(sd, &fds_read);
++    checked_fd_clr(sd, &fds_write);
++    checked_fd_clr(sd, &fds_except);
+     assert(numSDs > 0);
+     numSDs--;
+     if (sd == maxValidSD)
+@@ -4096,8 +4096,9 @@ static bool do_one_select_round(UltraSca
+       assert(probe->type == UltraProbe::UP_CONNECT);
+       sd = probe->CP()->sd;
+       /* Let see if anything has happened! */
+-      if (sd >= 0 && (FD_ISSET(sd, &fds_rtmp)  || FD_ISSET(sd, &fds_wtmp) ||
+-                      FD_ISSET(sd, &fds_xtmp))) {
++      if (sd >= 0 && (checked_fd_isset(sd, &fds_rtmp) ||
++                      checked_fd_isset(sd, &fds_wtmp) ||
++                      checked_fd_isset(sd, &fds_xtmp))) {
+         numGoodSD++;
+         newportstate = PORT_UNKNOWN;
+         if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *) &optval,
diff --git a/nmap.spec b/nmap.spec
index 3d05f9a..addfcd0 100644
--- a/nmap.spec
+++ b/nmap.spec
@@ -4,7 +4,7 @@ Name: nmap
 Epoch: 2
 Version: 6.40
 #global prerelease TEST5
-Release: 3%{?dist}
+Release: 4%{?dist}
 # nmap is GPLv2
 # zenmap is GPLv2 and LGPLv2+ (zenmap/higwidgets) and GPLv2+ (zenmap/radialnet)
 # libdnet-stripped is BSD (advertising clause rescinded by the Univ. of California in 1999) with some parts as Public Domain (crc32)
@@ -33,6 +33,7 @@ Patch6: nmap-6.25-displayerror.patch
 
 #rhbz#994376
 Patch7: nmap-6.40-logdebug.patch
+Patch8: nmap-6.40-fdsafe.patch
 
 URL: http://nmap.org/
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -87,6 +88,7 @@ uses.
 %patch5 -p1 -b .ncat_reg_stdin
 %patch6 -p1 -b .displayerror
 %patch7 -p1 -b .logdebug
+%patch8 -p1 -b .fdsafe
 
 # for aarch64 support, not needed with autotools 2.69+
 for f in acinclude.m4 configure.ac nping/configure.ac
@@ -220,6 +222,9 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man1/xnmap.1.gz
 
 %changelog
+* Wed Apr 09 2014 Michal Hlavinka <mhlavink at redhat.com> - 2:6.40-4
+- fix unexpected crash when too much paralelism is used (#1057912)
+
 * Thu Oct 17 2013 Michal Hlavinka <mhlavink at redhat.com> - 2:6.40-3
 - ncat should support UNIX sockets correctly, drop wrapper with socat
 


More information about the scm-commits mailing list