From: Stefan Fritsch Date: Mon, 7 Nov 2011 18:46:47 +0000 (+0000) Subject: Call apr_random_after_fork() manually in the child processes because the MPMs X-Git-Tag: 2.3.15~45 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c5a4c2bc9abf7d4dc1f329842cdb8d47c05862e;p=apache Call apr_random_after_fork() manually in the child processes because the MPMs use plain fork() and not apr_proc_fork(). Also add some workaround for APR not changing the RNG state in the parent. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1198868 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/mod_core.h b/include/mod_core.h index 58f3c93dcb..8e822d9b20 100644 --- a/include/mod_core.h +++ b/include/mod_core.h @@ -90,6 +90,9 @@ AP_DECLARE(int) ap_send_http_options(request_rec *r); /* Used for multipart/byteranges boundary string */ extern AP_DECLARE_DATA const char *ap_multipart_boundary; +/* Update RNG state in parent after fork */ +AP_CORE_DECLARE(void) ap_random_parent_after_fork(void); + #ifdef __cplusplus } #endif diff --git a/server/core.c b/server/core.c index e596508dc2..56e48d3215 100644 --- a/server/core.c +++ b/server/core.c @@ -4597,16 +4597,40 @@ AP_DECLARE(int) ap_state_query(int query) static apr_random_t *rng = NULL; #if APR_HAS_THREADS static apr_thread_mutex_t *rng_mutex = NULL; +#endif -static void create_rng_mutex(apr_pool_t *pchild, server_rec *s) +static void core_child_init(apr_pool_t *pchild, server_rec *s) { + apr_proc_t proc; +#if APR_HAS_THREADS int threaded_mpm; - if (ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm) != APR_SUCCESS) - return; - if (threaded_mpm) + if (ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm) == APR_SUCCESS + && threaded_mpm) + { apr_thread_mutex_create(&rng_mutex, APR_THREAD_MUTEX_DEFAULT, pchild); -} + } #endif + /* The MPMs use plain fork() and not apr_proc_fork(), so we have to call + * apr_random_after_fork() manually in the child + */ + proc.pid = getpid(); + apr_random_after_fork(&proc); +} + +AP_CORE_DECLARE(void) ap_random_parent_after_fork(void) +{ + /* + * To ensure that the RNG state in the parent changes after the fork, we + * pull some data from the RNG and discard it. This ensures that the RNG + * states in the children ar different even after the pid wraps around. + * As we only use apr_random for insecure random bytes, pulling 2 bytes + * should be enough. + * XXX: APR should probably have some dedicated API to do this, but it + * XXX: currently doesn't. + */ + apr_uint16_t data; + apr_random_insecure_bytes(rng, &data, sizeof(data)); +} static void rng_init(apr_pool_t *p) { @@ -4735,9 +4759,7 @@ static void register_hooks(apr_pool_t *p) ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST); ap_hook_map_to_storage(core_map_to_storage,NULL,NULL,APR_HOOK_REALLY_LAST); ap_hook_open_logs(ap_open_logs,NULL,NULL,APR_HOOK_REALLY_FIRST); -#if APR_HAS_THREADS - ap_hook_child_init(create_rng_mutex,NULL,NULL,APR_HOOK_REALLY_FIRST); -#endif + ap_hook_child_init(core_child_init,NULL,NULL,APR_HOOK_REALLY_FIRST); ap_hook_child_init(ap_logs_child_init,NULL,NULL,APR_HOOK_MIDDLE); ap_hook_handler(default_handler,NULL,NULL,APR_HOOK_REALLY_LAST); /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */ diff --git a/server/mpm_common.c b/server/mpm_common.c index d35d349a50..d189920072 100644 --- a/server/mpm_common.c +++ b/server/mpm_common.c @@ -41,6 +41,7 @@ #include "http_log.h" #include "http_main.h" #include "mpm_common.h" +#include "mod_core.h" #include "ap_mpm.h" #include "ap_listen.h" #include "util_mutex.h" @@ -453,6 +454,7 @@ void ap_core_child_status(server_rec *s, pid_t pid, APR_RING_ELEM_INIT(cur, link); APR_RING_INSERT_HEAD(geninfo, cur, mpm_gen_info_t, link); } + ap_random_parent_after_fork(); ++cur->active; break; case MPM_CHILD_EXITED: