High chrome Integer Overflow 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInteger overflow in Mojo
DescriptionInteger overflow in Mojo
ComponentMojo
Bug ClassInteger Overflow
Tracker513138301
Fix commit1598e0f19160 (chromium/src) +25/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-25

Changed Functions

FunctionChangeNotes
if
mojo/core/channel.cc
modified
if
mojo/core/channel_fuchsia.cc
modified
if
mojo/core/channel_posix.cc
modified
if
mojo/core/channel_win.cc
modified

Files Changed

  • mojo/core/channel.cc
  • mojo/core/channel_fuchsia.cc
  • mojo/core/channel_posix.cc
  • mojo/core/channel_win.cc
From 1598e0f1916030a6a9bd2ac6b878b48a696b35e5 Mon Sep 17 00:00:00 2001
From: Elly <ellyjones@chromium.org>
Date: Tue, 16 Jun 2026 08:04:55 -0700
Subject: [PATCH] mojo: don't overflow computation of channel read buffer size

I am fairly confident this isn't exploitable (see rationale on the bug)
but to make the code more obviously correct, add a check for overflow
and error handling up the call stack.

Fixed: 513138301
Change-Id: Ie2093dc08c2761951e4988ef283e21662de3bfd8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7946296
Commit-Queue: Elly <ellyjones@chromium.org>
Reviewed-by: Fred Shih <ffred@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1647564}
---

diff --git a/mojo/core/channel.cc b/mojo/core/channel.cc
index 32a35844..1131bb4a 100644
--- a/mojo/core/channel.cc
+++ b/mojo/core/channel.cc
@@ -939,7 +939,12 @@
 
   // Ensures the ReadBuffer has enough contiguous space allocated to hold
   // |num_bytes| more bytes; returns the address of the first available byte.
