CVE-2026-13884
Overview
Files Changed
chromecast/media/cma/backend/mixer/mixer_input_connection.cc
Patch
From 6183ca67a491323e74fd5352c66a55a3fa2a2eef Mon Sep 17 00:00:00 2001
From: Simeon Anfinrud <sanfin@chromium.org>
Date: Wed, 06 May 2026 13:24:22 -0700
Subject: [PATCH] [chromecast] Fix Heap buffer overflow in CreateBufferPool
Use base::CheckedNumeric<int> to calculate buffer_size to prevent integer truncation and heap overflow.
Bug: 500077014
Test: Compiled and passed unit tests.
Change-Id: I5c14abbd866418759033f2f5668d4244c3aa9b17
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7765498
Auto-Submit: Simeon Anfinrud <sanfin@chromium.org>
Reviewed-by: Sandeep Vijayasekar <sandv@google.com>
Commit-Queue: Simeon Anfinrud <sanfin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1626413}
---
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
index 0b30a27..062f3677 100644
--- a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
+++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
@@ -17,6 +17,7 @@
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/numerics/checked_math.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
@@ -461,8 +462,17 @@
DCHECK_GT(frame_count, 0);
buffer_pool_frames_ = frame_count;
- int converted_buffer_size =
- kAudioMessageHeaderSize + num_channels_ * sizeof(float) * frame_count;
+ base::CheckedNumeric<int> size(frame_count);
+ size *= sizeof(float);
+ size *= num_channels_;
+ size += kAudioMessageHeaderSize;
+
+ if (!size.IsValid()) {
+ LOG(ERROR) << "Buffer size is invalid.";
+ OnConnectionError();
+ return;
+ }
+ int converted_buffer_size = size.ValueOrDie();
buffer_pool_ = base::MakeRefCounted<IOBufferPool>(
converted_buffer_size, std::numeric_limits<size_t>::max(),
true /* threadsafe */);
Original Bug Report
Heap buffer overflow in Chromecast mixer due to integer truncation in CreateBufferPool
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the security team.
Overview: An integer truncation vulnerability in MixerInputConnection::CreateBufferPool allows an unauthenticated local attacker to create an undersized IOBufferPool. By supplying a large fill_size_frames parameter, the calculated buffer size overflows and truncates. Subsequent audio data processing results in a heap buffer overflow with attacker-controlled content in the cast_shell process.
Affected files:
chromecast/media/cma/backend/mixer/mixer_input_connection.ccchromecast/media/audio/net/io_buffer_pool.ccchromecast/media/audio/net/audio_socket.cc
Estimated timestamp from git blame: 2019-11-14
Summary
A potential integer truncation vulnerability exists in the Chromecast mixer service’s buffer management logic. When processing OutputStreamParams, the fill_size_frames parameter is used to calculate the size of an IOBufferPool. Due to a narrowing conversion from size_t to int and a lack of bounds checking, a large fill_size_frames value results in a very small buffer allocation. Subsequent audio data messages (kAudio) can then trigger a linear heap buffer overflow when converting and copying data into these undersized buffers.
Technical Details
1. Vulnerable Path and Entry Point
The mixer service listens on an unauthenticated abstract-namespace Unix-domain socket (\0/tmp/mixer-service). The credential callback in chromecast/media/audio/net/audio_socket_service_uds.cc always returns true, allowing any local process to connect.
Upon connection, a peer sends a Generic proto message containing OutputStreamParams. MixerServiceReceiver::CreateOutputStream constructs a MixerInputConnection using these params without sufficient validation of the fill_size_frames field.
2. Integer Truncation in CreateBufferPool
In MixerInputConnection::CreateBufferPool (chromecast/media/cma/backend/mixer/mixer_input_connection.cc):
void MixerInputConnection::CreateBufferPool(int frame_count) {
// ...
int converted_buffer_size =
kAudioMessageHeaderSize + num_channels_ * sizeof(float) * frame_count;
// ...
buffer_pool_ = base::MakeRefCounted<IOBufferPool>(converted_buffer_size, ...);
buffer_pool_frames_ = frame_count;
}
In the expression for converted_buffer_size, sizeof(float) is of type size_t. Consequently, the multiplication is performed using 64-bit unsigned arithmetic.
If an attacker configures num_channels = 2 and frame_count = 0x20000002 (536870914), the calculation is 16 + 2 * 4 * 0x20000002 = 0x100000020.
This size_t value (0x100000020) is then implicitly narrowed to a signed 32-bit int, resulting in converted_buffer_size = 32.
An IOBufferPool is created with a data block size of exactly 32 bytes, while buffer_pool_frames_ correctly records the massive 0x20000002 frame count.
3. Heap Buffer Overflow
When a subsequent kAudio message is received, it is processed by MixerInputConnection::HandleAudioData. Assuming the attacker sends 1024 bytes of 16-bit stereo audio (SAMPLE_FORMAT_INT16_I), the following occurs:
- The code calculates
num_frames = 256. - It checks if the pool needs resizing:
if (num_frames > buffer_pool_frames_). Since256 > 536870914is false, it incorrectly bypasses resizing the pool. - A 32-byte buffer is retrieved from the pool:
auto buffer = buffer_pool_->GetBuffer(). - The destination pointer is calculated:
float* dest = reinterpret_cast<float*>(buffer->data() + kAudioMessageHeaderSize);. With the 16-byte header,destpoints 16 bytes into the 32-byte buffer. ConvertInterleavedDatais called. It iterates through the 256 frames for both channels, writing 32-bit floats.
For 256 frames of stereo audio, the function writes 2048 bytes (256 * 2 * 4) to dest. Because the underlying buffer only has 16 bytes of remaining capacity, this results in a 2032-byte linear heap buffer overflow with attacker-controlled data.
Impact
This vulnerability allows for a fully controlled linear heap overflow in the unsandboxed cast_shell process. An attacker can control both the length and the content of the overflow. While it requires the ability to connect to a local Unix-domain socket, it provides a powerful primitive for Privilege Escalation or Remote Code Execution (if chained with a mechanism to reach the socket).
Potential Exploitation Steps (Theoretical)
Note: These steps are proposed and have not been executed by a proof-of-concept.
- Connect to the abstract socket
\0/tmp/mixer-servicefrom a local unprivileged process. - Send a framed
Genericmetadata message withOutputStreamParamsset to:num_channels=2,sample_format=SAMPLE_FORMAT_INT16_I,fill_size_frames=0x20000002. - Immediately follow this with a
kAudiomessage containing 1024 bytes of arbitrary payload. - The
cast_shellprocess will experience a heap buffer overflow during the processing of thekAudiomessage.
Proposed Fix
- Use Checked Math: Modify the calculation of
converted_buffer_sizeto usebase::CheckedNumericto ensure that overflows during the multiplication and addition are caught. - Appropriate Types: Change the type of
converted_buffer_sizetosize_tto avoid implicit narrowing conversions. - Bounds Validation: Add explicit bounds validation to
GetFillSizeor when parsingOutputStreamParamsto reject unreasonably large frame counts that exceed practical audio buffering limits.
Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.