Commit 85bb89cb authored by Chris Palmer's avatar Chris Palmer Committed by Commit Bot

Further tighten the Partition Alloc RNG API.

Bug: 984742
Change-Id: I35a17fc8b923c949125ff63511c424143f3f80e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1761402
Commit-Queue: Chris Palmer <palmer@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#688711}
parent 2de49f8b
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
namespace base { namespace base {
void* GetRandomPageBase() { void* GetRandomPageBase() {
uintptr_t random = static_cast<uintptr_t>(RandomValue(GetRandomContext())); uintptr_t random = static_cast<uintptr_t>(RandomValue());
#if defined(ARCH_CPU_64_BITS) #if defined(ARCH_CPU_64_BITS)
random <<= 32ULL; random <<= 32ULL;
random |= static_cast<uintptr_t>(RandomValue(GetRandomContext())); random |= static_cast<uintptr_t>(RandomValue());
// The kASLRMask and kASLROffset constants will be suitable for the // The kASLRMask and kASLROffset constants will be suitable for the
// OS and build configuration. // OS and build configuration.
......
...@@ -101,8 +101,8 @@ TEST(AddressSpaceRandomizationTest, Predictable) { ...@@ -101,8 +101,8 @@ TEST(AddressSpaceRandomizationTest, Predictable) {
if (!mask) if (!mask)
return; return;
const uintptr_t kInitialSeed = 0xfeed5eedULL; const uint64_t kInitialSeed = 0xfeed5eedULL;
base::SetRandomPageBaseSeed(kInitialSeed); base::SetMmapSeedForTesting(kInitialSeed);
std::vector<uintptr_t> sequence; std::vector<uintptr_t> sequence;
for (size_t i = 0; i < kSamples; ++i) { for (size_t i = 0; i < kSamples; ++i) {
...@@ -110,7 +110,7 @@ TEST(AddressSpaceRandomizationTest, Predictable) { ...@@ -110,7 +110,7 @@ TEST(AddressSpaceRandomizationTest, Predictable) {
sequence.push_back(address); sequence.push_back(address);
} }
base::SetRandomPageBaseSeed(kInitialSeed); base::SetMmapSeedForTesting(kInitialSeed);
for (size_t i = 0; i < kSamples; ++i) { for (size_t i = 0; i < kSamples; ++i) {
uintptr_t address = reinterpret_cast<uintptr_t>(base::GetRandomPageBase()); uintptr_t address = reinterpret_cast<uintptr_t>(base::GetRandomPageBase());
......
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
#include "base/allocator/partition_allocator/random.h" #include "base/allocator/partition_allocator/random.h"
#include "base/allocator/partition_allocator/spin_lock.h" #include "base/allocator/partition_allocator/spin_lock.h"
#include "base/logging.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/rand_util.h" #include "base/rand_util.h"
namespace base { namespace base {
// This is the same PRNG as used by tcmalloc for mapping address randomness; // This is the same PRNG as used by tcmalloc for mapping address randomness;
// see http://burtleburtle.net/bob/rand/smallprng.html // see http://burtleburtle.net/bob/rand/smallprng.html.
struct RandomContext { struct RandomContext {
subtle::SpinLock lock; subtle::SpinLock lock;
bool initialized; bool initialized;
...@@ -21,12 +22,11 @@ struct RandomContext { ...@@ -21,12 +22,11 @@ struct RandomContext {
uint32_t d; uint32_t d;
}; };
RandomContext* GetRandomContext() { namespace {
static NoDestructor<RandomContext> s_RandomContext;
return s_RandomContext.get();
}
uint32_t RandomValue(RandomContext* x) { RandomContext* GetRandomContext() {
static NoDestructor<RandomContext> g_random_context;
RandomContext* x = g_random_context.get();
subtle::SpinLock::Guard guard(x->lock); subtle::SpinLock::Guard guard(x->lock);
if (UNLIKELY(!x->initialized)) { if (UNLIKELY(!x->initialized)) {
const uint64_t r1 = RandUint64(); const uint64_t r1 = RandUint64();
...@@ -37,7 +37,14 @@ uint32_t RandomValue(RandomContext* x) { ...@@ -37,7 +37,14 @@ uint32_t RandomValue(RandomContext* x) {
x->d = static_cast<uint32_t>(r2 >> 32); x->d = static_cast<uint32_t>(r2 >> 32);
x->initialized = true; x->initialized = true;
} }
return x;
}
} // namespace
uint32_t RandomValue() {
RandomContext* x = GetRandomContext();
subtle::SpinLock::Guard guard(x->lock);
#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
uint32_t e = x->a - rot(x->b, 27); uint32_t e = x->a - rot(x->b, 27);
x->a = x->b ^ rot(x->c, 17); x->a = x->b ^ rot(x->c, 17);
...@@ -48,7 +55,7 @@ uint32_t RandomValue(RandomContext* x) { ...@@ -48,7 +55,7 @@ uint32_t RandomValue(RandomContext* x) {
#undef rot #undef rot
} }
void SetRandomPageBaseSeed(int64_t seed) { void SetMmapSeedForTesting(uint64_t seed) {
RandomContext* x = GetRandomContext(); RandomContext* x = GetRandomContext();
subtle::SpinLock::Guard guard(x->lock); subtle::SpinLock::Guard guard(x->lock);
x->a = x->b = static_cast<uint32_t>(seed); x->a = x->b = static_cast<uint32_t>(seed);
......
...@@ -11,23 +11,16 @@ ...@@ -11,23 +11,16 @@
namespace base { namespace base {
struct RandomContext; // Returns a random value. The generator's internal state is initialized with
// `base::RandUint64` which is very unpredictable, but which is expensive due to
// the need to call into the kernel. Therefore this generator uses a fast,
// entirely user-space function after initialization.
uint32_t RandomValue();
// TODO(crbug.com/984742): This doesn't need to be part of the interface, and
// can be an implementation detail of `RandomValue`.
//
// Returns a pointer to the global `RandomContext`. If the context has not been
// initialized yet, initializes it with a random starting state.
RandomContext* GetRandomContext();
uint32_t RandomValue(RandomContext* x);
// TODO(crbug.com/984742): Rename this to `SetRandomSeedForTesting`.
//
// Sets the seed for the random number generator to a known value, to cause the // Sets the seed for the random number generator to a known value, to cause the
// RNG to generate a predictable sequence of outputs. May be called multiple // RNG to generate a predictable sequence of outputs. May be called multiple
// times. // times.
BASE_EXPORT void SetRandomPageBaseSeed(int64_t seed); BASE_EXPORT void SetMmapSeedForTesting(uint64_t seed);
} // namespace base } // namespace base
......
...@@ -207,7 +207,7 @@ class PageAllocator : public v8::PageAllocator { ...@@ -207,7 +207,7 @@ class PageAllocator : public v8::PageAllocator {
size_t CommitPageSize() override { return base::kSystemPageSize; } size_t CommitPageSize() override { return base::kSystemPageSize; }
void SetRandomMmapSeed(int64_t seed) override { void SetRandomMmapSeed(int64_t seed) override {
base::SetRandomPageBaseSeed(seed); base::SetMmapSeedForTesting(seed);
} }
void* GetRandomMmapAddr() override { return base::GetRandomPageBase(); } void* GetRandomMmapAddr() override { return base::GetRandomPageBase(); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment