mirror of
https://github.com/nmap/nmap.git
synced 2026-05-13 08:46:45 +00:00
Handle immediate callback before thread yields
Nsock makes no guarantees that it will not call the callback for various functions before returning, so we have to check for that and not assert it. Fixes #3250. Fixes #3206.
This commit is contained in:
parent
36e2bf126d
commit
9458beda4c
2 changed files with 46 additions and 17 deletions
|
|
@ -1,5 +1,9 @@
|
|||
#Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE][GH#3250][GH#3206] Fix assertion failures in cases where connect or send
|
||||
returns immediately with a status other than ERROR, e.g. TIMEOUT or CANCELED.
|
||||
[Daniel Miller]
|
||||
|
||||
o Fix a crash when writing long CPE strings to output. Reported by Harshit
|
||||
Gupta. [Daniel Miller]
|
||||
|
||||
|
|
|
|||
59
nse_nsock.cc
59
nse_nsock.cc
|
|
@ -359,15 +359,23 @@ static void callback (nsock_pool nsp, nsock_event nse, void *ud)
|
|||
if (nse_status(nse) == NSE_STATUS_KILL)
|
||||
return;
|
||||
assert(nse_type(nse) != NSE_TYPE_READ);
|
||||
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. We'll use nu->action to signal
|
||||
// l_connect to return an error instead of yielding.
|
||||
// http://seclists.org/nmap-dev/2016/q1/201
|
||||
trace(nse_iod(nse), nu->action, nu->direction);
|
||||
trace(nse_iod(nse), nu->action, nu->direction);
|
||||
|
||||
if (lua_status(L) == LUA_OK) {
|
||||
// Sometimes an operation finishes immediately and Nsock calls the callback
|
||||
// before the caller has a chance to yield. We'll use nu->action to signal
|
||||
// the caller to return instead of yielding.
|
||||
nu->action = NU_ACTION_IMMEDIATE;
|
||||
if (nse_status(nse) == NSE_STATUS_SUCCESS) {
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, false);
|
||||
lua_pushstring(L, nse_status2str(nse_status(nse)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
assert(lua_status(L) == LUA_YIELD);
|
||||
switch (nse_type(nse)) {
|
||||
case NSE_TYPE_CONNECT:
|
||||
case NSE_TYPE_CONNECT_SSL:
|
||||
|
|
@ -378,8 +386,6 @@ static void callback (nsock_pool nsp, nsock_event nse, void *ud)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
assert(lua_status(L) == LUA_YIELD);
|
||||
trace(nse_iod(nse), nu->action, nu->direction);
|
||||
status(L, nse_status(nse));
|
||||
}
|
||||
|
||||
|
|
@ -468,9 +474,15 @@ static int l_reconnect_ssl (lua_State *L)
|
|||
return nseU_safeerror(L, "sorry, you don't have OpenSSL");
|
||||
#endif
|
||||
|
||||
int oldtop = lua_gettop(L);
|
||||
nu->action = "SSL RECONNECT";
|
||||
nsock_reconnect_ssl(nsp, nu->nsiod, callback, nu->timeout,
|
||||
nu, nu->ssl_session);
|
||||
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
// Immediate return
|
||||
return lua_gettop(L) - oldtop;
|
||||
}
|
||||
return yield(L, nu, "SSL RECONNECT", TO, 0, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -553,6 +565,7 @@ static int connect (lua_State *L, int status, lua_KContext ctx)
|
|||
nu->action = "PRECONNECT";
|
||||
nu->direction = TO;
|
||||
|
||||
int oldtop = lua_gettop(L);
|
||||
switch (what)
|
||||
{
|
||||
case TCP:
|
||||
|
|
@ -579,8 +592,8 @@ static int connect (lua_State *L, int status, lua_KContext ctx)
|
|||
freeaddrinfo(dest);
|
||||
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
// Immediate error
|
||||
return nseU_safeerror(L, nse_status2str(NSE_STATUS_ERROR));
|
||||
// Immediate return
|
||||
return lua_gettop(L) - oldtop;
|
||||
}
|
||||
return yield(L, nu, "CONNECT", TO, 0, NULL);
|
||||
}
|
||||
|
|
@ -598,10 +611,12 @@ static int l_send (lua_State *L)
|
|||
size_t size;
|
||||
const char *string = luaL_checklstring(L, 2, &size);
|
||||
trace(nu->nsiod, hexify((unsigned char *) string, size).c_str(), TO);
|
||||
int oldtop = lua_gettop(L);
|
||||
nu->action = "SEND";
|
||||
nsock_write(nsp, nu->nsiod, callback, nu->timeout, nu, string, size);
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
// Immediate error
|
||||
return nseU_safeerror(L, nse_status2str(NSE_STATUS_ERROR));
|
||||
// Immediate return
|
||||
return lua_gettop(L) - oldtop;
|
||||
}
|
||||
return yield(L, nu, "SEND", TO, 0, NULL);
|
||||
}
|
||||
|
|
@ -626,9 +641,15 @@ static int l_sendto (lua_State *L)
|
|||
if (dest == NULL)
|
||||
return nseU_safeerror(L, "getaddrinfo returned success but no addresses");
|
||||
|
||||
nsock_sendto(nsp, nu->nsiod, callback, nu->timeout, nu, dest->ai_addr, dest->ai_addrlen, port, string, size);
|
||||
trace(nu->nsiod, hexify((unsigned char *) string, size).c_str(), TO);
|
||||
int oldtop = lua_gettop(L);
|
||||
nu->action = "SENDTO";
|
||||
nsock_sendto(nsp, nu->nsiod, callback, nu->timeout, nu, dest->ai_addr, dest->ai_addrlen, port, string, size);
|
||||
freeaddrinfo(dest);
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
// Immediate return
|
||||
return lua_gettop(L) - oldtop;
|
||||
}
|
||||
return yield(L, nu, "SEND", TO, 0, NULL);
|
||||
|
||||
}
|
||||
|
|
@ -652,11 +673,11 @@ static void receive_callback (nsock_pool nsp, nsock_event nse, void *udata)
|
|||
nu->action = NU_ACTION_IMMEDIATE;
|
||||
return;
|
||||
}
|
||||
else if (lua_status(L) == LUA_OK && nse_status(nse) == NSE_STATUS_EOF) {
|
||||
else if (lua_status(L) == LUA_OK) {
|
||||
// since r39028, read event can fail immediately if the socket is EOF.
|
||||
trace(nse_iod(nse), nu->action, "EOF");
|
||||
lua_pushnil(L);
|
||||
lua_pushliteral(L, "EOF");
|
||||
trace(nse_iod(nse), nse_status2str(nse_status(nse)), FROM);
|
||||
lua_pushboolean(L, false);
|
||||
lua_pushstring(L, nse_status2str(nse_status(nse)));
|
||||
nu->action = NU_ACTION_IMMEDIATE;
|
||||
return;
|
||||
}
|
||||
|
|
@ -670,6 +691,7 @@ static int l_receive (lua_State *L)
|
|||
nse_nsock_udata *nu = check_nsock_udata(L, 1, true);
|
||||
NSOCK_UDATA_ENSURE_OPEN(L, nu);
|
||||
int oldtop = lua_gettop(L);
|
||||
nu->action = "RECEIVE";
|
||||
nsock_read(nsp, nu->nsiod, receive_callback, nu->timeout, nu);
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
// Immediate return
|
||||
|
|
@ -684,6 +706,7 @@ static int l_receive_lines (lua_State *L)
|
|||
nse_nsock_udata *nu = check_nsock_udata(L, 1, true);
|
||||
NSOCK_UDATA_ENSURE_OPEN(L, nu);
|
||||
int oldtop = lua_gettop(L);
|
||||
nu->action = "RECEIVE LINES";
|
||||
nsock_readlines(nsp, nu->nsiod, receive_callback, nu->timeout, nu,
|
||||
luaL_checkinteger(L, 2));
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
|
|
@ -699,6 +722,7 @@ static int l_receive_bytes (lua_State *L)
|
|||
nse_nsock_udata *nu = check_nsock_udata(L, 1, true);
|
||||
NSOCK_UDATA_ENSURE_OPEN(L, nu);
|
||||
int oldtop = lua_gettop(L);
|
||||
nu->action = "RECEIVE BYTES";
|
||||
nsock_readbytes(nsp, nu->nsiod, receive_callback, nu->timeout, nu,
|
||||
luaL_checkinteger(L, 2));
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
|
|
@ -769,6 +793,7 @@ static int receive_buf (lua_State *L, int status, lua_KContext ctx)
|
|||
{
|
||||
lua_pop(L, 2); /* pop 2 results */
|
||||
int oldtop = lua_gettop(L);
|
||||
nu->action = "RECEIVE BUF";
|
||||
nsock_read(nsp, nu->nsiod, receive_callback, nu->timeout, nu);
|
||||
if (nu->action == NU_ACTION_IMMEDIATE) {
|
||||
// Immediate return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue