CVE-2026-11165
Overview
Files Changed
media/midi/midi_service.cc
Patch
From 6ed6fc7c9055fda21cb152f414e55e65db5c4927 Mon Sep 17 00:00:00 2001 From: Takashi Toyoshima <[email protected]> Date: Tue, 14 Apr 2026 17:34:43 -0700 Subject: [PATCH] WebMIDI: Fix Use-After-Free in MidiManagerMac on iOS On iOS, MidiService::EndSession destroys the MidiManager instance when all sessions end. However, CoreMIDI callbacks can still be invoked on high-priority threads, leading to UAF. This CL changes the condition in MidiService::EndSession to not destroy the MidiManager on Apple platforms (including iOS), aligning with the existing behavior on macOS. As current production does not use Blink, this does not affect the real production yet. Bug: 502099949 Change-Id: I9b02f1f233d44b043a907dd3f4b2a12f7fc30224 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7761847 Reviewed-by: Michael Wilson <[email protected]> Commit-Queue: Takashi Toyoshima <[email protected]> Cr-Commit-Position: refs/heads/main@{#1614815} --- diff --git a/media/midi/midi_service.cc b/media/midi/midi_service.cc index 502ec97..50557db4 100644 --- a/media/midi/midi_service.cc +++ b/media/midi/midi_service.cc @@ -72,7 +72,7 @@ // MIDIClientCreate starts failing with the OSStatus -50 after repeated calls // of MIDIClientDispose. It rarely happens, but once it starts, it will never // get back to be sane. See https://crbug.com/718140. -#if !BUILDFLAG(IS_MAC) +#if !BUILDFLAG(IS_APPLE) if (!manager_->HasOpenSession()) { // MidiManager for each platform should be able to shutdown correctly even // if following destruction happens in the middle of StartInitialization().
Original Bug Report
Potential Use-After-Free in MidiManagerMac on iOS via CoreMIDI callback race
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 Chrome Security team.
Overview: A Use-After-Free vulnerability exists in MidiManagerMac on Blink-on-iOS builds due to a race condition between object destruction and asynchronous CoreMIDI callbacks. High-priority OS threads may attempt to access the manager instance after it has been freed when a Web MIDI session is terminated. Because the dangling pointer round-trips through a C API as a void*, it is not protected by MiraclePtr.
Affected files:
media/midi/midi_manager_mac.ccmedia/midi/midi_service.ccmedia/midi/task_service.cc
Estimated timestamp from git blame: 2022-01-15
Summary
A Use-After-Free (UAF) vulnerability has been identified in the MidiManagerMac class, specifically affecting Blink-on-iOS builds. The issue stems from a lack of synchronization between the destruction of the MidiManagerMac instance and high-priority OS threads managed by CoreMIDI. When a Web MIDI session ends, the manager may be destroyed while a callback is still executing, leading to a browser-process UAF that bypasses MiraclePtr.
Vulnerability Details
In media/midi/midi_service.cc, the MidiService::EndSession method attempts to destroy the MidiManager instance when the last session is closed. This logic is gated by #if !BUILDFLAG(IS_MAC). On macOS, this prevents destruction to avoid known CoreMIDI bugs. However, on iOS Blink builds, BUILDFLAG(IS_MAC) evaluates to false, causing manager_.reset() to be called.
During destruction, ~MidiManagerMac calls TaskService::UnbindInstance(). While TaskService correctly blocks the calling thread to wait for tasks scheduled via TaskService::PostBoundTask to complete, it does not track or fence raw OS callbacks. MidiManagerMac registers ReadMidiDispatch as a callback with CoreMIDI, passing a raw this pointer as a void* refcon (see media/midi/midi_manager_mac.cc).
ReadMidiDispatch is invoked on a separate high-priority thread owned by Apple’s CoreMIDI framework. Because MIDIClientDispose (called in the destructor) is not guaranteed to synchronously fence in-flight MIDIReadProc invocations, a race condition occurs. If a MIDI packet is processed while the destructor is running or immediately after, the CoreMIDI thread will execute ReadMidiDispatch, which casts the stale void* refcon back to a MidiManagerMac* and calls manager->ReceiveMidiData().
Inside MidiManager::ReceiveMidiData (media/midi/midi_manager.cc), the code immediately accesses internal members lock_ and clients_. If the freed memory has been reallocated with attacker-controlled data, the attacker can supply a fake clients_ set and achieve arbitrary remote code execution via a virtual method call on a fake client pointer.
Furthermore, because the pointer round-trips to the C API as a void*, MiraclePtr (BackupRefPtr) is completely bypassed and does not quarantine the allocation or crash on access.
Impact
This is a potential browser-process Use-After-Free. An attacker who has been granted Web MIDI permissions could potentially exploit this race to achieve remote code execution (RCE) in the context of the browser process, leading to a full sandbox escape on iOS.
Potential Exploitation Steps
Note: These steps are based on static analysis; our tooling cannot run live code execution.
- Setup: The user must have an active, streaming MIDI source connected (e.g., a BLE-MIDI controller sending periodic active sensing messages).
- Permission: An attacker’s malicious webpage calls
navigator.requestMIDIAccess(), and the user grants permission. - Session Initiation:
MidiServiceallocates aMidiManagerMacobject, registeringReadMidiDispatchwith CoreMIDI. - Session Termination: The attacker’s webpage intentionally closes the MIDI session (e.g., by dropping references or navigating away).
- Destruction Race: The browser process executes
manager_.reset().MidiManagerMacis freed. - Heap Grooming: The attacker immediately executes a heap grooming payload (e.g., using WebAssembly) to reallocate the freed
MidiManagerMacmemory space with attacker-controlled bytes, crafting a fakelock_andclients_set. - Callback Execution: The CoreMIDI thread concurrently executes
ReadMidiDispatch, casting the danglingvoid*refcon back toMidiManagerMac*and callingReceiveMidiData. - RCE:
ReceiveMidiDataattempts to iterate over the fakeclients_set and calls a virtual method on a fake client, redirecting execution to the attacker’s payload.
Suggested Fix
To fix this issue, MidiManagerMac destruction on iOS should be handled the same way it is on macOS. Update the preprocessor check in media/midi/midi_service.cc to use BUILDFLAG(IS_APPLE) instead of BUILDFLAG(IS_MAC):
// In media/midi/midi_service.cc:75
#if !BUILDFLAG(IS_APPLE)
if (!manager_->HasOpenSession()) {
manager_.reset();
// ...
}
#endif
This ensures the manager is kept alive until the service shuts down, avoiding the UAF entirely.
Evaluated with Chrome root at commit: 096fc8fdbfacf2546485756d03f160a3d04fcc9b
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.