summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHongchan Choi <hongchan@chromium.org>2024-01-12 22:57:22 +0000
committerMichael BrĂ¼ning <michael.bruning@qt.io>2024-02-07 21:52:14 +0000
commitf1ef87d506845dd62bb0802e80092d53100222f4 (patch)
treee2156c58f98451f1509134dd440a8609eda50e3c
parent733825e343b7b43d739555c8446854fc9402e269 (diff)
[Backport] CVE-2024-0807: Use after free in WebAudio
Manual cherry-pick of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/5225523: Update rendering state of automatic pull nodes before graph rendering M114 merge issues: third_party/blink/renderer/modules/webaudio/analyser_handler.cc: PullInputs/CheckNumberOfChannelsForInput not present in 114. In rare cases, the rendering fan out count of automatic pull node does not match the main thread fan out count after recreating a platform destination followed by disconnection. This CL forces the update of the rendering state of automatic pull nodes before graph rendering to make sure that fan out counts are synchronized before executing the audio processing function call. NOTE: This change makes 2 WPTs fail. The follow-up work is planned to address them once this patch is merged. Bug: 1505080 Test: Locally confirmed that ASAN doesn't crash on all repro cases. Change-Id: I6768cd8bc64525ea9d56a19b9c58439e9cdab9a8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5131958 Commit-Queue: Hongchan Choi <hongchan@chromium.org> Cr-Commit-Position: refs/heads/main@{#1246718} (cherry picked from commit f4bffa09b46c21147431179e1e6dd2b27bc35fbc) Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/537374 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc10
4 files changed, 34 insertions, 6 deletions
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
index cb281f5b728..9f515af5d9a 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
@@ -51,9 +51,11 @@ AnalyserHandler::~AnalyserHandler() {
}
void AnalyserHandler::Process(uint32_t frames_to_process) {
- AudioBus* output_bus = Output(0).Bus();
+ DCHECK(Context()->IsAudioThread());
- if (!IsInitialized()) {
+ AudioBus* output_bus = Output(0).RenderingFanOutCount() > 0 ? Output(0).Bus() : nullptr;
+
+ if (!IsInitialized() && output_bus) {
output_bus->Zero();
return;
}
@@ -65,6 +67,11 @@ void AnalyserHandler::Process(uint32_t frames_to_process) {
// Analyser reflects the current input.
analyser_.WriteInput(input_bus.get(), frames_to_process);
+ // Subsequent steps require `output_bus` to be valid.
+ if (!output_bus) {
+ return;
+ }
+
if (!Input(0).IsConnected()) {
// No inputs, so clear the output, and propagate the silence hint.
output_bus->Zero();
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
index eccf002b6da..5f18c4cd12d 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
@@ -102,11 +102,16 @@ void AudioWorkletHandler::Process(uint32_t frames_to_process) {
// We also need to check if the global scope is valid before we request
// the rendering in the AudioWorkletGlobalScope.
if (processor_ && !processor_->hasErrorOccurred()) {
- // If the input is not connected, inform the processor with nullptr.
- for (unsigned i = 0; i < NumberOfInputs(); ++i)
+ // If the input or the output is not connected, inform the processor with
+ // nullptr.
+ for (unsigned i = 0; i < NumberOfInputs(); ++i) {
inputs_[i] = Input(i).IsConnected() ? Input(i).Bus() : nullptr;
- for (unsigned i = 0; i < NumberOfOutputs(); ++i)
- outputs_[i] = WrapRefCounted(Output(i).Bus());
+ }
+ for (unsigned i = 0; i < NumberOfOutputs(); ++i) {
+ outputs_[i] = Output(i).RenderingFanOutCount() > 0
+ ? WrapRefCounted(Output(i).Bus())
+ : nullptr;
+ }
for (const auto& param_name : param_value_map_.Keys()) {
auto* const param_handler = param_handler_map_.at(param_name);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
index e68b1c1b2f6..84ab72b9774 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
@@ -343,6 +343,12 @@ void AudioWorkletProcessor::CopyArrayBuffersToPort(
for (uint32_t bus_index = 0; bus_index < audio_port.size(); ++bus_index) {
const scoped_refptr<AudioBus>& audio_bus = audio_port[bus_index];
+
+ // nullptr indicates the output bus is not connected. Do not proceed.
+ if (!audio_bus) {
+ break;
+ }
+
for (uint32_t channel_index = 0;
channel_index < audio_bus->NumberOfChannels(); ++channel_index) {
const v8::ArrayBuffer::Contents& contents =
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc b/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
index 76aa9acccd3..88e4228caef 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
@@ -169,6 +169,16 @@ void DeferredTaskHandler::UpdateAutomaticPullNodes() {
if (try_locker.Locked()) {
CopyToVector(automatic_pull_handlers_,
rendering_automatic_pull_handlers_);
+
+ // In rare cases, it is possible for automatic pull nodes' output bus
+ // to become stale. Make sure update their rendering output counts.
+ // crbug.com/1505080.
+ for (auto& handler : rendering_automatic_pull_handlers_) {
+ for (unsigned i = 0; i < handler->NumberOfOutputs(); ++i) {
+ handler->Output(i).UpdateRenderingState();
+ }
+ }
+
automatic_pull_handlers_need_updating_ = false;
}
}