urandom_test: force MADV_WIPEONFORK both ways.

This test could simulate the lack of MADV_WIPEONFORK on systems with it,
but couldn't simulate having it if the kernel didn't support it.

This change makes the presence / absence of
BORINGSSL_IGNORE_MADV_WIPEONFORK control whether MADV_WIPEONFORK is
"supported" in the test environment or not, and corrects the test for
the case where it's missing.

Change-Id: I23876788a0e0a4fd2a148f98b6b94e40880b6fc9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57745
Auto-Submit: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/rand/fork_detect.c b/crypto/fipsmodule/rand/fork_detect.c
index 51cf18a..58b0687 100644
--- a/crypto/fipsmodule/rand/fork_detect.c
+++ b/crypto/fipsmodule/rand/fork_detect.c
@@ -40,10 +40,11 @@
 DEFINE_STATIC_MUTEX(g_fork_detect_lock);
 DEFINE_BSS_GET(volatile char *, g_fork_detect_addr);
 DEFINE_BSS_GET(uint64_t, g_fork_generation);
-DEFINE_BSS_GET(int, g_ignore_madv_wipeonfork);
+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_ignore_madv_wipeonfork_bss_get()) {
+  if (*g_force_madv_wipeonfork_bss_get()) {
     return;
   }
 
@@ -93,7 +94,14 @@
   // not assume that it has exclusive access to it.
   volatile char *const flag_ptr = *g_fork_detect_addr_bss_get();
   if (flag_ptr == NULL) {
-    // Our kernel is too old to support |MADV_WIPEONFORK|.
+    // Our kernel is too old to support |MADV_WIPEONFORK| or
+    // |g_force_madv_wipeonfork| is set.
+    if (*g_force_madv_wipeonfork_bss_get() &&
+        *g_force_madv_wipeonfork_enabled_bss_get()) {
+      // A constant generation number to simulate support, even if the kernel
+      // doesn't support it.
+      return 42;
+    }
     return 0;
   }
 
@@ -125,8 +133,9 @@
   return current_generation;
 }
 
-void CRYPTO_fork_detect_ignore_madv_wipeonfork_for_testing(void) {
-  *g_ignore_madv_wipeonfork_bss_get() = 1;
+void CRYPTO_fork_detect_force_madv_wipeonfork_for_testing(int on) {
+  *g_force_madv_wipeonfork_bss_get() = 1;
+  *g_force_madv_wipeonfork_enabled_bss_get() = on;
 }
 
 #else   // !OPENSSL_LINUX
diff --git a/crypto/fipsmodule/rand/fork_detect.h b/crypto/fipsmodule/rand/fork_detect.h
index 8518830..f9bbe02 100644
--- a/crypto/fipsmodule/rand/fork_detect.h
+++ b/crypto/fipsmodule/rand/fork_detect.h
@@ -38,9 +38,10 @@
 // should only be used as a hardening measure.
 OPENSSL_EXPORT uint64_t CRYPTO_get_fork_generation(void);
 
-// CRYPTO_fork_detect_ignore_madv_wipeonfork_for_testing is an internal detail
+// CRYPTO_fork_detect_force_madv_wipeonfork_for_testing is an internal detail
 // used for testing purposes.
-OPENSSL_EXPORT void CRYPTO_fork_detect_ignore_madv_wipeonfork_for_testing(void);
+OPENSSL_EXPORT void CRYPTO_fork_detect_force_madv_wipeonfork_for_testing(
+    int on);
 
 #if defined(__cplusplus)
 }  // extern C
diff --git a/crypto/fipsmodule/rand/urandom_test.cc b/crypto/fipsmodule/rand/urandom_test.cc
index d593b90..f92fe94 100644
--- a/crypto/fipsmodule/rand/urandom_test.cc
+++ b/crypto/fipsmodule/rand/urandom_test.cc
@@ -657,7 +657,11 @@
 static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
   std::vector<Event> ret;
   bool getrandom_ready = false;
-  const bool used_daemon = kUsesDaemon && AppendDaemonEvents(&ret, flags);
+  bool used_daemon = false;
+
+  if (have_fork_detection()) {
+    used_daemon = kUsesDaemon && AppendDaemonEvents(&ret, flags);
+  }
 
   // Probe for getrandom support
   ret.push_back(Event::GetRandom(1, GRND_NONBLOCK));
@@ -714,8 +718,13 @@
   const size_t kAdditionalDataLength = 32;
 
   if (!have_rdrand()) {
-    if ((!have_fork_detection() && !sysrand(true, kAdditionalDataLength)) ||
-        // Initialise CRNGT.
+    if (!have_fork_detection()) {
+      if (!sysrand(true, kAdditionalDataLength)) {
+        return ret;
+      }
+      used_daemon = kUsesDaemon && AppendDaemonEvents(&ret, flags);
+    }
+    if (// Initialise CRNGT.
         (!used_daemon && !sysrand(true, kSeedLength + (kIsFIPS ? 16 : 0))) ||
         // Personalisation draw if the daemon was used.
         (used_daemon && !sysrand(false, CTR_DRBG_ENTROPY_LEN)) ||
@@ -816,7 +825,9 @@
   ::testing::InitGoogleTest(&argc, argv);
 
   if (getenv("BORINGSSL_IGNORE_MADV_WIPEONFORK")) {
-    CRYPTO_fork_detect_ignore_madv_wipeonfork_for_testing();
+    CRYPTO_fork_detect_force_madv_wipeonfork_for_testing(0);
+  } else {
+    CRYPTO_fork_detect_force_madv_wipeonfork_for_testing(1);
   }
 
   return RUN_ALL_TESTS();