From 44951380ee6be5ac13dbd09d6072193d18c7d71a Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 22 May 2017 18:26:31 -0700 Subject: [PATCH] [wasm] Randomize code generation order. Security feature: pick compiled functions randomly Bug: v8:6417 Change-Id: Ibcef9ba94e3730a47cd43d2a59b23d5cee3fad40 Reviewed-on: https://chromium-review.googlesource.com/511842 Commit-Queue: Brad Nelson Reviewed-by: Brad Nelson Cr-Commit-Position: refs/heads/master@{#45472} --- src/wasm/wasm-module.cc | 51 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc index 151770bc2e..9c407f9103 100644 --- a/src/wasm/wasm-module.cc +++ b/src/wasm/wasm-module.cc @@ -8,6 +8,7 @@ #include "src/asmjs/asm-js.h" #include "src/assembler-inl.h" #include "src/base/atomic-utils.h" +#include "src/base/utils/random-number-generator.h" #include "src/code-stubs.h" #include "src/compiler/wasm-compiler.h" #include "src/debug/interface-types.h" @@ -290,6 +291,42 @@ bool compile_lazy(const WasmModule* module) { (FLAG_asm_wasm_lazy_compilation && module->is_asm_js()); } +class CodeGenerationSchedule { + public: + explicit CodeGenerationSchedule( + base::RandomNumberGenerator* random_number_generator) + : random_number_generator_(random_number_generator) { + DCHECK_NOT_NULL(random_number_generator_); + } + + void Schedule(std::unique_ptr&& item) { + schedule_.push_back(std::move(item)); + } + + bool IsEmpty() const { return schedule_.empty(); } + + std::unique_ptr GetNext() { + DCHECK(!IsEmpty()); + size_t index = GetRandomIndexInSchedule(); + auto ret = std::move(schedule_[index]); + std::swap(schedule_[schedule_.size() - 1], schedule_[index]); + schedule_.pop_back(); + return ret; + } + + private: + size_t GetRandomIndexInSchedule() { + double factor = random_number_generator_->NextDouble(); + size_t index = (size_t)(factor * schedule_.size()); + DCHECK_GE(index, 0); + DCHECK_LT(index, schedule_.size()); + return index; + } + + base::RandomNumberGenerator* random_number_generator_ = nullptr; + std::vector> schedule_; +}; + // A helper for compiling an entire module. class CompilationHelper { public: @@ -299,7 +336,10 @@ class CompilationHelper { // reclaimed by explicitely releasing the {module_} field. CompilationHelper(Isolate* isolate, std::unique_ptr module, bool is_sync) - : isolate_(isolate), module_(std::move(module)), is_sync_(is_sync) {} + : isolate_(isolate), + module_(std::move(module)), + is_sync_(is_sync), + executed_units_(isolate->random_number_generator()) {} // The actual runnable task that performs compilations in the background. class CompilationTask : public CancelableTask { @@ -320,7 +360,7 @@ class CompilationHelper { bool is_sync_; std::vector> compilation_units_; - std::queue> executed_units_; + CodeGenerationSchedule executed_units_; base::Mutex result_mutex_; base::AtomicNumber next_unit_; size_t num_background_tasks_ = 0; @@ -349,7 +389,7 @@ class CompilationHelper { unit->ExecuteCompilation(); { base::LockGuard guard(&result_mutex_); - executed_units_.push(std::move(unit)); + executed_units_.Schedule(std::move(unit)); if (!finisher_is_running_) { no_finisher_callback(); // We set the flag here so that not more than one finisher is started. @@ -429,9 +469,8 @@ class CompilationHelper { std::unique_ptr unit; { base::LockGuard guard(&result_mutex_); - if (executed_units_.empty()) return Handle::null(); - unit = std::move(executed_units_.front()); - executed_units_.pop(); + if (executed_units_.IsEmpty()) return Handle::null(); + unit = executed_units_.GetNext(); } *func_index = unit->func_index(); Handle result = unit->FinishCompilation(thrower);