From 0577e3bb1e7dd97f52e089f580f844288a974393 Mon Sep 17 00:00:00 2001 From: dmiller Date: Fri, 4 Mar 2016 23:04:01 +0000 Subject: [PATCH] Avoid crashing when Nsock connect calls the callback immediately due to parameter errors --- nse_nsock.cc | 12 ++++++++++++ service_scan.cc | 13 +++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/nse_nsock.cc b/nse_nsock.cc index 15396db73..717ab54e6 100644 --- a/nse_nsock.cc +++ b/nse_nsock.cc @@ -350,6 +350,15 @@ static void callback (nsock_pool nsp, nsock_event nse, void *ud) { nse_nsock_udata *nu = (nse_nsock_udata *) ud; lua_State *L = nu->thread; + if (lua_status(L) == LUA_OK && nse_status(nse) == NSE_STATUS_ERROR) { + // Sometimes Nsock fails immediately and callback is called before + // l_connect has a chance to yield. TODO: Figure out how to return an error + // to the calling thread without falling into an infinite loop somewhere. + // http://seclists.org/nmap-dev/2016/q1/201 + trace(nse_iod(nse), nu->action, nu->direction); + nsock_iod_delete(nu->nsiod, NSOCK_PENDING_NOTIFY); + luaL_error(L, "Nsock immediate error"); + } assert(lua_status(L) == LUA_YIELD); trace(nse_iod(nse), nu->action, nu->direction); status(L, nse_status(nse)); @@ -515,6 +524,9 @@ static int l_connect (lua_State *L) } nu->af = dest->ai_addr->sa_family; + nu->thread = L; + nu->action = "PRECONNECT"; + nu->direction = TO; switch (what) { diff --git a/service_scan.cc b/service_scan.cc index 4c1807081..734d140a6 100644 --- a/service_scan.cc +++ b/service_scan.cc @@ -2261,10 +2261,15 @@ static int launchSomeServiceProbes(nsock_pool nsp, ServiceGroup *SG) { svc, (struct sockaddr *) &ss, ss_len, svc->portno); } - // Now remove it from the remaining service list - SG->services_remaining.pop_front(); - // And add it to the in progress list - SG->services_in_progress.push_back(svc); + // Check that the service is still where we left it. + // servicescan_connect_handler can call end_svcprobe before this point, + // putting it into services_finished already. + if (SG->services_remaining.front() == svc) { + // Now remove it from the remaining service list + SG->services_remaining.pop_front(); + // And add it to the in progress list + SG->services_in_progress.push_back(svc); + } } return 0; }