Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactHeap buffer overflow in Chromecast
DescriptionHeap buffer overflow in Chromecast
ComponentChromecast
Bug ClassOOB
Tracker500077014
Fix commit6183ca67a491 (chromium/src) +12/-2
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Files Changed

  • chromecast/media/cma/backend/mixer/mixer_input_connection.cc
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 */);
Loading diff…

Original Bug Report

reported by vm...@google.com

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.cc
  • chromecast/media/audio/net/io_buffer_pool.cc
  • chromecast/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:

  1. The code calculates num_frames = 256.
  2. It checks if the pool needs resizing: if (num_frames > buffer_pool_frames_). Since 256 > 536870914 is false, it incorrectly bypasses resizing the pool.
  3. A 32-byte buffer is retrieved from the pool: auto buffer = buffer_pool_->GetBuffer().
  4. The destination pointer is calculated: float* dest = reinterpret_cast<float*>(buffer->data() + kAudioMessageHeaderSize);. With the 16-byte header, dest points 16 bytes into the 32-byte buffer.
  5. ConvertInterleavedData is 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.

  1. Connect to the abstract socket \0/tmp/mixer-service from a local unprivileged process.
  2. Send a framed Generic metadata message with OutputStreamParams set to: num_channels=2, sample_format=SAMPLE_FORMAT_INT16_I, fill_size_frames=0x20000002.
  3. Immediately follow this with a kAudio message containing 1024 bytes of arbitrary payload.
  4. The cast_shell process will experience a heap buffer overflow during the processing of the kAudio message.

Proposed Fix

  1. Use Checked Math: Modify the calculation of converted_buffer_size to use base::CheckedNumeric to ensure that overflows during the multiplication and addition are caught.
  2. Appropriate Types: Change the type of converted_buffer_size to size_t to avoid implicit narrowing conversions.
  3. Bounds Validation: Add explicit bounds validation to GetFillSize or when parsing OutputStreamParams to 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.

View on issue tracker