Commit b43103bf authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

WorkerOrWorkletScriptController: Clear V8->Blink references on Dispose

Blink stand-alone GCs are used in testing and on thread termination.
Such GCs iterate Blink->V8 references (global handles) to find the
corresponding V8->Blink references that should be treated as roots.

On WorkerOrWorkletGlobalScope dispose we also clear the DOMWrapperWorld
that holds the Blink->V8 references (global handles).

In the case a stand-alone GC happens at this point,
WorklerOrWorkletGlobalScope is reclaimed. Access through the JS wrapper
back references results in UAF.

Bug: chromium:1003729
Change-Id: Iba0cb340a2037445947920888596ea7ecf7c32da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1833825Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701968}
parent 12ed37dd
......@@ -114,9 +114,8 @@ void WorkerOrWorkletScriptController::Dispose() {
rejected_promises_->Dispose();
rejected_promises_ = nullptr;
world_->Dispose();
DisposeContextIfNeeded();
world_->Dispose();
}
void WorkerOrWorkletScriptController::DisposeContextIfNeeded() {
......@@ -132,9 +131,23 @@ void WorkerOrWorkletScriptController::DisposeContextIfNeeded() {
{
ScriptState::Scope scope(script_state_);
v8::Local<v8::Context> context = script_state_->GetContext();
// After disposing the world, all Blink->V8 references are gone. Blink
// stand-alone GCs may collect the WorkerOrWorkletGlobalScope because there
// are no more roots (V8->Blink references that are actually found by
// iterating Blink->V8 references). Clear the back pointers to avoid
// referring to cleared memory on the next GC in case the JS wrapper objects
// survived.
v8::Local<v8::Object> global_proxy_object = context->Global();
v8::Local<v8::Object> global_object =
global_proxy_object->GetPrototype().As<v8::Object>();
DCHECK(!global_object.IsEmpty());
V8DOMWrapper::ClearNativeInfo(isolate_, global_object);
V8DOMWrapper::ClearNativeInfo(isolate_, global_proxy_object);
// This detaches v8::MicrotaskQueue pointer from v8::Context, so that we can
// destroy EventLoop safely.
script_state_->GetContext()->DetachGlobal();
context->DetachGlobal();
}
script_state_->DisposePerContextData();
......
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