From f74326e6e105415d93c55a3ca43a2166320dac28 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 17 Feb 2019 10:46:30 +0800 Subject: [PATCH] cgi: fix stdin cgiwsi leak when closed early --- lib/core-net/close.c | 16 ++++++++++------ lib/core-net/dummy-callback.c | 5 +++-- lib/roles/cgi/cgi-server.c | 17 ++++++++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 584e574e0..5cf8296b2 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -200,10 +200,13 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, #ifdef LWS_WITH_CGI if (wsi->role_ops == &role_ops_cgi) { + + // lwsl_debug("%s: closing stdwsi index %d\n", __func__, (int)wsi->cgi_channel); + /* we are not a network connection, but a handler for CGI io */ if (wsi->parent && wsi->parent->http.cgi) { - if (wsi->cgi_channel == LWS_STDOUT) + if (wsi->parent->child_list == wsi && !wsi->sibling_list) lws_cgi_remove_and_kill(wsi->parent); /* end the binding between us and master */ @@ -414,9 +417,8 @@ just_kill_connection: __lws_remove_from_timeout_list(wsi); lws_dll_lws_remove(&wsi->dll_hrtimer); - /* don't repeat event loop stuff */ - if (wsi->told_event_loop_closed) - return; + //if (wsi->told_event_loop_closed) // cgi std close case (dummy-callback) + // return; /* checking return redundant since we anyway close */ if (wsi->desc.sockfd != LWS_SOCK_INVALID) @@ -493,11 +495,13 @@ __lws_close_free_wsi_final(struct lws *wsi) if (wsi->http.cgi->pipe_fds[n][!!(n == 0)] == 0) lwsl_err("ZERO FD IN CGI CLOSE"); - if (wsi->http.cgi->pipe_fds[n][!!(n == 0)] >= 0) + if (wsi->http.cgi->pipe_fds[n][!!(n == 0)] >= 0) { close(wsi->http.cgi->pipe_fds[n][!!(n == 0)]); + wsi->http.cgi->pipe_fds[n][!!(n == 0)] = LWS_SOCK_INVALID; + } } - lws_free(wsi->http.cgi); + lws_free_set_NULL(wsi->http.cgi); } #endif diff --git a/lib/core-net/dummy-callback.c b/lib/core-net/dummy-callback.c index 5dd384953..e66395361 100644 --- a/lib/core-net/dummy-callback.c +++ b/lib/core-net/dummy-callback.c @@ -575,9 +575,10 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, __remove_wsi_socket_from_fds(siwsi); lwsi_set_state(siwsi, LRS_DEAD_SOCKET); siwsi->socket_is_permanently_unusable = 1; - lws_remove_child_from_any_parent(siwsi); +// lws_remove_child_from_any_parent(siwsi); if (wsi->context->event_loop_ops-> close_handle_manually) { + wsi->context->event_loop_ops-> close_handle_manually(siwsi); siwsi->told_event_loop_closed = 1; @@ -587,7 +588,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, } wsi->http.cgi->pipe_fds[LWS_STDIN][1] = -1; - args->stdwsi[LWS_STDIN] = NULL; +// args->stdwsi[LWS_STDIN] = NULL; } } diff --git a/lib/roles/cgi/cgi-server.c b/lib/roles/cgi/cgi-server.c index e2d0437e8..382b3c1fe 100644 --- a/lib/roles/cgi/cgi-server.c +++ b/lib/roles/cgi/cgi-server.c @@ -135,6 +135,11 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, sum = cgi->summary; sumend = sum + strlen(cgi->summary) - 1; + for (n = 0; n < 3; n++) { + cgi->pipe_fds[n][0] = -1; + cgi->pipe_fds[n][1] = -1; + } + /* create pipes for [stdin|stdout] and [stderr] */ for (n = 0; n < 3; n++) @@ -145,12 +150,14 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, for (n = 0; n < 3; n++) { cgi->stdwsi[n] = lws_create_basic_wsi(wsi->context, wsi->tsi); - if (!cgi->stdwsi[n]) + if (!cgi->stdwsi[n]) { + lwsl_err("%s: unable to create cgi stdwsi\n", __func__); goto bail2; + } cgi->stdwsi[n]->cgi_channel = n; lws_vhost_bind_wsi(wsi->vhost, cgi->stdwsi[n]); - lwsl_debug("%s: cgi %p: pipe fd %d -> fd %d / %d\n", __func__, + lwsl_debug("%s: cgi stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__, cgi->stdwsi[n], n, cgi->pipe_fds[n][!!(n == 0)], cgi->pipe_fds[n][!(n == 0)]); @@ -504,14 +511,14 @@ bail3: __remove_wsi_socket_from_fds(wsi->http.cgi->stdwsi[n]); bail2: for (n = 0; n < 3; n++) - if (wsi->http.cgi->stdwsi[n] > 0) + if (wsi->http.cgi->stdwsi[n]) __lws_free_wsi(cgi->stdwsi[n]); bail1: for (n = 0; n < 3; n++) { - if (cgi->pipe_fds[n][0] > 0) + if (cgi->pipe_fds[n][0] >= 0) close(cgi->pipe_fds[n][0]); - if (cgi->pipe_fds[n][1] > 0) + if (cgi->pipe_fds[n][1] >= 0) close(cgi->pipe_fds[n][1]); }