Sampled mprotect write-guard for DOMWrapperWorld::m_wrappers corruption
d2af128 → beb0b21
DOMWrapperWorld::m_wrappers는 JS/DOM binding layer의 핵심 hash map입니다. DOM 객체와 살아있는 Weak<JSObject> wrapper handle을 연결합니다. JS가 DOM 노드에 접근할 때마다 cacheWrapper가 항목을 삽입하거나 갱신합니다. GC는 rehash 과정에서 JSC::WeakImpl::clear()를 호출해 stale 항목을 정리하는데, 테이블이 손상된 상태라면 이 시점에 garbage address를 역참조하게 됩니다. 이번 commit은 이런 stray write를 포착하기 위한 sampled instrumentation을 추가했습니다.
Source/WebCore/bindings/js/DOMWrapperWorld.cpp
+void* WrapperMapTableMalloc::allocate(size_t size)
+{
+ size_t pageSize = WTF::pageSize();
+ size_t rounded = (requested + pageSize - 1) & ~(pageSize - 1);
+ void* base = mmap(nullptr, rounded, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ RELEASE_ASSERT(base != MAP_FAILED);
+ if (auto* world = WrapperMutationScope::currentlyMutatedWorld())
+ world->noteTableBacking(base, rounded);
+ return base;
+}
+
+void DOMWrapperWorld::setWrappersTableWritable(bool writable)
+{
+ if (writable) {
+ if (m_wrappersTableWritableDepth++)
+ return;
+ } else {
+ ASSERT(m_wrappersTableWritableDepth);
+ if (--m_wrappersTableWritableDepth)
+ return;
+ }
+ if (m_wrappersTableBase)
+ RELEASE_ASSERT(!mprotect(m_wrappersTableBase, m_wrappersTableSize,
+ PROT_READ | (writable ? PROT_WRITE : 0)));
+}
새로 추가된 WrapperMapTableMalloc allocator는 hash table의 backing을 page-aligned mmap 메모리에 배치하고, 평소에는 PROT_READ 상태로 유지합니다. cacheWrapper / uncacheWrapper / clearWrappers 호출 중에는 WrapperMutationScope RAII guard가 해당 페이지를 일시적으로 PROT_READ|WRITE로 전환합니다. 이 기능은 시작 시 weakRandomNumber를 통해 약 1/64 프로세스에서 활성화됩니다. 덕분에 mutation scope 밖에서 stray write가 발생하면, 나중에 메모리 손상으로 crash가 이어지는 대신 write 발생 지점에서 즉시 fault가 발생합니다.
Significance
WebKit JS/DOM binding layer에서 현재 진행 중인 미해결 production heap corruption이 존재함을 드러냅니다. 동일한 garbage-pointer 패턴이 위상적으로 무관한 hash table(m_wrappers, CodeBlockSet) 양쪽에서 관찰됩니다. 이는 해제된 객체가 hash table backing으로 재사용된 후, dangling pointer에 의해 기록되는 패턴과 일치합니다.
Audit directions
Aaaaaaaa Aa Aaaa Aaaaaa Aaaa Aa Aaaaaaaa Aaaa a Aaaaaaaa Aaaaaa Aa Aa Aaaaaaaa Aaaa Aa Aaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaa Aaaaa Aaaaaa Aaaaa Aaaaaaaaaaaa Aaaa Aaaaaaaaaaa a Aaa Aaaa Aaaa a Aaa Aa Aaaa Aaa Aaaa Aaaaaa Aaaaaa Aaaa Aaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aa Aaa Aaaa Aaaa
Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaa Aa Aaaaaaaaa Aaaaaaaaa Aaaaaaaa Aaaa Aaa Aaaa a Aaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaa Aaaaa Aaa Aaa a Aaaaa Aa Aaaa Aaaaaaaaa Aaaa Aaaaa Aa Aaa Aaaa Aaa Aaaaaaaa Aaaa Aa Aa Aaaa Aaa a Aaaaa Aa Aaa Aaaaaaaaaaa Aaa Aaaaa
Aa Aaa Aa Aaaa Aaaaaaaaaaa Aa Aaaa Aaaa Aaaaaa Aaaa Aaaa Aa Aaaaaaaaaaaaa Aaaaaaaaaaaaa Aaaaa Aaaaaa Aaaa Aaaaa Aaa a Aaaaa Aa Aa Aaaaa Aa Aa Aa Aaaaaa Aaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaa Aaaaaaaaaa Aaa Aaaa Aaaaa Aaaaaaa Aaa Aaaaa Aa Aaa Aaa Aaaaaa
🔒Cross-process shared memory with three concurrent writers, a removed extrapolation bound, and new floor/ceiling invariants — audit directions included.
더 확인하려면 구독해 주세요