Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactOut of bounds write in Media
DescriptionOut of bounds write in Media
ComponentMedia
Bug ClassOOB
Tracker496607380
Fix commit497faf3e01db (chromium/src) +3/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-05

Changed Functions

FunctionChangeNotes
for
media/base/mac/channel_layout_util_mac.cc
modified
if
media/base/mac/channel_layout_util_mac.cc
modified

Files Changed

  • media/base/mac/channel_layout_util_mac.cc
From 497faf3e01dbeb2bf1e584c161afb6cda46f2eec Mon Sep 17 00:00:00 2001
From: Syed AbuTalib <[email protected]>
Date: Mon, 30 Mar 2026 16:50:15 -0700
Subject: [PATCH] Skip orders past input_channels

It is unnecessary to test for orders past the total # of channels,
continue if so.

Bug: 496607380
Change-Id: I1525fdec20d49978233f995900b9a865523203dd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7706421
Commit-Queue: Syed AbuTalib <[email protected]>
Reviewed-by: Thomas Guilbert <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1607459}
---

diff --git a/media/base/mac/channel_layout_util_mac.cc b/media/base/mac/channel_layout_util_mac.cc
index 88d4b100..82424db 100644
--- a/media/base/mac/channel_layout_util_mac.cc
+++ b/media/base/mac/channel_layout_util_mac.cc
@@ -144,7 +144,9 @@
   } else {
     for (int ch = 0; ch <= CHANNELS_MAX; ++ch) {
       const int order = ChannelOrder(input_layout, static_cast<Channels>(ch));
-      if (order == -1) {
+      // We only allocate up to `input_channels`, skip if past what was
+      // allocated for.
+      if (order == -1 || order >= input_channels) {
         continue;
       }
       UNSAFE_TODO(descriptions[order].mChannelLabel) =
Loading diff…

Original Bug Report

reported by [email protected]

Potential Heap OOB Write in ChannelLayoutToAudioChannelLayout via CHANNEL_LAYOUT_5_1_4_DOWNMIX

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A compromised renderer can bypass audio parameter validation by requesting the CHANNEL_LAYOUT_5_1_4_DOWNMIX layout with a mismatched channel count (e.g., 1). This bypasses standard validation and reaches the audio service on macOS, where ChannelLayoutToAudioChannelLayout allocates an undersized buffer based on the requested channel count but attempts to write up to 6 channels’ worth of data. This results in a fixed-stride out-of-bounds write on the heap, potentially leading to arbitrary code execution within the sandboxed audio service utility process.

Affected files:

  • media/base/mac/channel_layout_util_mac.cc
  • media/base/channel_layout.cc
  • media/base/audio_parameters.cc
  • media/audio/apple/audio_auhal.cc
  • media/audio/mac/audio_manager_mac.cc
  • media/audio/mac/avfoundation_output_stream.mm

Estimated timestamp from git blame: 2023-04-27

Summary

A potential heap-based out-of-bounds (OOB) write vulnerability exists in ChannelLayoutToAudioChannelLayout within media/base/mac/channel_layout_util_mac.cc. A compromised renderer can leverage a special-case validation bypass for the CHANNEL_LAYOUT_5_1_4_DOWNMIX layout to send crafted AudioParameters that trigger this overflow in the audio service utility process on macOS.

(Note: This report is generated by an LLM agent that cannot yet run code. The steps below are a potential attack path based on static analysis.)

Vulnerability Details

In media/base/mac/channel_layout_util_mac.cc, the function ChannelLayoutToAudioChannelLayout allocates an AudioChannelLayout structure using a std::vector<uint8_t> as backing storage. The size of this allocation is determined by the input_channels parameter:

int output_layout_size =
    offsetof(AudioChannelLayout, mChannelDescriptions[input_channels]);
auto new_layout =
    std::make_unique<ScopedAudioChannelLayout>(output_layout_size);

However, in the subsequent loop that populates the mChannelDescriptions array, the code uses ChannelOrder(input_layout, ch) to determine the destination index for each channel. For CHANNEL_LAYOUT_5_1_4_DOWNMIX, the predefined channel ordering in media/base/channel_layout.cc maps channels to indices up to 5 (mapping to 6 channels). If input_channels is less than 6 (e.g., input_channels=1), the loop writes to descriptions[order] without any bounds checking, resulting in an OOB write beyond the allocated buffer.

Specifically, when input_channels=1, the vector is sized for a single AudioChannelDescription. The loop then writes to descriptions[0..5] based on the ordering for CHANNEL_LAYOUT_5_1_4_DOWNMIX. Since each description is 20 bytes and the code writes the first 8 bytes (label and flags), this results in multiple 8-byte OOB writes at a 20-byte stride, extending up to approximately 88 bytes past the allocated buffer.

Validation Bypass

The malicious AudioParameters are able to reach the vulnerable function due to explicit special-casing of CHANNEL_LAYOUT_5_1_4_DOWNMIX in media/base/audio_parameters.cc. The AudioParameters::IsValid() function exempts this layout from the standard check that channels() must match ChannelLayoutToChannelCount(channel_layout()):

         (channel_layout() == CHANNEL_LAYOUT_DISCRETE ||
          channel_layout() == CHANNEL_LAYOUT_5_1_4_DOWNMIX ||
          channels() == ChannelLayoutToChannelCount(channel_layout()));

This bypass allows a compromised renderer to pass Mojo validation (ParamTraits<media::AudioParameters>::Read) with an AudioParameters object containing CHANNEL_LAYOUT_5_1_4_DOWNMIX and channels=1.

Potential Attack Path

  1. Mojo Connection: A compromised renderer process obtains a Mojo connection to blink::mojom::RendererAudioOutputStreamFactory.
  2. Requesting Audio Stream: The renderer calls RequestDeviceAuthorization for the default output device to receive an AudioOutputStreamProvider.
  3. Crafting Malicious AudioParameters: The renderer calls Acquire() with crafted media::AudioParameters: format=AUDIO_PCM_LOW_LATENCY, channel_layout=CHANNEL_LAYOUT_5_1_4_DOWNMIX (enum value 33), and channels=1 (or any value < 6).
  4. Forwarding to Audio Service: The browser process deserializes the parameters, validates them successfully (due to the bypass), and forwards the stream creation request to the Audio Service via an AudioOutputStreamBroker.
  5. Audio Service Parameter Handling: In the Audio Service on macOS, AudioManagerMac::GetPreferredOutputStreamParameters preserves the malicious layout because channels=1 is typically less than or equal to the hardware channel count.
  6. Triggering the Bug: AUHALStream::Open (or AVFoundationOutputStream::Open) calls ChannelLayoutToAudioChannelLayout to configure the layout. This triggers the OOB write in the sandboxed audio service utility process.

Impact

An attacker with control over a renderer process can trigger a linear heap OOB write in the audio service utility process. While the values written are fixed (specific AudioChannelLabel constants and zeros), the attacker controls the size of the initial heap allocation (by varying channels from 1 to 5) and the timing. This allows them to place the buffer in different PartitionAlloc buckets and potentially overwrite specific fields in adjacent objects, leading to memory corruption and potentially arbitrary code execution within the sandboxed audio service process.

Of note, the presence of #pragma allow_unsafe_buffers in media/base/mac/channel_layout_util_mac.cc suppressed diagnostic warnings from the clang unsafe-buffers plugin that might have otherwise flagged this issue.

Suggested Fix

  1. Fix Validation: The bypass in AudioParameters::IsValid() should be re-evaluated. If CHANNEL_LAYOUT_5_1_4_DOWNMIX requires a custom number of channels, the acceptable range should be strictly enforced.
  2. Add Bounds Checking: In ChannelLayoutToAudioChannelLayout, add a bounds check to ensure that order is strictly less than input_channels before writing to the descriptions array. For example:
    const int order = ChannelOrder(input_layout, static_cast<Channels>(ch));
    if (order == -1 || order >= input_channels) {
      continue;
    }
    

Evaluated with Chrome root at commit: bb48272cafb7e24c93f55ef40da398cd206ee651


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. Please feel free to reach out to me if you have concerns or feedback.

View on issue tracker