CVE-2026-87464
Overview
Background
- ANGLE
- Chrome’s translation layer that implements the WebGL/OpenGL ES API on top of native graphics backends, including the GL backend where this bug lives.
- `TextureGL::setStorage()`
- the ANGLE GL-backend routine that allocates immutable texture storage in response to
glTexStorage3D-style calls. - `reattachTextureToFboAfterLayerIncrease`
- an ANGLE feature flag whose workaround forces framebuffers to re-bind to a texture after its layer count grows and its backing storage is reallocated.
- `TextureLayerCountIncreased`
- a
SubjectMessagebroadcast to observers (such as an attached FBO) signaling that a_2DArraytexture gained layers and must be re-attached to fresh storage.
Root Cause Analysis
When an FBO is attached to a layer of a gl::TextureType::_2DArray texture and the texture’s immutable storage is then (re)allocated through TextureGL::setStorage() with a larger size.depth (more array layers), the native GL driver allocates a new backing object, but the framebuffer attachment was left pointing at the old, now-freed storage. The pre-existing reattachTextureToFboAfterLayerIncrease workaround already emitted angle::SubjectMessage::TextureLayerCountIncreased on the mutable glTexImage3D path so observers would reattach, but setStorage() (the glTexStorage3D immutable path) never issued that notification, violating the invariant that any layer-count increase which reallocates storage must notify attached FBOs.
The fix mirrors the mutable-path logic inside setStorage(): it iterates the mip levels, compares the incoming size.depth against each gl::ImageDesc’s previous depth, and calls onStateChange(angle::SubjectMessage::TextureLayerCountIncreased) when depth grows, so the FBO reattaches to the new storage instead of dereferencing the stale one.
glTexStorage3D path, leaving attached framebuffers pointing at freed storage after a layer-count increase; the fix closes the gap by emitting the same TextureLayerCountIncreased notification from TextureGL::setStorage().Attack Path
- Create and attach
A page’s WebGL2 code creates a
2D_ARRAYtexture, gives it storage, and attaches layer 0 of it to a framebuffer color attachment viaglFramebufferTextureLayer. - Reallocate via TexStorage3D
The page calls
glTexStorage3D(or otherwise re-drivessetStorage()) with an increased depth, causing ANGLE to allocate new backing storage and free the old one without notifying the attached FBO. - Dangle the attachment
Because
setStorage()never emittedTextureLayerCountIncreased, the framebuffer still references the freed storage, producing a use-after-free. - Trigger the UAF The page renders to or samples from the framebuffer/texture, driving reads or writes through the dangling pointer to reclaimed GPU-process memory.
Impact Assessment
2D_ARRAY texture and framebuffer-layer calls; no special permissions are required beyond loading the page.Files Changed
src/tests/gl_tests/TextureTest.cppsrc/libANGLE/renderer/gl/TextureGL.cpp
Audit Directions
- Paired mutable/immutable pathsWhen a workaround or invariant is added to a mutable resource-allocation path (
glTexImage*), audit the immutable counterpart (glTexStorage*/setStorage) for the same notification or reattachment logic. - Reallocation without observer notificationFlag any code that frees and reallocates backing storage but does not broadcast a
SubjectMessage(e.g.ObjectReallocated,TextureLayerCountIncreased) to attachments such as FBOs. - Feature-flag-gated fixesVerify that security workarounds behind flags like
reattachTextureToFboAfterLayerIncreaseare consistently applied to every entry point that can trigger the vulnerable condition, not just the first one discovered.
Patch
From 87f5655006e4a66842c004a722440a643cc03c22 Mon Sep 17 00:00:00 2001
From: Zhenyao Mo <zmo@chromium.org>
Date: Tue, 18 Aug 2026 14:49:13 -0700
Subject: [PATCH] GL: Apply reattachTextureToFboAfterLayerIncrease to TexStorage3D
This adds the workaround logic inside TextureGL::setStorage() for cases
where an FBO is attached before the immutable storage is allocated. Also
updates the related tests to verify this with both TexImage3D and
TexStorage3D.
Bug: chromium:544163112
Change-Id: Ibb50ffeed6eaa369bed4ab25b625c16a1e63796c
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/8266365
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Zhenyao Mo <zmo@chromium.org>
---
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index be2ccee..45ea907 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -1300,6 +1300,20 @@
onStateChange(angle::SubjectMessage::ObjectReallocated);
}
+ if (features.reattachTextureToFboAfterLayerIncrease.enabled &&
+ getType() == gl::TextureType::_2DArray)
+ {
+ for (size_t level = 0; level < levels; level++)
+ {
+ const gl::ImageDesc &desc = mState.getImageDesc(gl::TextureTarget::_2DArray, level);
+ if (size.depth > desc.size.depth)
+ {
+ onStateChange(angle::SubjectMessage::TextureLayerCountIncreased);
+ break;
+ }
+ }
+ }
+
const gl::InternalFormat &originalInternalFormatInfo =
gl::GetSizedInternalFormatInfo(internalFormat);
nativegl::TexStorageFormat texStorageFormat =
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index 3e6bc69..f391bdd 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -9363,54 +9363,70 @@
// layer count without releasing storage.
ANGLE_SKIP_TEST_IF(IsMetal());
- glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ for (bool useTexStorage : {false, true})
+ {
+ glDeleteTextures(1, &m2DArrayTexture);
+ glGenTextures(1, &m2DArrayTexture);
- std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsRed.data());
- ASSERT_GL_NO_ERROR();
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- GLFramebuffer fbo;
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
+ std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+ ASSERT_GL_NO_ERROR();
- // Increase layer count to 2.
- std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsGreen.data());
- ASSERT_GL_NO_ERROR();
+ GLFramebuffer fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- // Verify layer 0 points to the new memory (green).
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
- // Verify layer 1 is also green.
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ // Increase layer count to 2.
+ std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
+ if (useTexStorage)
+ {
+ glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 4, 4, 2);
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 2, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ else
+ {
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ ASSERT_GL_NO_ERROR();
- // Clear layer 1 to blue and verify.
- glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
+ // Verify layer 0 points to the new memory (green).
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
- // Now sample from layer 0 and layer 1 using a shader to ensure texture memory matches FBO
- // memory.
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
- glUseProgram(mProgram);
- glUniform1i(mTextureArrayLocation, 0);
+ // Verify layer 1 is also green.
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
- // Verify layer 0 is green.
- glUniform1i(mTextureArraySliceUniformLocation, 0);
- drawQuad(mProgram, "position", 0.5f);
- EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
+ // Clear layer 1 to blue and verify.
+ glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
- // Verify layer 1 is blue.
- glUniform1i(mTextureArraySliceUniformLocation, 1);
- drawQuad(mProgram, "position", 0.5f);
- EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::blue);
+ // Now sample from layer 0 and layer 1 using a shader to ensure texture memory matches FBO
+ // memory.
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
+ glUseProgram(mProgram);
+ glUniform1i(mTextureArrayLocation, 0);
+
+ // Verify layer 0 is green.
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
+
+ // Verify layer 1 is blue.
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::blue);
+ }
}
// Test increasing layer count of a 2D array texture when one of its layers is attached to a
@@ -9423,62 +9439,78 @@
// layer count without releasing storage.
ANGLE_SKIP_TEST_IF(IsMetal());
- glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ for (bool useTexStorage : {false, true})
+ {
+ glDeleteTextures(1, &m2DArrayTexture);
+ glGenTextures(1, &m2DArrayTexture);
- std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsRed.data());
- ASSERT_GL_NO_ERROR();
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- GLFramebuffer fbo;
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
+ std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+ ASSERT_GL_NO_ERROR();
- // Set up and switch to a secondary context sharing resources with the current context.
- EGLWindow *window = getEGLWindow();
- EGLDisplay display = window->getDisplay();
- EGLConfig config = window->getConfig();
- EGLSurface surface = window->getSurface();
- EGLint contextAttributes[] = {
- EGL_CONTEXT_MAJOR_VERSION_KHR,
- GetParam().majorVersion,
- EGL_CONTEXT_MINOR_VERSION_KHR,
- GetParam().minorVersion,
- EGL_NONE,
- };
- EGLContext context1 = eglGetCurrentContext();
- EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
- ASSERT_NE(context2, EGL_NO_CONTEXT);
- eglMakeCurrent(display, surface, surface, context2);
+ GLFramebuffer fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- // In the secondary context, bind the texture and increase layer count to 2.
- glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
- std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsGreen.data());
- ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
- // Switch back to the primary context.
- eglMakeCurrent(display, surface, surface, context1);
+ // Set up and switch to a secondary context sharing resources with the current context.
+ EGLWindow *window = getEGLWindow();
+ EGLDisplay display = window->getDisplay();
+ EGLConfig config = window->getConfig();
+ EGLSurface surface = window->getSurface();
+ EGLint contextAttributes[] = {
+ EGL_CONTEXT_MAJOR_VERSION_KHR,
+ GetParam().majorVersion,
+ EGL_CONTEXT_MINOR_VERSION_KHR,
+ GetParam().minorVersion,
+ EGL_NONE,
+ };
+ EGLContext context1 = eglGetCurrentContext();
+ EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
+ ASSERT_NE(context2, EGL_NO_CONTEXT);
+ eglMakeCurrent(display, surface, surface, context2);
- // Verify layer 0 points to the new memory (green).
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ // In the secondary context, bind the texture and increase layer count to 2.
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+ std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
+ if (useTexStorage)
+ {
+ glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 4, 4, 2);
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 2, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ else
+ {
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ ASSERT_GL_NO_ERROR();
- // Attach layer 1 to the FBO in context1 and verify. Explicitly calling
- // glFramebufferTextureLayer attaches to the newly allocated texture storage.
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ // Switch back to the primary context.
+ eglMakeCurrent(display, surface, surface, context1);
- // Clear layer 1 to blue and verify.
- glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
+ // Verify layer 0 points to the new memory (green).
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
- // Clean up secondary context.
- eglDestroyContext(display, context2);
+ // Attach layer 1 to the FBO in context1 and verify. Explicitly calling
+ // glFramebufferTextureLayer attaches to the newly allocated texture storage.
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+
+ // Clear layer 1 to blue and verify.
+ glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
+
+ // Clean up secondary context.
+ eglDestroyContext(display, context2);
+ }
}
// Create a 3D texture, use it, then redefine one level without changing dimensions.
Regression Test / PoC
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index 3e6bc69..f391bdd 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -9363,54 +9363,70 @@
// layer count without releasing storage.
ANGLE_SKIP_TEST_IF(IsMetal());
- glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ for (bool useTexStorage : {false, true})
+ {
+ glDeleteTextures(1, &m2DArrayTexture);
+ glGenTextures(1, &m2DArrayTexture);
- std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsRed.data());
- ASSERT_GL_NO_ERROR();
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- GLFramebuffer fbo;
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
+ std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+ ASSERT_GL_NO_ERROR();
- // Increase layer count to 2.
- std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsGreen.data());
- ASSERT_GL_NO_ERROR();
+ GLFramebuffer fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- // Verify layer 0 points to the new memory (green).
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
- // Verify layer 1 is also green.
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ // Increase layer count to 2.
+ std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
+ if (useTexStorage)
+ {
+ glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 4, 4, 2);
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 2, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ else
+ {
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ ASSERT_GL_NO_ERROR();
- // Clear layer 1 to blue and verify.
- glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
+ // Verify layer 0 points to the new memory (green).
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
- // Now sample from layer 0 and layer 1 using a shader to ensure texture memory matches FBO
- // memory.
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
- glUseProgram(mProgram);
- glUniform1i(mTextureArrayLocation, 0);
+ // Verify layer 1 is also green.
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
- // Verify layer 0 is green.
- glUniform1i(mTextureArraySliceUniformLocation, 0);
- drawQuad(mProgram, "position", 0.5f);
- EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
+ // Clear layer 1 to blue and verify.
+ glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
- // Verify layer 1 is blue.
- glUniform1i(mTextureArraySliceUniformLocation, 1);
- drawQuad(mProgram, "position", 0.5f);
- EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::blue);
+ // Now sample from layer 0 and layer 1 using a shader to ensure texture memory matches FBO
+ // memory.
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
+ glUseProgram(mProgram);
+ glUniform1i(mTextureArrayLocation, 0);
+
+ // Verify layer 0 is green.
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
+
+ // Verify layer 1 is blue.
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::blue);
+ }
}
// Test increasing layer count of a 2D array texture when one of its layers is attached to a
@@ -9423,62 +9439,78 @@
// layer count without releasing storage.
ANGLE_SKIP_TEST_IF(IsMetal());
- glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ for (bool useTexStorage : {false, true})
+ {
+ glDeleteTextures(1, &m2DArrayTexture);
+ glGenTextures(1, &m2DArrayTexture);
- std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsRed.data());
- ASSERT_GL_NO_ERROR();
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- GLFramebuffer fbo;
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
+ std::vector<GLColor> pixelsRed(4 * 4 * 1, GLColor::red);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+ ASSERT_GL_NO_ERROR();
- // Set up and switch to a secondary context sharing resources with the current context.
- EGLWindow *window = getEGLWindow();
- EGLDisplay display = window->getDisplay();
- EGLConfig config = window->getConfig();
- EGLSurface surface = window->getSurface();
- EGLint contextAttributes[] = {
- EGL_CONTEXT_MAJOR_VERSION_KHR,
- GetParam().majorVersion,
- EGL_CONTEXT_MINOR_VERSION_KHR,
- GetParam().minorVersion,
- EGL_NONE,
- };
- EGLContext context1 = eglGetCurrentContext();
- EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
- ASSERT_NE(context2, EGL_NO_CONTEXT);
- eglMakeCurrent(display, surface, surface, context2);
+ GLFramebuffer fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
- // In the secondary context, bind the texture and increase layer count to 2.
- glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
- std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- pixelsGreen.data());
- ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red);
- // Switch back to the primary context.
- eglMakeCurrent(display, surface, surface, context1);
+ // Set up and switch to a secondary context sharing resources with the current context.
+ EGLWindow *window = getEGLWindow();
+ EGLDisplay display = window->getDisplay();
+ EGLConfig config = window->getConfig();
+ EGLSurface surface = window->getSurface();
+ EGLint contextAttributes[] = {
+ EGL_CONTEXT_MAJOR_VERSION_KHR,
+ GetParam().majorVersion,
+ EGL_CONTEXT_MINOR_VERSION_KHR,
+ GetParam().minorVersion,
+ EGL_NONE,
+ };
+ EGLContext context1 = eglGetCurrentContext();
+ EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
+ ASSERT_NE(context2, EGL_NO_CONTEXT);
+ eglMakeCurrent(display, surface, surface, context2);
- // Verify layer 0 points to the new memory (green).
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ // In the secondary context, bind the texture and increase layer count to 2.
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+ std::vector<GLColor> pixelsGreen(4 * 4 * 2, GLColor::green);
+ if (useTexStorage)
+ {
+ glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 4, 4, 2);
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 2, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ else
+ {
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+ }
+ ASSERT_GL_NO_ERROR();
- // Attach layer 1 to the FBO in context1 and verify. Explicitly calling
- // glFramebufferTextureLayer attaches to the newly allocated texture storage.
- glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+ // Switch back to the primary context.
+ eglMakeCurrent(display, surface, surface, context1);
- // Clear layer 1 to blue and verify.
- glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
+ // Verify layer 0 points to the new memory (green).
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
- // Clean up secondary context.
- eglDestroyContext(display, context2);
+ // Attach layer 1 to the FBO in context1 and verify. Explicitly calling
+ // glFramebufferTextureLayer attaches to the newly allocated texture storage.
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 1);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
+
+ // Clear layer 1 to blue and verify.
+ glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::blue);
+
+ // Clean up secondary context.
+ eglDestroyContext(display, context2);
+ }
}
// Create a 3D texture, use it, then redefine one level without changing dimensions.
Original Bug Report
PowerVR `texStorage3D` attachment lifetime bug yields address-selected native CPU r/w/RCE from WebGL
Steps to reproduce the problem
- Use a Pixel 10 Pro running the latest stock security update (July 5) Google build shown below. HAS TO BE EXACTLY A PIXEL 10 PRO,
- Open the attached
PoC.htmlin Chrome Canary. - Observe the page output and
adb logcat. - The page first proves an address-selected native read and write against a safe in-process allocation. It then changes the same native destination pointer to
0x0000414141414000and submits one more uniform update. - Chrome’s GPU process terminates with
SIGSEGV; the tombstone reports fault address0x0000414141414000, and registerx8contains the same attacker-selected value.
Hosted copy used for this run:
https://payload.engineering/14184-24622-23478/FUCK/B0018_8dcf_selected_write_7f3a.html
26f71e7f26cf3a96edb8d02f9c4078d8ebef1b1f6f5b21b72e85f3e8ccfb8f80 PoC.html
Problem Description
I will provide a full system() exploit as soon as possible. Preliminary findings:
The WebGL2 page obtains two stale native mip-record aliases after growing attached TEXTURE_2D_ARRAY storage with texStorage3D. It uses the aliases and deterministic 0x2600/0x3c0 allocation reuse to leave a native program object reachable after its backing record has been freed and reclaimed.
The reclaimed GLES3ProgramRec can be shaped so that its default uniform-store pointer names an address selected by the page. The PoC demonstrates both directions before crashing:
alias 1: controller=0 marker=0 object=0xb4000077bd549290
alias 2: controller=1 marker=1 object=0xb4000077bd547010
address-selected native read proven; native program name=13
address-selected native write proven at 0xb4000077bd549600
ARMED: next native uniform write destination=0x0000414141414000
Submitting 16 bytes of 0x41; inspect logcat for the GPU-process write fault.
WebGL context lost after native write submission
The safe write is verified through a second, independent WebGL uniform view of the reclaimed native allocation. The final deliberately unmapped destination faults on the driver’s preparatory read before the write, producing a stable attacker-selected native-pointer tombstone:
F libc : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR),
fault addr 0x414141414000 in tid 17828 (CrGpuMain)
F DEBUG : Cmdline: com.chrome.canary:privileged_process0
F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR),
fault addr 0x0000414141414000 (read)
F DEBUG : x8 0000414141414000
F DEBUG : pc 000000773313ba2c
F DEBUG : backtrace:
F DEBUG : #00 pc 0000000000127a2c /vendor/lib64/egl/libGLESv2_powervr.so
F DEBUG : (GLES3ProgramUniformScalarVector(...)+188)
F DEBUG : (BuildId: 8dcf1f5c390a11f44a0be224d4d3f31d)
F DEBUG : #01 pc 00000000001a14dc /vendor/lib64/egl/libGLESv2_powervr.so
F DEBUG : (glProgramUniform4uiv+124)
F DEBUG : (BuildId: 8dcf1f5c390a11f44a0be224d4d3f31d)
The complete logcat and a screenshot containing the successful safe read/write proof immediately before the crash are attached.
Expected result
Changing or replacing texture storage while the texture is attached must not leave a native driver record referencing freed or subsequently reused CPU memory. WebGL object operations must not permit a page to select a native pointer used by glGetUniform*/glProgramUniform*.
Security impact
This is not only a null dereference or GPU denial of service. The page demonstrates:
- A stale native PowerVR object alias reachable from WebGL2.
- Controlled reclaim as a live
GLES3ProgramRec. - Address-selected native CPU read.
- Address-selected 16-byte native CPU write, verified at a safe mapped target.
- A final native access using the page-selected pointer
0x0000414141414000, confirmed in the GPU-process tombstone and register state.
The current PoC intentionally stops at a controlled GPU-process crash. We have not included a code-execution payload.
Tested environment
Device: Pixel 10 Pro (blazer)
Build fingerprint: google/blazer/blazer:17/CP2A.260705.006/15641320:user/release-keys
Security patch: 2026-07-05
Chrome Canary: 153.0.7997.0 (799700004)
Chrome GPU-process UID: 10325
libGLESv2_powervr.so
BuildId: 8dcf1f5c390a11f44a0be224d4d3f31d
SHA-256: 6956f1f4ec041b66692518d1e47db738d78bce47692ac68b26bda2f090e7226e
The OS/vendor binaries are stock Google and the device is unrooted. The bootloader was already unlocked; the PoC does not require root, debugging APIs, native code, command-line flags, or user interaction beyond opening the page.
Note: I reported the root cause already here: https://issues.chromium.org/issues/543660458
Summary
PowerVR texStorage3D attachment lifetime bug yields address-selected native CPU r/w/RCE from WebGL
Custom Questions
Type of crash:
GPU
Crash state:
08-08 20:57:58.996 18480 18480 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
08-08 20:57:58.996 18480 18480 F DEBUG : Build fingerprint: 'google/blazer/blazer:17/CP2A.260705.006/15641320:user/release-keys'
08-08 20:57:58.996 18480 18480 F DEBUG : Kernel Release: '6.6.118-android15-8-g53e6e091166e-ab15266607-4k'
08-08 20:57:58.996 18480 18480 F DEBUG : Revision: 'MP1.0'
08-08 20:57:58.996 18480 18480 F DEBUG : ABI: 'arm64'
08-08 20:57:58.996 18480 18480 F DEBUG : Timestamp: 2026-08-08 20:57:58.890241123+0200
08-08 20:57:58.996 18480 18480 F DEBUG : Process uptime: 22s
08-08 20:57:58.996 18480 18480 F DEBUG : Executable: /system/bin/app_process64
08-08 20:57:58.996 18480 18480 F DEBUG : Cmdline: com.chrome.canary:privileged_process6
08-08 20:57:58.996 18480 18480 F DEBUG : pid: 18428, ppid: 1003, tid: 18441, name: CrGpuMain >>> com.chrome.canary:privileged_process6 <<<
08-08 20:57:58.996 18480 18480 F DEBUG : uid: 10325
08-08 20:57:58.996 18480 18480 F DEBUG : tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
08-08 20:57:58.996 18480 18480 F DEBUG : pac_enabled_keys: 000000000000000f (PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY)
08-08 20:57:58.996 18480 18480 F DEBUG : esr: 0000000092000004 (Data Abort Exception 0x24)
08-08 20:57:58.996 18480 18480 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0000414141414000 (read)
08-08 20:57:58.996 18480 18480 F DEBUG : x0 b4000077bd55cf80 x1 b4000077bd55cd60 x2 0000000000000010 x3 0000000000000001
08-08 20:57:58.996 18480 18480 F DEBUG : x4 000000773304377c x5 0000007784967e94 x6 00000077331f0e40 x7 000000000000000e
08-08 20:57:58.996 18480 18480 F DEBUG : x8 0000414141414000 x9 0000000000000004 x10 0000000000000000 x11 0000000000000001
08-08 20:57:58.996 18480 18480 F DEBUG : x12 0000000000000001 x13 0000000000000001 x14 0000007200d3aa90 x15 ffffffffff00ffff
08-08 20:57:58.996 18480 18480 F DEBUG : x16 000000773e8f95a0 x17 0000007a4e953180 x18 00000076e6e14000 x19 b40000797d4b1080
08-08 20:57:58.996 18480 18480 F DEBUG : x20 0000007784967e94 x21 000000773304377c x22 0000000000000004 x23 0000000000000001
08-08 20:57:58.996 18480 18480 F DEBUG : x24 0000000000000000 x25 b4000077bd55cd60 x26 00000077331f0e40 x27 000000000000000e
08-08 20:57:58.996 18480 18480 F DEBUG : x28 0000000000000007 x29 00000076e78d5590
08-08 20:57:58.996 18480 18480 F DEBUG : lr 002b24773313b9c0 sp 00000076e78d5480 pc 000000773313ba2c pst 0000000080001000
08-08 20:57:58.996 18480 18480 F DEBUG : esr 0000000092000004 vg 0000000000000002
08-08 20:57:58.996 18480 18480 F DEBUG : 29 total frames
08-08 20:57:58.996 18480 18480 F DEBUG : backtrace:
08-08 20:57:58.996 18480 18480 F DEBUG : #00 pc 0000000000127a2c /vendor/lib64/egl/libGLESv2_powervr.so (GLES3ProgramUniformScalarVector(GLES3Context_TAG*, GLES3ProgramRec*, unsigned int, int, int, void const*, char const* const*, GLSLTypeSpecifierTAG, GLES3UniformTypeTAG, char const*) (.__uniq.175030908309407430927784858702543253136)+188) (BuildId: 8dcf1f5c390a11f44a0be224d4d3f31d)
08-08 20:57:58.996 18480 18480 F DEBUG : #01 pc 00000000001a14dc /vendor/lib64/egl/libGLESv2_powervr.so (glProgramUniform4uiv+124) (BuildId: 8dcf1f5c390a11f44a0be224d4d3f31d)
08-08 20:57:58.996 18480 18480 F DEBUG : #02 pc 00000000097d7a48 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #03 pc 00000000097c8a50 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #04 pc 0000000007988314 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #05 pc 0000000007987808 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #06 pc 000000000798751c /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #07 pc 00000000079873c8 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #08 pc 0000000007987338 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #09 pc 00000000079600fc /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #10 pc 0000000007d18bc4 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #11 pc 000000000641a3c4 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #12 pc 00000000062b24d0 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #13 pc 00000000062b2020 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #14 pc 0000000007c7ff90 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #15 pc 000000000638c994 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #16 pc 00000000062ce0fc /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #17 pc 00000000062cd4ac /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #18 pc 00000000062cd1f8 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk!libchrome.so (offset 0xf78000) (BuildId: 3e2f88e3eafde15b51dd0c5af94c81c8fdba410f)
08-08 20:57:58.996 18480 18480 F DEBUG : #19 pc 00000000002e42b8 /system/framework/arm64/boot.oat (art_jni_trampoline+104) (BuildId: 4d093721a5cd1aa2dbff309faa61a2832807aef9)
08-08 20:57:58.996 18480 18480 F DEBUG : #20 pc 000000000072c104 /apex/com.android.art/lib64/libart.so (nterp_helper+116) (BuildId: 1f156fc62660d075a8d675db850b95d5)
08-08 20:57:58.996 18480 18480 F DEBUG : #21 pc 00000000000fcd42 /data/app/~~baPAwlVs5Yy4AjAz63MIeg==/com.chrome.canary-c_DMREJulaN92SuKHIA2fQ==/base.apk (offset 0xbea000) (lb4.run+582)
08-08 20:57:58.996 18480 18480 F DEBUG : #22 pc 00000000000a9d10 /system/framework/arm64/boot.oat (java.lang.Thread.run+64) (BuildId: 4d093721a5cd1aa2dbff309faa61a2832807aef9)
08-08 20:57:58.996 18480 18480 F DEBUG : #23 pc 0000000000298f94 /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+612) (BuildId: 1f156fc62660d075a8d675db850b95d5)
08-08 20:57:58.996 18480 18480 F DEBUG : #24 pc 000000000029738c /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+148) (BuildId: 1f156fc62660d075a8d675db850b95d5)
08-08 20:57:58.996 18480 18480 F DEBUG : #25 pc 00000000004d5fd0 /apex/com.android.art/lib64/libart.so (art::Thread::CreateCallback(void*)+1384) (BuildId: 1f156fc62660d075a8d675db850b95d5)
08-08 20:57:58.996 18480 18480 F DEBUG : #26 pc 00000000004d5a54 /apex/com.android.art/lib64/libart.so (art::Thread::CreateCallbackWithUffdGc(void*)+12) (BuildId: 1f156fc62660d075a8d675db850b95d5)
08-08 20:57:58.996 18480 18480 F DEBUG : #27 pc 000000000008d954 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*) (.__uniq.67847048707805468364044055584648682506)+180) (BuildId: bff603430d1ad139d4f0e6a78f542c4d)
08-08 20:57:58.996 18480 18480 F DEBUG : #28 pc 000000000007da64 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+68) (BuildId: bff603430d1ad139d4f0e6a78f542c4d)
Reporter credit:
Lexi Groves (49016)
Additional Data
Category: Security
Chrome Channel: Canary
Regression: N/A \