diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-04-17 15:07:31 +0200 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2020-06-05 10:00:25 +0000 |
commit | f11657ed645939c383c9955fd32daf52437f2ec2 (patch) | |
tree | a4f62f21210a3a09b889e69e793c8d92b1ce3764 | |
parent | becfaac2ceb06c8c05019cb614dd8699ebfedc68 (diff) | |
download | qtwebengine-chromium-f11657ed645939c383c9955fd32daf52437f2ec2.tar.gz |
[Backport] Fix for CVE-2020-6423
Use KeepSelfAlive on AudioContext to keep it alive until rendering stops
When an ExecutionContext is abruptly/unexpectedly destroyed (e.g.
shutting down of document or iframe), an AudioContext can also
go away. This type of shutdown can be problematic because the render
thread still might be touching resources in the AudioContext allocated
by the main thread.
This CL introduces a self-referencing pointer to the AudioContext,
and it is cleared after the underlying render thread is stopped. In
that way, the destruction of AudioContext can be done safely.
(cherry picked from commit 85f708fa7ab898c7ae678c0b8a270105be6bbb4e)
Test: Locally confirmed the repro case doesn't crash (UAP) after 1hr.
Bug: 1043446
Change-Id: I2e40b7d58ca9d647eed8a5971fc69dc87ee3d1fe
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
3 files changed, 27 insertions, 4 deletions
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc index 93bc73d73f1..71a1013fdb2 100644 --- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc @@ -116,7 +116,8 @@ AudioContext* AudioContext::Create(Document& document, AudioContext::AudioContext(Document& document, const WebAudioLatencyHint& latency_hint) : BaseAudioContext(&document, kRealtimeContext), - context_id_(g_context_id++) { + context_id_(g_context_id++), + keep_alive_(this) { destination_node_ = DefaultAudioDestinationNode::Create(this, latency_hint); switch (GetAutoplayPolicy()) { @@ -143,7 +144,7 @@ void AudioContext::Uninitialize() { DCHECK(IsMainThread()); DCHECK_NE(g_hardware_context_count, 0u); --g_hardware_context_count; - + StopRendering(); DidClose(); RecordAutoplayMetrics(); BaseAudioContext::Uninitialize(); @@ -315,14 +316,26 @@ bool AudioContext::IsContextClosed() const { return close_resolver_ || BaseAudioContext::IsContextClosed(); } +void AudioContext::StartRendering() { + DCHECK(IsMainThread()); + + if (!keep_alive_) + keep_alive_ = this; + BaseAudioContext::StartRendering(); +} + void AudioContext::StopRendering() { DCHECK(IsMainThread()); DCHECK(destination()); - if (ContextState() == kRunning) { + // It is okay to perform the following on a suspended AudioContext because + // this method gets called from ExecutionContext::ContextDestroyed() meaning + // the AudioContext is already unreachable from the user code. + if (ContextState() != kClosed) { destination()->GetAudioDestinationHandler().StopRendering(); SetContextState(kSuspended); GetDeferredTaskHandler().ClearHandlersToBeDeleted(); + keep_alive_.Clear(); } } diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h index 3d253775521..9680cfdc3e4 100644 --- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h +++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h @@ -11,6 +11,7 @@ #include "third_party/blink/renderer/modules/webaudio/audio_context_options.h" #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/self_keep_alive.h" namespace blink { @@ -104,6 +105,13 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext { // Record the current autoplay metrics. void RecordAutoplayMetrics(); + // Starts rendering via AudioDestinationNode. This sets the self-referencing + // pointer to this object. + void StartRendering() override; + + // Called when the context is being closed to stop rendering audio and clean + // up handlers. This clears the self-referencing pointer, making this object + // available for the potential GC. void StopRendering(); void DidClose(); @@ -126,6 +134,8 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext { // Records if start() was ever called for any source node in this context. bool source_node_started_ = false; + + SelfKeepAlive<AudioContext> keep_alive_; }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h index 10c4dc3b0eb..02e6a75b681 100644 --- a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h +++ b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h @@ -281,7 +281,7 @@ class MODULES_EXPORT BaseAudioContext DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange); - void StartRendering(); + virtual void StartRendering(); void NotifyStateChange(); |