diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index d6a7c7ef529a8..046abfde17951 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc @@ -165,6 +165,28 @@ void DedicatedWorker::postMessage(ScriptState* script_state, if (!GetExecutionContext()) return; + // --- POC INJECTION: simulate Page-Lifecycle freeze via magic message. --- + { + v8::Local v = message.V8Value(); + if (!v.IsEmpty() && v->IsString()) { + v8::String::Utf8Value s(script_state->GetIsolate(), v); + std::string str(*s ? *s : ""); + if (str == "__POC_FREEZE__") { + LOG(ERROR) << "[POC] DedicatedWorker: triggering Freeze()"; + ContextLifecycleStateChanged( + mojom::blink::FrameLifecycleState::kFrozen); + return; + } + if (str == "__POC_RESUME__") { + LOG(ERROR) << "[POC] DedicatedWorker: triggering Resume()"; + ContextLifecycleStateChanged( + mojom::blink::FrameLifecycleState::kRunning); + return; + } + } + } + // --- END POC INJECTION --- + BlinkTransferableMessage transferable_message; Transferables transferables; scoped_refptr serialized_message = diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index ef25707a97c4d..f7f2fa9a4a7bc 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc @@ -43,6 +43,8 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "v8/include/v8-script.h" #include "third_party/blink/renderer/core/execution_context/agent.h" #include "third_party/blink/renderer/core/frame/policy_container.h" #include "third_party/blink/renderer/core/inspector/console_message_storage.h" @@ -951,6 +953,46 @@ void WorkerThread::PauseOrFreezeOnWorkerThread( if (pause_or_freeze_count_ > 1) return; + LOG(ERROR) << "[POC] PauseOrFreezeOnWorkerThread: entering nested loop, " + "state=" << static_cast(state); + // --- POC INJECTION: simulate attacker JS landing on the unpausable + // (kWebLocks) task queue, which the nested message loop below processes. + // The vulnerability report identifies WebLocks Granted() as one such vector; + // this stub stands in for it so the POC is deterministic. + { + WorkerThread* self = this; + GlobalScope()->GetTaskRunner(TaskType::kWebLocks)->PostTask( + FROM_HERE, base::BindOnce( + [](WorkerThread* thread) { + if (!thread || !thread->GlobalScope() || + !thread->GlobalScope()->ScriptController()) { + return; + } + ScriptState* state = thread->GlobalScope() + ->ScriptController() + ->GetScriptState(); + if (!state || !state->ContextIsValid()) { + return; + } + ScriptState::Scope scope(state); + v8::Isolate* iso = state->GetIsolate(); + v8::TryCatch tc(iso); + v8::Local src = + v8::String::NewFromUtf8Literal( + iso, + "globalThis.__pocReentry && " + "globalThis.__pocReentry()"); + v8::Local script; + if (v8::Script::Compile(state->GetContext(), src) + .ToLocal(&script)) { + LOG(ERROR) << "[POC] running __pocReentry on " + "unpausable queue"; + std::ignore = script->Run(state->GetContext()); + } + }, + base::Unretained(self))); + } + // --- END POC INJECTION --- pause_handle_ = GetScheduler()->Pause(); { // Since the nested message loop runner needs to be created and destroyed on diff --git a/v8/src/execution/futex-emulation.cc b/v8/src/execution/futex-emulation.cc index 436614c82f8..cc844414094 100644 --- a/v8/src/execution/futex-emulation.cc +++ b/v8/src/execution/futex-emulation.cc @@ -216,6 +216,14 @@ void FutexEmulation::NotifyAsyncWaiter(FutexWaitListNode* node) { } void FutexWaitList::AddNode(FutexWaitListNode* node) { + // POC diagnostic only (does not change behaviour): log double-add. + if (node->prev_ || node->next_) { + fprintf(stderr, + "[POC] FutexWaitList::AddNode DOUBLE-ADD node=%p prev=%p next=%p " + "loc=%p\n", + static_cast(node), static_cast(node->prev_), + static_cast(node->next_), node->wait_location_); + } DCHECK_NULL(node->prev_); DCHECK_NULL(node->next_); auto [it, inserted] =