+  // If computing the new size overflows, returns nullptr.
   char* Reserve(size_t num_bytes) {
+    const auto new_size = base::CheckAdd(num_bytes, size_);
+    if (!new_size.IsValid()) {
+      return nullptr;
+    }
     if (num_occupied_bytes_ + num_bytes > size_) {
       size_ = std::max(static_cast<size_t>(size_ * kGrowthFactor),
                        num_occupied_bytes_ + num_bytes);
diff --git a/mojo/core/channel_fuchsia.cc b/mojo/core/channel_fuchsia.cc
index b7a75b5..adedc2b4 100644
--- a/mojo/core/channel_fuchsia.cc
+++ b/mojo/core/channel_fuchsia.cc
@@ -310,6 +310,13 @@
     do {
       buffer_capacity = next_read_size;
       char* buffer = GetReadBuffer(&buffer_capacity);
+      // A null buffer means the size computation for the new buffer overflowed
+      // so mark the connection as broken and bail.
+      if (!buffer) {
+        read_error = true;
+        validation_error = true;
+        break;
+      }
       DCHECK_GT(buffer_capacity, 0u);
 
       uint32_t bytes_read = 0;
diff --git a/mojo/core/channel_posix.cc b/mojo/core/channel_posix.cc
index 40aafd68..bdc9a5a 100644
--- a/mojo/core/channel_posix.cc
+++ b/mojo/core/channel_posix.cc
@@ -291,6 +291,13 @@
   do {
     buffer_capacity = next_read_size;
     char* buffer = GetReadBuffer(&buffer_capacity);
+    // A null buffer means that computing the read size overflowed, which means
+    // we received a malformed message; bail.
+    if (!buffer) {
+      read_error = true;
+      validation_error = true;
+      break;
+    }
     DCHECK_GT(buffer_capacity, 0u);
 
     std::vector<base::ScopedFD> incoming_fds;
diff --git a/mojo/core/channel_win.cc b/mojo/core/channel_win.cc
index 8c87829..f4f3e83 100644
--- a/mojo/core/channel_win.cc
+++ b/mojo/core/channel_win.cc
@@ -306,6 +306,12 @@
 
     size_t buffer_capacity = next_read_size_hint;
     char* buffer = GetReadBuffer(&buffer_capacity);
+    // A null buffer means the size computation for the buffer overflowed;
+    // break the connection.
+    if (!buffer) {
+      OnError(Error::kDisconnected);
+      return;
+    }
     DCHECK_GT(buffer_capacity, 0u);
 
     BOOL ok =
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential 32-bit Integer Overflow in Mojo Channel::ReadBuffer::Reserve leading to Heap OOB Write

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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A potential 32-bit integer overflow exists in Mojo’s ReadBuffer::Reserve function, allowing an attacker to bypass buffer reallocation logic. This can result in an out-of-bounds heap write in the browser process when processing crafted IPC messages from a compromised renderer. The issue specifically affects 32-bit platforms where size_t is 32 bits.

Affected files:

  • mojo/core/channel.cc
  • mojo/core/channel_posix.cc
  • mojo/core/channel_win.cc
  • mojo/core/channel.h

Estimated timestamp from git blame: 2022-08-15

Summary

A potential integer overflow vulnerability has been identified in mojo/core/channel.cc. On 32-bit architectures, the Channel::ReadBuffer::Reserve method can be induced to return a pointer that is out-of-bounds of its backing heap allocation. This occurs because the calculation used to determine if the buffer should grow can overflow, leading the code to incorrectly conclude that sufficient space is already available.

Root Cause Analysis

In mojo/core/channel.cc, the Channel::ReadBuffer::Reserve(size_t num_bytes) method is responsible for ensuring the read buffer has enough contiguous space for incoming data:

char* Reserve(size_t num_bytes) {
  if (num_occupied_bytes_ + num_bytes > size_) {
    // ... reallocation logic ...
  }
  return data_.subspan(num_occupied_bytes_).data();
}

On 32-bit systems, size_t is 32 bits. An attacker can control num_bytes (via a Mojo message header parsed in TryDispatchMessage) by providing a value such that num_occupied_bytes_ + num_bytes overflows and wraps around. For example, if the current buffer is full (num_occupied_bytes_ == size_ == 4096), and num_bytes is 0xFFFFFFFF, the sum wraps to 4095. Since 4095 > 4096 is false, the reallocation is skipped.

Reserve then returns data_.subspan(4096).data(), which is a pointer to the first byte immediately following the 4096-byte allocation.

Exploitation Potential

The transport layer (e.g., ChannelPosix or ChannelWin) uses the pointer returned by Reserve to read data from the IPC socket. In ChannelPosix::OnFdReadable:

char* buffer = GetReadBuffer(&buffer_capacity);
// ...
ssize_t read_result = SocketRecvmsg(socket_.get(), buffer, buffer_capacity, ...);

Here, buffer will be the out-of-bounds pointer, and buffer_capacity will be the original large num_bytes value. This allows a compromised renderer to perform a linear heap overflow in the unsandboxed browser process, which can be leveraged for a sandbox escape.

Suggested Fix

Use base::CheckedNumeric to perform the addition and comparison in ReadBuffer::Reserve safely to detect and handle potential overflows.

char* Reserve(size_t num_bytes) {
  base::CheckedNumeric<size_t> required_size = num_occupied_bytes_;
  required_size += num_bytes;
  if (!required_size.IsValid() || required_size.ValueOrDie() > size_) {
    // ... reallocation logic ...
  }
  return data_.subspan(num_occupied_bytes_).data();
}

Suggested Reproduction Steps

Note: These steps are theoretical as they have not been validated with a running PoC.

  1. Target a 32-bit Chrome/WebView build (e.g., 32-bit Android or Windows x86).
  2. From a compromised renderer, send a Mojo message where the header specifies a very large size (e.g., 0xFFFFFFFF).
  3. Ensure the browser-side Mojo Channel has some data already in its ReadBuffer such that the addition overflows.
  4. Send the overflow payload over the IPC channel. The browser should write this data past the end of the ReadBuffer allocation.

Evaluated with Chrome root at commit: b3153093eb3c78c3e88ccf562bcbc20437a04b0e


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

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