[11] RenderLayer Re-Entrancy During Reflection Layer Teardown
Severity: Medium | Component: WebCore RenderLayerCompositor | ecde527
Rated Medium because the observable effect is access to a partially-destroyed RenderLayer during child teardown (assertion failure via CheckedPtr in debug builds), and while the pre-CheckedPtr behavior in release builds would have accessed invalid memory, the specific memory corruption primitive is uncharacterized — the bug was exposed by a fuzzer hitting the new assertion rather than a demonstrated exploit.
Patch Details
Adds a guard in RenderLayer::removeChild() to skip calling compositor().layerWillBeRemoved() when the child being removed is a reflection layer.
Source/WebCore/rendering/RenderLayer.cpp
void RenderLayer::removeChild(RenderLayer& oldChild)
{
- if (!renderer().renderTreeBeingDestroyed())
+ if (!renderer().renderTreeBeingDestroyed() && !isReflectionLayer(oldChild))
compositor().layerWillBeRemoved(*this, oldChild);
// remove the child
LayoutTests/fast/reflections/reflection-removed-crash-2.html
+<style>
+ rt {
+ translate: 23% 80cap 1svi;
+ -webkit-box-reflect: below;
+ }
+</style>
+ <script>
+ (async () => {
+ let n1 = document.createElement('ruby');
+ document.documentElement.appendChild(n1);
+ n1.appendChild(document.createElement('rt'));
+ let n7 = document.createElement('object');
+ n7.id = 'n4';
+ n1.append(document.createElement('rt'));
+ })();
+ testRunner?.dumpAsText();
+ </script>
Re-entrant access to a partially-destroyed object during child teardown in the render layer tree.
Background
RenderLayer is WebKit's representation of a compositing layer in the render tree, forming a tree structure with child layers. A reflection layer is a special child layer created by the -webkit-box-reflect CSS property — it mirrors the visual content of its parent layer. RenderLayerCompositor::layerWillBeRemoved() notifies the compositor that a layer is about to be removed, triggering repaint in the composited ancestor — the nearest ancestor layer that has its own compositing backing store.
Analysis
When a RenderLayer containing a reflection layer is destroyed, it removes the reflection child first. removeChild() calls compositor().layerWillBeRemoved(*this, oldChild), which calls repaintInCompositedAncestor(). When the composited ancestor of the reflection layer is the parent layer currently being destroyed, the code operates on a partially-destroyed object. A CheckedPtr introduced by commit 306315@main exposed this by asserting that the composited ancestor is valid when the pointer goes out of scope — but the underlying bug existed before: the code was accessing a layer in the process of destruction.
Aaaa Aaa Aaaaa Aa Aaaaaaa Aaaa Aaa Aaaaa Aaaaaaaa Aaaaaa Aaaaaaaaaaa Aaa Aaaaa Aaaaaaaaaaaaaa Aaaaa a Aaaaaaa Aaa Aaaaaaaa Aaaaaaaaaaaa Aaa Aaaaaaaaaaaa Aaa Aaaaaaaa a Aaaaaaaa a Aaaaaaaaa Aaaaaaaaaaaaaaaa Aaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaa Aaaaaaaa Aaaaaaa Aaaaaa Aaaaaaa Aaaaaa Aaa Aaaaaaaaaa Aaaaaaaa Aa Aaaaaaaaaaaa Aaaa Aaa Aaa Aaaaaa a Aaa Aaaaaaaaaaaaaaaaaaa Aaaaa Aaa Aaaaaaaa Aaaaaaa Aaa Aaaaaaaaaa Aaaaaaa Aaaaaaa Aaaaaa Aaaaaaaa Aaaaaaaa Aa Aaaaaaa Aaaaaaa Aaa Aaaaaaaaaaaa Aa Aaaaaaaaaa Aaaaaaaa Aaa Aaaaaa Aaa Aa a Aaaaaaa Aaaaaa Aaaaaaaaaaaaa Aaa Aaaaa Aa Aaaaaaaa Aaaaaaa Aaaaaaa Aaaaaa Aaaaaaaaa
🔒Explores the object lifecycle implications and whether the partially-destroyed state could be leveraged beyond a crash
Subscribe to read more
Audit directions
a Aaaaaaa Aaaaaaaa Aaaaaaaaaaaaaa Aaaa a Aaaaaa Aaaaaaaa Aaaaaaaaaa Aaaaaaa Aaaaaaaaa Aaa Aaa Aaaaaaa Aaaa Aaaaa Aaaa Aaaa Aaaaaaaaaaaaaa Aaaa Aaaaaaa Aaa Aaaaaa Aa Aaaaa Aaaaaa a Aaaaaaaaaaa Aaa Aaaaaaa Aaaaa Aaaaa Aaaaaaaaaaa Aaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaa Aaaaaaa Aaaaaaaa Aaaaa Aaaaaaaaaa Aa Aaaaa Aaaaaaaaa Aaaaa Aaaaa a Aaaaaaaaaaaaaaaaaaa Aaaaaaaaa Aaaa Aaa Aaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaa
a Aaaaaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaaaaa Aaaaaaaaaa Aaaaaa Aaaa a Aaaaaa Aaaaaaaaaaaa Aaaaaaaaaaaaa Aaaaa Aaaaa Aaaaaaaaaaaaaaaaaa Aaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaa Aaaa Aaa Aaaaaa Aaaaa Aa Aaaaa Aaaaa Aaaa Aaa Aaaaaaaaaa Aaaaaaaa Aaaaaaaaaa Aaaaaaaaaaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaa Aaaaaa Aaa Aaaaaaa Aaaaaaa
a Aaaaaaaaaaaa Aaaaaaaa Aaaaaaaaaaaaaaa Aaa Aaaaaa Aaaaaaa Aaaaaaaaa Aaaaaaaaaaa Aaaaa Aaa Aaaaaaaaaaa Aaa Aaaaa Aaaaa Aaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaa Aaaaaaaaaaa Aaaaaaaaaa Aaa Aaaaa Aaaaaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaaaa Aaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaa Aaaaa Aaaaaaaaaa Aaaaaaaaaaaa Aaaaaaaa
🔒Multiple audit patterns identified around render layer teardown re-entrancy, with concrete starting points in the compositor notification infrastructure
Subscribe to read more