Bug 1167248 - Call RtlGenRandom() instead of rand_s() to workaround crashes from injected third-party hooks. r=jandem a=sylvestre
authorChris Peterson <cpeterson@mozilla.com>
Sun, 20 Dec 2015 21:14:44 -0800
changeset 310556 c5bef3674a1b217a35198a8c8f084328b99dca77
parent 310555 0ab687772056d6ea268a3a29e8eaebef1bbf9c7f
child 310557 1394461357c062ebfd3f5da2258e9375601a6ca7
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, sylvestre
bugs1167248
milestone45.0a2
Bug 1167248 - Call RtlGenRandom() instead of rand_s() to workaround crashes from injected third-party hooks. r=jandem a=sylvestre
js/src/jsmath.cpp
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -33,16 +33,25 @@
 #include "jstypes.h"
 
 #include "jit/InlinableNatives.h"
 #include "js/Class.h"
 #include "vm/Time.h"
 
 #include "jsobjinlines.h"
 
+#if defined(XP_WIN)
+// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036.  See the
+// "Community Additions" comment on MSDN here:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
+# define SystemFunction036 NTAPI SystemFunction036
+# include <NTSecAPI.h>
+# undef SystemFunction036
+#endif
+
 #if defined(ANDROID) || defined(XP_DARWIN) || defined(__DragonFly__) || \
     defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
 # include <stdlib.h>
 # define HAVE_ARC4RANDOM
 #endif
 
 using namespace js;
 
@@ -727,105 +736,46 @@ js::math_pow_handle(JSContext* cx, Handl
 bool
 js::math_pow(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     return math_pow_handle(cx, args.get(0), args.get(1), args.rval());
 }
 
-static void
-GenerateSeed(uint64_t* seedBuffer, size_t length)
+static uint64_t
+GenerateSeed()
 {
-    MOZ_ASSERT(length > 0);
+    uint64_t seed = 0;
 
 #if defined(XP_WIN)
-    /*
-     * Temporary diagnostic for bug 1167248: Test whether the injected hooks
-     * react differently to LoadLibraryW / LoadLibraryExW.
-     */
-    HMODULE oldWay = LoadLibraryW(L"ADVAPI32.DLL");
-    HMODULE newWay = LoadLibraryExW(L"ADVAPI32.DLL",
-                                    nullptr,
-                                    LOAD_LIBRARY_SEARCH_SYSTEM32);
-    /* Fallback for older versions of Windows */
-    if (!newWay && GetLastError() == ERROR_INVALID_PARAMETER)
-        newWay = LoadLibraryExW(L"ADVAPI32.DLL", nullptr, 0);
-
-    if (oldWay && !newWay)
-        MOZ_CRASH();
-
-    union {
-        uint32_t    u32[2];
-        uint64_t    u64;
-    } seed;
-    seed.u64 = 0;
-
-    errno_t error = rand_s(&seed.u32[0]);
-
-    if (oldWay)
-        FreeLibrary(oldWay);
-    if (newWay)
-        FreeLibrary(newWay);
-
-    MOZ_ASSERT(error == 0, "rand_s() error?!");
-
-    error = rand_s(&seed.u32[1]);
-    MOZ_ASSERT(error == 0, "rand_s() error?!");
-
-    seedBuffer[0] = seed.u64 ^= PRMJ_Now();
-    for (size_t i = 1; i < length; i++) {
-        error = rand_s(&seed.u32[0]);
-        MOZ_ASSERT(error == 0, "rand_s() error?!");
-
-        error = rand_s(&seed.u32[1]);
-        MOZ_ASSERT(error == 0, "rand_s() error?!");
-
-        seedBuffer[i] = seed.u64 ^ PRMJ_Now();
-    }
-
+    MOZ_ALWAYS_TRUE(RtlGenRandom(&seed, sizeof(seed)));
 #elif defined(HAVE_ARC4RANDOM)
-    union {
-        uint32_t    u32[2];
-        uint64_t    u64;
-    } seed;
-    seed.u64 = 0;
-
-    for (size_t i = 0; i < length; i++) {
-        seed.u32[0] = arc4random();
-        seed.u32[1] = arc4random();
-        seedBuffer[i] = seed.u64 ^ PRMJ_Now();
-    }
-
+    seed = (static_cast<uint64_t>(arc4random()) << 32) | arc4random();
 #elif defined(XP_UNIX)
     int fd = open("/dev/urandom", O_RDONLY);
-    MOZ_ASSERT(fd >= 0, "Can't open /dev/urandom?!");
     if (fd >= 0) {
-        ssize_t size = length * sizeof(seedBuffer[0]);
-        ssize_t nread = read(fd, (char *) seedBuffer, size);
+        read(fd, static_cast<void*>(&seed), sizeof(seed));
         close(fd);
-        MOZ_ASSERT(nread == size, "Can't read /dev/urandom?!");
-        if (nread == size)
-            return;
     }
+#else
+# error "Platform needs to implement GenerateSeed()"
+#endif
 
-    // Use PRMJ_Now() if we couldn't read from /dev/urandom.
-    for (size_t i = 0; i < length; i++)
-        seedBuffer[i] = PRMJ_Now();
-#else
-# error "Platform needs to implement random_generateSeed()"
-#endif
+    // Also mix in PRMJ_Now() in case we couldn't read random bits from the OS.
+    return seed ^ PRMJ_Now();
 }
 
 void
 js::GenerateXorShift128PlusSeed(mozilla::Array<uint64_t, 2>& seed)
 {
     // XorShift128PlusRNG must be initialized with a non-zero seed.
     do {
-        GenerateSeed(seed.begin(), mozilla::ArrayLength(seed));
+        seed[0] = GenerateSeed();
+        seed[1] = GenerateSeed();
     } while (seed[0] == 0 && seed[1] == 0);
 }
 
 void
 JSCompartment::ensureRandomNumberGenerator()
 {
     if (randomNumberGenerator.isNothing()) {
         mozilla::Array<uint64_t, 2> seed;