[11] RenderLayer Re-Entrancy During Reflection Layer Teardown
Severity: Medium | Component: WebCore RenderLayerCompositor | ecde527
child teardown 과정에서 부분적으로 파괴된 RenderLayer에 접근하는 현상이 관측 가능한 영향이며, debug 빌드에서는 CheckedPtr을 통한 assertion 실패로 나타납니다. CheckedPtr 도입 이전 release 빌드에서는 유효하지 않은 메모리에 접근했을 가능성이 있으나, 구체적인 memory corruption primitive는 특정되지 않았습니다. 실제 exploit이 시연된 것이 아니라 fuzzer가 새 assertion을 발생시키면서 노출된 버그이므로, Medium으로 평가합니다.
Patch Details
RenderLayer::removeChild()에서, 제거 대상 child가 reflection layer인 경우 compositor().layerWillBeRemoved() 호출을 건너뛰는 guard가 추가되었습니다.
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>
render layer tree의 child teardown 과정에서 부분적으로 파괴된 객체에 re-entrant하게 접근하는 패턴.
Background
RenderLayer는 render tree 내 compositing layer를 나타내는 WebKit의 객체로, child layer들과 함께 트리 구조를 형성합니다. reflection layer는 -webkit-box-reflect CSS 속성에 의해 생성되는 특수 child layer로, parent layer의 시각적 내용을 그대로 반사합니다. RenderLayerCompositor::layerWillBeRemoved()는 layer가 제거되려 한다는 사실을 compositor에 통지하며, 이를 통해 composited ancestor에서 repaint가 발생합니다. 여기서 composited ancestor란 자체 compositing backing store를 갖는 가장 가까운 ancestor layer를 의미합니다.
Analysis
reflection layer를 포함한 RenderLayer가 소멸될 때, reflection child가 먼저 제거됩니다. removeChild()는 compositor().layerWillBeRemoved(*this, oldChild)를 호출하고, 이 호출은 다시 repaintInCompositedAncestor()로 이어집니다. 이때 reflection layer의 composited ancestor가 현재 소멸 중인 parent layer인 경우, 해당 코드는 부분적으로 파괴된 객체를 대상으로 동작하게 됩니다. 306315@main에서 도입된 CheckedPtr은 pointer가 scope를 벗어날 때 composited ancestor의 유효성을 assertion하는 방식으로 이 문제를 표면화했습니다. 다만 근본적인 버그는 그 이전부터 존재했습니다. 소멸이 진행 중인 layer에 접근하는 코드가 이미 있었던 것입니다.
a Aaaa Aaaaaaaa Aa Aaaaaaaaaa Aaa Aaaaaa Aaaaaaaaaa Aaaa Aaaaaa Aaaa Aaaa Aaa a Aaaaa Aaa Aa Aaa Aaaaa Aaa Aaa Aaa Aaaaaaa Aaaa Aaaaa Aaa Aaaa
a Aaaa Aaaaaaaa Aaaaaaaa Aaa Aaaa Aaaaaaa Aaaaaaaaaaaa Aaaaaaaaaa Aa Aaaa a Aaa Aaa Aaaaaaa Aaaaa Aaa Aaaaaa Aaa Aaaaaaaaa Aa Aaaaaa Aaaaaaa Aaaaa Aaaa Aa Aaaa Aaa Aaaa Aaaaaaaa Aaaaaaaaaaa Aaa a Aa Aaa Aaaa Aaaaaa Aaaaaaa Aaaaaaa Aaaaa Aa Aa Aaaaaaa Aaaaaa Aaa Aaa a Aaaa Aaaaaa
🔒Explores the object lifecycle implications and whether the partially-destroyed state could be leveraged beyond a crash
더 확인하려면 구독해 주세요
Audit directions
a Aaaaaaa Aaaaaaaa Aaaaaaaaaaaaaa Aaaaaa Aaa Aaaaaaaaaaa Aaaaaa Aaaa Aaaaa a Aa Aaa Aaaaaaa Aaa Aaaaa Aaaa Aa Aaa Aa Aaa Aa Aaaaaaaaaaa Aaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaa a Aa Aaaaaaaaaaa Aa Aaaaa Aaaaaaaaaaa Aaaaa Aaaaaaaaa Aaaaa Aaa Aaaaaaaaa Aaaa Aa Aaa Aaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaaaaa
a Aaaaaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaaaaa Aaaaaaaaaa Aaaaaa Aaaaaaa Aaa Aaaaaaaaaaaa Aaa Aa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa a Aa Aaaaaaaaaa Aa Aaaa Aaaaaaa Aaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaaaaaa Aaaaa Aaa Aaaaaa Aaaaaa Aaa Aaaaa Aaa Aaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaa Aa Aaaa Aaaaaa Aaa Aaa Aaaaaaa
a Aaaaaaaaaaaa Aaaaaaaa Aaaaaaaaaaaaaaa Aaaaaa Aaaa Aaa Aaaaaaaaaaaaa Aaa Aaaaaaaaaaa Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaaaaaaaa Aaa Aa Aaaa Aaaaa Aaa Aaaaaa Aaa Aaaa Aa Aa Aaaa Aaa Aaa Aaa Aaaaa Aaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa a a Aaaaaaaaaa Aaaaaaaaaaaa Aaaaa Aaaaaaa
🔒Multiple audit patterns identified around render layer teardown re-entrancy, with concrete starting points in the compositor notification infrastructure
더 확인하려면 구독해 주세요