]> granicus.if.org Git - apache/commitdiff
Call apr_random_after_fork() manually in the child processes because the MPMs
authorStefan Fritsch <sf@apache.org>
Mon, 7 Nov 2011 18:46:47 +0000 (18:46 +0000)
committerStefan Fritsch <sf@apache.org>
Mon, 7 Nov 2011 18:46:47 +0000 (18:46 +0000)
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

include/mod_core.h
server/core.c
server/mpm_common.c

index 58f3c93dcb6e3cdc66c98f401d48b96c58ac6d28..8e822d9b20af6de403ad547fe00d3a7b118e64a9 100644 (file)
@@ -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
index e596508dc2f8715ae5c66c6cde161d35d3054dfe..56e48d3215c0c0a5eecedfe9d5adec8e6ee8d116 100644 (file)
@@ -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 */
index d35d349a5040bbffc589562fa280d42519710275..d189920072561d66b8b2b06427cc9a3ec4abf45b 100644 (file)
@@ -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: