diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-04-17 15:07:31 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-04-20 11:07:01 +0000 |
commit | 580c53c725c07e0e49b66812d3c0e9edca976ae6 (patch) | |
tree | 1395192c920c48caa3be3177db1c91bb3691aa77 | |
parent | 55a8f34b5deaf20f6f81913a3beead8be1677690 (diff) | |
download | qtwebengine-chromium-580c53c725c07e0e49b66812d3c0e9edca976ae6.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: Raymond Toy <rtoy@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#742338}
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/branch-heads/4044@{#498}
Cr-Branched-From: a6d9daf149a473ceea37f629c41d4527bf2055bd-refs/heads/master@{#737173}
Reviewed-by: Kirill Burtsev <kirill.burtsev@qt.io>
3 files changed, 27 insertions, 5 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 f544a4658f3..6618c8d74bd 100644 --- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc @@ -132,7 +132,8 @@ AudioContext::AudioContext(Document& document, const WebAudioLatencyHint& latency_hint, base::Optional<float> sample_rate) : BaseAudioContext(&document, kRealtimeContext), - context_id_(g_context_id++) { + context_id_(g_context_id++), + keep_alive_(PERSISTENT_FROM_HERE, this) { destination_node_ = RealtimeAudioDestinationNode::Create(this, latency_hint, sample_rate); @@ -169,13 +170,14 @@ AudioContext::AudioContext(Document& document, destination()->GetAudioDestinationHandler()); base_latency_ = destination_handler.GetFramesPerBuffer() / static_cast<double>(sampleRate()); + } void AudioContext::Uninitialize() { DCHECK(IsMainThread()); DCHECK_NE(g_hardware_context_count, 0u); --g_hardware_context_count; - + StopRendering(); DidClose(); RecordAutoplayMetrics(); BaseAudioContext::Uninitialize(); @@ -358,14 +360,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(kClosed); 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 6e3455921f5..d3e521f1291 100644 --- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h +++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h @@ -13,6 +13,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 { @@ -133,8 +134,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. + // up handlers. This clears the self-referencing pointer, making this object + // available for the potential GC. void StopRendering(); // Called when suspending the context to stop reundering audio, but don't @@ -196,6 +202,8 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext { // determine audibility on render quantum boundaries, so counting quanta is // all that's needed. size_t total_audible_renders_ = 0; + + 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 a99b2dddad4..051890e2742 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 @@ -285,7 +285,7 @@ class MODULES_EXPORT BaseAudioContext DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange, kStatechange) - void StartRendering(); + virtual void StartRendering(); void NotifyStateChange(); |