fork_detect: be robust to qemu.

fork_detect needs to know whether |MADV_WIPEONFORK| is supported by the
kernel or not. However, current versions of qemu ignore madvise calls
and just return zero, making it seems like it's supported when it's
actually not. Therefore, try an madvise with -1 to ensure that clearly
bogus values actually produce and error before trusting the result of
calling with |MADV_WIPEONFORK|.

Change-Id: I7f72714d5794274acabd0bee0b0ac470e1933774
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41024
Reviewed-by: 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 6de6293..8dd2c95 100644
--- a/crypto/fipsmodule/rand/fork_detect.c
+++ b/crypto/fipsmodule/rand/fork_detect.c
@@ -59,7 +59,13 @@
     return;
   }
 
-  if (madvise(addr, (size_t)page_size, MADV_WIPEONFORK) != 0) {
+  // Some versions of qemu (up to at least 5.0.0-rc4, see linux-user/syscall.c)
+  // ignore |madvise| calls and just return zero (i.e. success). But we need to
+  // know whether MADV_WIPEONFORK actually took effect. Therefore try an invalid
+  // call to check that the implementation of |madvise| is actually rejecting
+  // unknown |advice| values.
+  if (madvise(addr, (size_t)page_size, -1) == 0 ||
+      madvise(addr, (size_t)page_size, MADV_WIPEONFORK) != 0) {
     munmap(addr, (size_t)page_size);
     return;
   }