summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmcilroy <rmcilroy@chromium.org>2015-01-09 03:31:22 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-09 11:32:12 +0000
commitda69cd0f7c2f92640b7d00e59f66eb3b9fabba2e (patch)
tree27214eb143b0898348defb783b8cd2e7f0337658
parent712f1acaf22f225a5eaef28b3dff9aecb7bc5cc8 (diff)
downloadchromium_src-da69cd0f7c2f92640b7d00e59f66eb3b9fabba2e.zip
chromium_src-da69cd0f7c2f92640b7d00e59f66eb3b9fabba2e.tar.gz
chromium_src-da69cd0f7c2f92640b7d00e59f66eb3b9fabba2e.tar.bz2
[gin] Fingerprint the V8 snapshot files on Windows and verify before loading the snapshot.
Adds code which generates a SHA256 fingerprint of the external V8 snapshot blob files during the build process, and embeds these values into the binary. During startup the SHA256 hash of the snapshot blobs are compared against these fingerprints and Chrome will fail to load if they differ. BUG=421063,439661 Review URL: https://codereview.chromium.org/832393003 Cr-Commit-Position: refs/heads/master@{#310755}
-rw-r--r--content/app/content_main_runner.cc8
-rw-r--r--gin/BUILD.gn36
-rw-r--r--gin/DEPS1
-rw-r--r--gin/fingerprint/fingerprint_v8_snapshot.gypi47
-rwxr-xr-xgin/fingerprint/fingerprint_v8_snapshot.py86
-rw-r--r--gin/gin.gyp26
-rw-r--r--gin/isolate_holder.cc43
-rw-r--r--gin/public/isolate_holder.h2
8 files changed, 235 insertions, 14 deletions
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 05e45bd..2da7dc1 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -721,7 +721,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
else
CHECK(base::i18n::InitializeICU());
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
int v8_natives_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
kV8NativesDataDescriptor);
int v8_snapshot_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
@@ -736,10 +736,10 @@ class ContentMainRunnerImpl : public ContentMainRunner {
#else
CHECK(base::i18n::InitializeICU());
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
CHECK(gin::IsolateHolder::LoadV8Snapshot());
-#endif // V8_USE_EXTERNAL_STARTUP_DATA
-#endif // OS_ANDROID
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
+#endif // OS_ANDROID
InitializeStatsTable(command_line);
diff --git a/gin/BUILD.gn b/gin/BUILD.gn
index b352c3a..d389b84 100644
--- a/gin/BUILD.gn
+++ b/gin/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/module_args/v8.gni")
+
component("gin") {
sources = [
"arguments.cc",
@@ -68,6 +70,40 @@ component("gin") {
deps = [
"//base/third_party/dynamic_annotations",
]
+ if (v8_use_external_startup_data && is_win) {
+ deps += [
+ ":gin_v8_snapshot_fingerprint",
+ "//crypto:crypto",
+ ]
+ sources += [ "$target_gen_dir/v8_snapshot_fingerprint.cc" ]
+ defines += [ "V8_VERIFY_EXTERNAL_STARTUP_DATA" ]
+ }
+}
+
+if (v8_use_external_startup_data) {
+ action("gin_v8_snapshot_fingerprint") {
+ script = "//gin/fingerprint/fingerprint_v8_snapshot.py"
+
+ snapshot_file = "$root_build_dir/snapshot_blob.bin"
+ natives_file = "$root_build_dir/natives_blob.bin"
+ output_file = "$target_gen_dir/v8_snapshot_fingerprint.cc"
+
+ args = [
+ "--snapshot_file",
+ rebase_path(snapshot_file, root_build_dir),
+ "--natives_file",
+ rebase_path(natives_file, root_build_dir),
+ "--output_file",
+ rebase_path(output_file, root_build_dir),
+ ]
+ inputs = [
+ snapshot_file,
+ natives_file,
+ ]
+ outputs = [
+ output_file,
+ ]
+ }
}
executable("gin_shell") {
diff --git a/gin/DEPS b/gin/DEPS
index 4e3f30a..d4cc2ba 100644
--- a/gin/DEPS
+++ b/gin/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+base",
+ "+crypto",
"+v8",
]
diff --git a/gin/fingerprint/fingerprint_v8_snapshot.gypi b/gin/fingerprint/fingerprint_v8_snapshot.gypi
new file mode 100644
index 0000000..ede0de3
--- /dev/null
+++ b/gin/fingerprint/fingerprint_v8_snapshot.gypi
@@ -0,0 +1,47 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is meant to be included into a target to provide a rule that
+# fingerprints the v8 snapshot and generates a .cc file which includes this
+# fingerprint.
+#
+# To use this, create a gyp target with the following form:
+# {
+# 'target_name': 'gin_v8_snapshot_fingerprint',
+# 'type': 'none',
+# 'variables': {
+# 'snapshot_file': 'snapshot blob file to be fingerprinted',
+# 'natives_file': 'natives blob file to be fingerprinted',
+# 'output_file': 'output .cc file to generate with fingerprints',
+# },
+# 'includes': [ '../gin/fingerprint/fingerprint_v8_snapshot.gypi' ],
+# },
+#
+
+{
+ 'conditions': [
+ ['v8_use_external_startup_data==1', {
+ 'actions': [
+ {
+ 'action_name': 'Generate V8 snapshot fingerprint',
+ 'message': 'Generating V8 snapshot fingerprint',
+ 'inputs': [
+ '<(DEPTH)/gin/fingerprint/fingerprint_v8_snapshot.py',
+ '<(snapshot_file)',
+ '<(natives_file)',
+ ],
+ 'outputs': [
+ '<(output_file)',
+ ],
+ 'action': [
+ 'python', '<(DEPTH)/gin/fingerprint/fingerprint_v8_snapshot.py',
+ '--snapshot_file=<(snapshot_file)',
+ '--natives_file=<(natives_file)',
+ '--output_file=<(output_file)',
+ ],
+ }
+ ],
+ }],
+ ],
+} \ No newline at end of file
diff --git a/gin/fingerprint/fingerprint_v8_snapshot.py b/gin/fingerprint/fingerprint_v8_snapshot.py
new file mode 100755
index 0000000..d1f7092
--- /dev/null
+++ b/gin/fingerprint/fingerprint_v8_snapshot.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Fingerprints the V8 snapshot blob files.
+
+Constructs a SHA256 fingerprint of the V8 natives and snapshot blob files and
+creates a .cc file which includes these fingerprint as variables.
+"""
+
+import hashlib
+import optparse
+import os
+import sys
+
+_HEADER = """// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file was generated by fingerprint_v8_snapshot.py.
+
+namespace gin {
+"""
+
+_FOOTER = """
+} // namespace gin
+"""
+
+
+def FingerprintFile(file_path):
+ input_file = open(file_path, 'rb')
+ sha256 = hashlib.sha256()
+ while True:
+ block = input_file.read(sha256.block_size)
+ if not block:
+ break
+ sha256.update(block)
+ return sha256.digest()
+
+
+def WriteFingerprint(output_file, variable_name, fingerprint):
+ output_file.write('\nextern const unsigned char %s[] = { ' % variable_name)
+ for byte in fingerprint:
+ output_file.write(str(ord(byte)) + ', ')
+ output_file.write('};\n')
+
+
+def WriteOutputFile(natives_fingerprint,
+ snapshot_fingerprint,
+ output_file_path):
+ output_dir_path = os.path.dirname(output_file_path)
+ if not os.path.exists(output_dir_path):
+ os.makedirs(output_dir_path)
+ output_file = open(output_file_path, 'w')
+
+ output_file.write(_HEADER)
+ WriteFingerprint(output_file, 'g_natives_fingerprint', natives_fingerprint)
+ output_file.write('\n')
+ WriteFingerprint(output_file, 'g_snapshot_fingerprint', snapshot_fingerprint)
+ output_file.write(_FOOTER)
+
+
+def main():
+ parser = optparse.OptionParser()
+
+ parser.add_option('--snapshot_file',
+ help='The input V8 snapshot blob file path.')
+ parser.add_option('--natives_file',
+ help='The input V8 natives blob file path.')
+ parser.add_option('--output_file',
+ help='The path for the output cc file which will be write.')
+
+ options, _ = parser.parse_args()
+
+ natives_fingerprint = FingerprintFile(options.natives_file)
+ snapshot_fingerprint = FingerprintFile(options.snapshot_file)
+ WriteOutputFile(
+ natives_fingerprint, snapshot_fingerprint, options.output_file)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/gin/gin.gyp b/gin/gin.gyp
index b38dc85..096c120 100644
--- a/gin/gin.gyp
+++ b/gin/gin.gyp
@@ -5,6 +5,7 @@
{
'variables': {
'chromium_code': 1,
+ 'gin_gen_path': '<(SHARED_INTERMEDIATE_DIR)/gin/',
},
'targets': [
{
@@ -14,7 +15,6 @@
'../base/base.gyp:base',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../v8/tools/gyp/v8.gyp:v8',
-
],
'export_dependent_settings': [
'../base/base.gyp:base',
@@ -78,6 +78,30 @@
'wrappable.h',
'wrapper_info.cc',
],
+ 'conditions': [
+ ['v8_use_external_startup_data==1 and OS=="win"', {
+ 'dependencies': [
+ 'gin_v8_snapshot_fingerprint',
+ '../crypto/crypto.gyp:crypto',
+ ],
+ 'sources': [
+ '<(gin_gen_path)/v8_snapshot_fingerprint.cc',
+ ],
+ 'defines': [
+ 'V8_VERIFY_EXTERNAL_STARTUP_DATA',
+ ]
+ }],
+ ],
+ },
+ {
+ 'target_name': 'gin_v8_snapshot_fingerprint',
+ 'type': 'none',
+ 'variables': {
+ 'snapshot_file': '<(PRODUCT_DIR)/snapshot_blob.bin',
+ 'natives_file': '<(PRODUCT_DIR)/natives_blob.bin',
+ 'output_file': '<(gin_gen_path)/v8_snapshot_fingerprint.cc',
+ },
+ 'includes': [ '../gin/fingerprint/fingerprint_v8_snapshot.gypi' ],
},
{
'target_name': 'gin_shell',
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc
index 2b6d64b..38215b2 100644
--- a/gin/isolate_holder.cc
+++ b/gin/isolate_holder.cc
@@ -12,6 +12,7 @@
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "base/sys_info.h"
+#include "crypto/sha2.h"
#include "gin/array_buffer.h"
#include "gin/debug_impl.h"
#include "gin/function_template.h"
@@ -19,8 +20,8 @@
#include "gin/public/v8_platform.h"
#include "gin/run_microtasks_observer.h"
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
-#ifdef OS_MACOSX
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
#endif // OS_MACOSX
#include "base/path_service.h"
@@ -40,7 +41,7 @@ bool GenerateEntropy(unsigned char* buffer, size_t amount) {
base::MemoryMappedFile* g_mapped_natives = NULL;
base::MemoryMappedFile* g_mapped_snapshot = NULL;
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
bool MapV8Files(base::FilePath* natives_path, base::FilePath* snapshot_path,
int natives_fd = -1, int snapshot_fd = -1) {
int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
@@ -72,21 +73,39 @@ bool MapV8Files(base::FilePath* natives_path, base::FilePath* snapshot_path,
return true;
}
+#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
+bool VerifyV8SnapshotFile(base::MemoryMappedFile* snapshot_file,
+ const unsigned char* fingerprint) {
+ unsigned char output[crypto::kSHA256Length];
+ crypto::SHA256HashString(
+ base::StringPiece(reinterpret_cast<const char*>(snapshot_file->data()),
+ snapshot_file->length()),
+ output, sizeof(output));
+ return !memcmp(fingerprint, output, sizeof(output));
+}
+#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
+
#if !defined(OS_MACOSX)
const int v8_snapshot_dir =
#if defined(OS_ANDROID)
base::DIR_ANDROID_APP_DATA;
#elif defined(OS_POSIX)
base::DIR_EXE;
-#endif // defined(OS_ANDROID)
-#endif // !defined(OS_MACOSX)
+#endif // OS_ANDROID
+#endif // !OS_MACOSX
#endif // V8_USE_EXTERNAL_STARTUP_DATA
} // namespace
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+
+#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
+// Defined in gen/gin/v8_snapshot_fingerprint.cc
+extern const unsigned char g_natives_fingerprint[];
+extern const unsigned char g_snapshot_fingerprint[];
+#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
// static
bool IsolateHolder::LoadV8Snapshot() {
if (g_mapped_natives && g_mapped_snapshot)
@@ -108,7 +127,15 @@ bool IsolateHolder::LoadV8Snapshot() {
DCHECK(!snapshot_path.empty());
#endif // !defined(OS_MACOSX)
- return MapV8Files(&natives_path, &snapshot_path);
+ if (!MapV8Files(&natives_path, &snapshot_path))
+ return false;
+
+#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
+ return VerifyV8SnapshotFile(g_mapped_natives, g_natives_fingerprint) &&
+ VerifyV8SnapshotFile(g_mapped_snapshot, g_snapshot_fingerprint);
+#else
+ return true;
+#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
}
//static
@@ -193,7 +220,7 @@ void IsolateHolder::Initialize(ScriptMode mode,
v8::V8::SetFlagsFromString(v8_flags, sizeof(v8_flags) - 1);
}
v8::V8::SetEntropySource(&GenerateEntropy);
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
v8::StartupData natives;
natives.data = reinterpret_cast<const char*>(g_mapped_natives->data());
natives.raw_size = static_cast<int>(g_mapped_natives->length());
diff --git a/gin/public/isolate_holder.h b/gin/public/isolate_holder.h
index b12734c..64fc952 100644
--- a/gin/public/isolate_holder.h
+++ b/gin/public/isolate_holder.h
@@ -51,7 +51,7 @@ class GIN_EXPORT IsolateHolder {
// thread.
void RemoveRunMicrotasksObserver();
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
static bool LoadV8SnapshotFD(int natives_fd, int snapshot_fd);
static bool LoadV8Snapshot();
#endif // V8_USE_EXTERNAL_STARTUP_DATA