summaryrefslogtreecommitdiff
path: root/src/crypto/fipsmodule/rand/fork_detect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/fipsmodule/rand/fork_detect.c')
-rw-r--r--src/crypto/fipsmodule/rand/fork_detect.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/src/crypto/fipsmodule/rand/fork_detect.c b/src/crypto/fipsmodule/rand/fork_detect.c
index 71a02c89..a2cf3a05 100644
--- a/src/crypto/fipsmodule/rand/fork_detect.c
+++ b/src/crypto/fipsmodule/rand/fork_detect.c
@@ -17,31 +17,34 @@
#endif
#include <openssl/base.h>
-
#include "fork_detect.h"
-#if defined(OPENSSL_LINUX)
-#include <assert.h>
-#include <sys/mman.h>
+#if defined(OPENSSL_FORK_DETECTION_MADVISE)
#include <unistd.h>
#include <stdlib.h>
-
-#include "../delocate.h"
-#include "../../internal.h"
-
-
+#include <assert.h>
+#include <sys/mman.h>
#if defined(MADV_WIPEONFORK)
static_assert(MADV_WIPEONFORK == 18, "MADV_WIPEONFORK is not 18");
#else
#define MADV_WIPEONFORK 18
#endif
+#elif defined(OPENSSL_FORK_DETECTION_PTHREAD_ATFORK)
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+#endif // OPENSSL_FORK_DETECTION_MADVISE
+#include "../delocate.h"
+#include "../../internal.h"
+
+#if defined(OPENSSL_FORK_DETECTION_MADVISE)
+DEFINE_BSS_GET(int, g_force_madv_wipeonfork);
+DEFINE_BSS_GET(int, g_force_madv_wipeonfork_enabled);
DEFINE_STATIC_ONCE(g_fork_detect_once);
DEFINE_STATIC_MUTEX(g_fork_detect_lock);
DEFINE_BSS_GET(CRYPTO_atomic_u32 *, g_fork_detect_addr);
DEFINE_BSS_GET(uint64_t, g_fork_generation);
-DEFINE_BSS_GET(int, g_force_madv_wipeonfork);
-DEFINE_BSS_GET(int, g_force_madv_wipeonfork_enabled);
static void init_fork_detect(void) {
if (*g_force_madv_wipeonfork_bss_get()) {
@@ -73,9 +76,12 @@ static void init_fork_detect(void) {
CRYPTO_atomic_store_u32(addr, 1);
*g_fork_detect_addr_bss_get() = addr;
*g_fork_generation_bss_get() = 1;
+
}
uint64_t CRYPTO_get_fork_generation(void) {
+ CRYPTO_once(g_fork_detect_once_bss_get(), init_fork_detect);
+
// In a single-threaded process, there are obviously no races because there's
// only a single mutator in the address space.
//
@@ -87,7 +93,6 @@ uint64_t CRYPTO_get_fork_generation(void) {
// child process is single-threaded, the child may become multi-threaded
// before it observes this. Therefore, we must synchronize the logic below.
- CRYPTO_once(g_fork_detect_once_bss_get(), init_fork_detect);
CRYPTO_atomic_u32 *const flag_ptr = *g_fork_detect_addr_bss_get();
if (flag_ptr == NULL) {
// Our kernel is too old to support |MADV_WIPEONFORK| or
@@ -98,6 +103,12 @@ uint64_t CRYPTO_get_fork_generation(void) {
// doesn't support it.
return 42;
}
+ // With Linux and clone(), we do not believe that pthread_atfork() is
+ // sufficient for detecting all forms of address space duplication. At this
+ // point we have a kernel that does not support MADV_WIPEONFORK. We could
+ // return the generation number from pthread_atfork() here and it would
+ // probably be safe in almost any situation, but to ensure safety we return
+ // 0 and force an entropy draw on every call.
return 0;
}
@@ -140,7 +151,34 @@ void CRYPTO_fork_detect_force_madv_wipeonfork_for_testing(int on) {
*g_force_madv_wipeonfork_enabled_bss_get() = on;
}
-#elif defined(OPENSSL_WINDOWS) || defined(OPENSSL_TRUSTY)
+#elif defined(OPENSSL_FORK_DETECTION_PTHREAD_ATFORK)
+
+DEFINE_STATIC_ONCE(g_pthread_fork_detection_once);
+DEFINE_BSS_GET(uint64_t, g_atfork_fork_generation);
+
+static void we_are_forked(void) {
+ // Immediately after a fork, the process must be single-threaded.
+ uint64_t value = *g_atfork_fork_generation_bss_get() + 1;
+ if (value == 0) {
+ value = 1;
+ }
+ *g_atfork_fork_generation_bss_get() = value;
+}
+
+static void init_pthread_fork_detection(void) {
+ if (pthread_atfork(NULL, NULL, we_are_forked) != 0) {
+ abort();
+ }
+ *g_atfork_fork_generation_bss_get() = 1;
+}
+
+uint64_t CRYPTO_get_fork_generation(void) {
+ CRYPTO_once(g_pthread_fork_detection_once_bss_get(), init_pthread_fork_detection);
+
+ return *g_atfork_fork_generation_bss_get();
+}
+
+#elif defined(OPENSSL_DOES_NOT_FORK)
// These platforms are guaranteed not to fork, and therefore do not require
// fork detection support. Returning a constant non zero value makes BoringSSL