From 3fadc493c915cd1c8078cfd1c3e5fa9e6003a8f5 Mon Sep 17 00:00:00 2001 From: Ruediger Pluem Date: Sun, 16 Aug 2009 20:29:47 +0000 Subject: [PATCH] * Do better checking of pollset operations in various places to avoid segfaults. PR: 46467 Submitted by: Stefan Fritsch Reviewed by: rpluem git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@804764 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ modules/generators/mod_cgi.c | 20 +++++++++++++++++--- modules/proxy/mod_proxy_connect.c | 19 ++++++++++++++++--- server/mpm/event/event.c | 3 ++- server/mpm/prefork/prefork.c | 8 ++++++-- server/mpm/worker/worker.c | 20 ++++++++++++++++---- 6 files changed, 61 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 0bbcd38acc..6c96a6be4d 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.3.3 + *) Various modules: Do better checking of pollset operations in order to + avoid segmentation faults if they fail. PR 46467 + [Stefan Fritsch ] + *) mod_autoindex: Correctly create an empty cell if the description for a file is missing. PR 47682 [Peter Poeml ] diff --git a/modules/generators/mod_cgi.c b/modules/generators/mod_cgi.c index 1d4a16370e..359b3baa89 100644 --- a/modules/generators/mod_cgi.c +++ b/modules/generators/mod_cgi.c @@ -580,7 +580,11 @@ static apr_bucket *cgi_bucket_create(request_rec *r, /* Create the pollset */ rv = apr_pollset_create(&data->pollset, 2, r->pool, 0); - AP_DEBUG_ASSERT(rv == APR_SUCCESS); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "cgi: apr_pollset_create(); check system or user limits"); + return NULL; + } fd.desc_type = APR_POLL_FILE; fd.reqevents = APR_POLLIN; @@ -588,12 +592,20 @@ static apr_bucket *cgi_bucket_create(request_rec *r, fd.desc.f = out; /* script's stdout */ fd.client_data = (void *)1; rv = apr_pollset_add(data->pollset, &fd); - AP_DEBUG_ASSERT(rv == APR_SUCCESS); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "cgi: apr_pollset_add(); check system or user limits"); + return NULL; + } fd.desc.f = err; /* script's stderr */ fd.client_data = (void *)2; rv = apr_pollset_add(data->pollset, &fd); - AP_DEBUG_ASSERT(rv == APR_SUCCESS); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "cgi: apr_pollset_add(); check system or user limits"); + return NULL; + } data->r = r; b->data = data; @@ -908,6 +920,8 @@ static int cgi_handler(request_rec *r) apr_file_pipe_timeout_set(script_err, 0); b = cgi_bucket_create(r, script_in, script_err, c->bucket_alloc); + if (b == NULL) + return HTTP_INTERNAL_SERVER_ERROR; #else b = apr_bucket_pipe_create(script_in, c->bucket_alloc); #endif diff --git a/modules/proxy/mod_proxy_connect.c b/modules/proxy/mod_proxy_connect.c index fdadc565e6..8f55e911f3 100644 --- a/modules/proxy/mod_proxy_connect.c +++ b/modules/proxy/mod_proxy_connect.c @@ -268,7 +268,8 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) { apr_socket_close(sock); ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "proxy: CONNECT: error apr_pollset_create()"); + "proxy: CONNECT: error apr_pollset_create();" + " check system or user limits"); return HTTP_INTERNAL_SERVER_ERROR; } @@ -278,11 +279,23 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, pollfd.reqevents = APR_POLLIN; pollfd.desc.s = client_socket; pollfd.client_data = NULL; - apr_pollset_add(pollset, &pollfd); + rv = apr_pollset_add(pollset, &pollfd); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: CONNECT: error apr_pollset_add();" + " check system or user limits"); + return HTTP_INTERNAL_SERVER_ERROR; + } /* Add the server side to the poll */ pollfd.desc.s = sock; - apr_pollset_add(pollset, &pollfd); + rv = apr_pollset_add(pollset, &pollfd); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: CONNECT: error apr_pollset_add();" + " check system or user limits"); + return HTTP_INTERNAL_SERVER_ERROR; + } while (1) { /* Infinite loop until error (one side closes the connection) */ if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) != APR_SUCCESS) { diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index 630121adbc..cb5c9427a5 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -2444,7 +2444,8 @@ static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog, if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, "Couldn't create a Thread Safe Pollset. " - "Is it supported on your platform?"); + "Is it supported on your platform?" + "Also check system or user limits!"); return HTTP_INTERNAL_SERVER_ERROR; } apr_pollset_destroy(event_pollset); diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index d1559c7997..9b30635fc8 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -521,8 +521,12 @@ static void child_main(int child_num_arg) pfd.reqevents = APR_POLLIN; pfd.client_data = lr; - /* ### check the status */ - (void) apr_pollset_add(pollset, &pfd); + status = apr_pollset_add(pollset, &pfd); + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, + "Couldn't add listener to pollset; check system or user limits"); + clean_child_exit(APEXIT_CHILDSICK); + } lr->accept_func = ap_unixd_accept; } diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index a5994d0c2d..d1ae528254 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -610,8 +610,14 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy) free(ti); - /* ### check the status */ - (void) apr_pollset_create(&pollset, num_listensocks, tpool, 0); + rv = apr_pollset_create(&pollset, num_listensocks, tpool, 0); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, + "Couldn't create pollset in thread;" + " check system or user limits"); + /* let the parent decide how bad this really is */ + clean_child_exit(APEXIT_CHILDSICK); + } for (lr = ap_listeners; lr != NULL; lr = lr->next) { apr_pollfd_t pfd = { 0 }; @@ -621,8 +627,14 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy) pfd.reqevents = APR_POLLIN; pfd.client_data = lr; - /* ### check the status */ - (void) apr_pollset_add(pollset, &pfd); + rv = apr_pollset_add(pollset, &pfd); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, + "Couldn't create add listener to pollset;" + " check system or user limits"); + /* let the parent decide how bad this really is */ + clean_child_exit(APEXIT_CHILDSICK); + } lr->accept_func = ap_unixd_accept; } -- 2.40.0