summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-04-17 15:07:31 +0200
committerMichal Klocek <michal.klocek@qt.io>2020-06-05 10:00:25 +0000
commitf11657ed645939c383c9955fd32daf52437f2ec2 (patch)
treea4f62f21210a3a09b889e69e793c8d92b1ce3764
parentbecfaac2ceb06c8c05019cb614dd8699ebfedc68 (diff)
downloadqtwebengine-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>
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h2
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();