From: Colm MacCarthaigh Date: Mon, 19 Sep 2005 14:57:07 +0000 (+0000) Subject: Backport r239710, r239711, r239732, r239740 and r241815 to the 2.2.x branch; X-Git-Tag: 2.1.8~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0819080a9cbc5a843087cf3266e6e355d718c511;p=thirdparty%2Fapache%2Fhttpd.git Backport r239710, r239711, r239732, r239740 and r241815 to the 2.2.x branch; Fix PR 28167, which means we stop listening on ports when we do a graceful-restart. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@290179 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index fb733180ae7..f07ddf5806a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.1.8 + *) prefork, worker and event MPMs: Prevent children from holding open + listening ports upon graceful restart or stop. PR 28167. + [Colm MacCarthaigh, Brian Pinkerton ] + *) SECURITY: CAN-2005-2700 (cve.mitre.org) mod_ssl: Fix a security issue where "SSLVerifyClient" was not enforced in per-location context if "SSLVerifyClient optional" diff --git a/include/ap_listen.h b/include/ap_listen.h index d98949f3792..6182a8917d9 100644 --- a/include/ap_listen.h +++ b/include/ap_listen.h @@ -77,6 +77,11 @@ AP_DECLARE(void) ap_listen_pre_config(void); */ AP_DECLARE(int) ap_setup_listeners(server_rec *s); +/** + * Loop through the global ap_listen_rec list and close each of the sockets. + */ +AP_DECLARE_NONSTD(void) ap_close_listeners(void); + /* Although these functions are exported from libmain, they are not really * public functions. These functions are actually called while parsing the * config file, when one of the LISTEN_COMMANDS directives is read. These diff --git a/modules/generators/mod_cgid.c b/modules/generators/mod_cgid.c index 1299f4c45da..110e4a49d91 100644 --- a/modules/generators/mod_cgid.c +++ b/modules/generators/mod_cgid.c @@ -566,6 +566,9 @@ static int cgid_server(void *data) apr_signal(SIGCHLD, SIG_IGN); apr_signal(SIGHUP, daemon_signal_handler); + /* Close our copy of the listening sockets */ + ap_close_listeners(); + /* cgid should use its own suexec doer */ ap_hook_get_suexec_identity(cgid_suexec_id_doer, NULL, NULL, APR_HOOK_REALLY_FIRST); diff --git a/server/listen.c b/server/listen.c index 6d557430690..f95e0f61107 100644 --- a/server/listen.c +++ b/server/listen.c @@ -237,17 +237,10 @@ static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis, static apr_status_t close_listeners_on_exec(void *v) { - ap_listen_rec *lr; - - for (lr = ap_listeners; lr; lr = lr->next) { - apr_socket_close(lr->sd); - lr->active = 0; - } - + ap_close_listeners(); return APR_SUCCESS; } - static const char *alloc_listener(process_rec *process, char *addr, apr_port_t port, const char* proto) { @@ -568,6 +561,15 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s) return num_listeners; } +AP_DECLARE_NONSTD(void) ap_close_listeners(void) { + ap_listen_rec *lr; + + for (lr = ap_listeners; lr; lr = lr->next) { + apr_socket_close(lr->sd); + lr->active = 0; + } +} + AP_DECLARE(void) ap_listen_pre_config(void) { old_listeners = ap_listeners; diff --git a/server/mpm/experimental/event/event.c b/server/mpm/experimental/event/event.c index 45d8458290f..299cdf856f9 100644 --- a/server/mpm/experimental/event/event.c +++ b/server/mpm/experimental/event/event.c @@ -1036,6 +1036,7 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) } /* listener main loop */ + ap_close_listeners(); ap_queue_term(worker_queue); dying = 1; ap_scoreboard_image->parent[process_slot].quiescing = 1; diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index 8776f32616e..41a54866b31 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -328,6 +328,11 @@ static void just_die(int sig) clean_child_exit(0); } +static void stop_listening(int sig) +{ + ap_close_listeners(); +} + /* volatile just in case */ static int volatile shutdown_pending; static int volatile restart_pending; @@ -712,10 +717,10 @@ static int make_child(server_rec *s, int slot) */ apr_signal(SIGHUP, just_die); apr_signal(SIGTERM, just_die); - /* The child process doesn't do anything for AP_SIG_GRACEFUL. - * Instead, the pod is used for signalling graceful restart. + /* The child process just closes listeners on AP_SIG_GRACEFUL. + * The pod is used for signalling graceful restart. */ - apr_signal(AP_SIG_GRACEFUL, SIG_IGN); + apr_signal(AP_SIG_GRACEFUL, stop_listening); child_main(slot); } @@ -1093,6 +1098,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* we've been told to restart */ apr_signal(SIGHUP, SIG_IGN); + apr_signal(AP_SIG_GRACEFUL, SIG_IGN); if (one_process) { /* not worth thinking about */ return 1; @@ -1120,6 +1126,14 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) for (index = 0; index < ap_daemons_limit; ++index) { if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL; + /* Ask each child to close its listeners. + * + * NOTE: we use the scoreboard, because if we send SIGUSR1 + * to every process in the group, this may include CGI's, + * piped loggers, etc. They almost certainly won't handle + * it gracefully. + */ + kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); } } } diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index 1380ee23b52..904ef4a9028 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -775,6 +775,7 @@ static void *listener_thread(apr_thread_t *thd, void * dummy) } } + ap_close_listeners(); ap_queue_term(worker_queue); dying = 1; ap_scoreboard_image->parent[process_slot].quiescing = 1;