summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@qt.io>2018-08-17 16:58:32 +0200
committerMichael BrĂ¼ning <michael.bruning@qt.io>2018-08-20 09:58:36 +0000
commitf78390d24d2128ecf90c17f692d5c6bcd9cf7fa5 (patch)
treea8a996e5e86f4d64bba2b620fbdafb1daed8005e
parentd739b9e990b1c2daff4d47c810ac3e256af385c8 (diff)
[Backport] Security Bug 831117 1/2
[oilpan] Detach V8 garbage colector before running termination GC Any roots from V8 into Blink need to be cleared before running the termination garbage collection to ensure that all objects die and finalizers are called. Bug: chromium:831117 Reviewed-on: https://chromium-review.googlesource.com/1025032 Change-Id: I3e153584e1a8d0ea42675e6f6e94693295230f05 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
-rw-r--r--chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp49
-rw-r--r--chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp1
-rw-r--r--chromium/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp8
4 files changed, 56 insertions, 7 deletions
diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
index 7dc184828cd..096baa7a937 100644
--- a/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
+++ b/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -477,34 +477,69 @@ void V8GCController::CollectAllGarbageForTesting(v8::Isolate* isolate) {
v8::Isolate::kFullGarbageCollection);
}
-class DOMWrapperTracer : public v8::PersistentHandleVisitor {
+namespace {
+
+// Traces all DOM persistent handles using the provided visitor.
+class DOMWrapperTracer final : public v8::PersistentHandleVisitor {
public:
explicit DOMWrapperTracer(Visitor* visitor) : visitor_(visitor) {
DCHECK(visitor_);
}
void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
- uint16_t class_id) override {
+ uint16_t class_id) final {
if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId)
return;
+ visitor_->Trace(
+ ToScriptWrappable(v8::Persistent<v8::Object>::Cast(*value)));
+ }
+
+ private:
+ Visitor* const visitor_;
+};
- const v8::Persistent<v8::Object>& wrapper =
- v8::Persistent<v8::Object>::Cast(*value);
+// Purges all DOM persistent handles.
+class DOMWrapperPurger final : public v8::PersistentHandleVisitor {
+ public:
+ explicit DOMWrapperPurger(v8::Isolate* isolate)
+ : isolate_(isolate), scope_(isolate) {}
- if (ScriptWrappable* script_wrappable = ToScriptWrappable(wrapper))
- ToWrapperTypeInfo(wrapper)->Trace(visitor_, script_wrappable);
+ void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
+ uint16_t class_id) final {
+ if (class_id != WrapperTypeInfo::kNodeClassId &&
+ class_id != WrapperTypeInfo::kObjectClassId)
+ return;
+
+ // Clear out wrapper type information, essentially disconnecting the Blink
+ // wrappable from the V8 wrapper. This way, V8 cannot find the C++ object
+ // anymore.
+
+ int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
+ void* values[] = {nullptr, nullptr};
+ v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(
+ isolate_, v8::Persistent<v8::Object>::Cast(*value));
+ wrapper->SetAlignedPointerInInternalFields(arraysize(indices), indices,
+ values);
+ value->Reset();
}
private:
- Visitor* visitor_;
+ v8::Isolate* isolate_;
+ v8::HandleScope scope_;
};
+} // namespace
void V8GCController::TraceDOMWrappers(v8::Isolate* isolate, Visitor* visitor) {
DOMWrapperTracer tracer(visitor);
isolate->VisitHandlesWithClassIds(&tracer);
}
+void V8GCController::ClearDOMWrappers(v8::Isolate* isolate) {
+ DOMWrapperPurger purger(isolate);
+ isolate->VisitHandlesWithClassIds(&purger);
+}
+
class PendingActivityVisitor : public v8::PersistentHandleVisitor {
public:
PendingActivityVisitor(v8::Isolate* isolate,
diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.h b/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.h
index 55d4383d001..eb8be55aa13 100644
--- a/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.h
+++ b/chromium/third_party/WebKit/Source/bindings/core/v8/V8GCController.h
@@ -61,7 +61,12 @@ class CORE_EXPORT V8GCController {
static void TraceDOMWrappers(v8::Isolate*, Visitor*);
static bool HasPendingActivity(v8::Isolate*, ExecutionContext*);
+ // Called when Oilpan traces references from V8 wrappers to DOM wrappables.
static v8::HeapProfiler::RetainerInfos GetRetainerInfos(v8::Isolate*);
+
+ // Called upon terminating a thread when Oilpan clears references from V8
+ // wrappers to DOM wrappables.
+ static void ClearDOMWrappers(v8::Isolate*);
};
} // namespace blink
diff --git a/chromium/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp b/chromium/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
index 82562c638eb..779a44951ad 100644
--- a/chromium/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
+++ b/chromium/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
@@ -114,6 +114,7 @@ void WorkerBackingThread::ShutdownOnBackingThread() {
Platform::Current()->WillStopWorkerThread();
V8PerIsolateData::WillBeDestroyed(isolate_);
+ V8GCController::ClearDOMWrappers(isolate_);
// TODO(yhirano): Remove this when https://crbug.com/v8/1428 is fixed.
if (should_call_gc_on_shutdown_) {
// This statement runs only in tests.
diff --git a/chromium/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp b/chromium/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp
index 8c62f1f4a06..b06f68cd391 100644
--- a/chromium/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp
+++ b/chromium/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp
@@ -153,6 +153,14 @@ void V8PerIsolateData::WillBeDestroyed(v8::Isolate* isolate) {
data->ClearEndOfScopeTasks();
data->active_script_wrappables_.Clear();
+
+
+ // Detach V8's garbage collector.
+
+ isolate->SetEmbedderHeapTracer(nullptr);
+ if (data->script_wrappable_visitor_->WrapperTracingInProgress())
+ data->script_wrappable_visitor_->AbortTracing();
+ data->script_wrappable_visitor_.reset();
}
// destroy() clear things that should be cleared after ThreadState::detach()