[19] PlatformScreen data-race / GPUCanvasContextCocoa worker race
Severity: Medium | Component: WebCore PlatformScreen | 08911bd, cf20d12
두 diff가 프로세스 전역 ScreenProperties singleton의 concurrent HashMap 접근을 수정한다는 점에서 Medium으로 평가되었습니다. Worker thread의 reader가 screenDataMap.values()를 순회하는 동안 main thread가 rehash를 수행했고, ARM 하드웨어에서 MTE tag-mismatch crash로 드러났습니다.
동일한 root cause에서 비롯된 두 가지 fix가 함께 발견되었습니다. 첫 번째(cf20d12)는 기존 screenProperties() accessor에 ASSERT(isMainThread())를 추가하고, off-main-thread의 GPUCanvasContextCocoa read를 callOnMainThread + BinarySemaphore를 통해 처리하도록 변경되었습니다. 두 번째(08911bd)는 구조적인 수정입니다. NeverDestroyed<ScreenProperties> accessor를 ThreadSafeRefCounted<PlatformScreen> singleton으로 교체하고, Ref<const PlatformScreen>을 통해 접근하도록 변경되었습니다. platformScreenLock() 하에서 copy-on-write 방식이 적용되었습니다.
Source/WebCore/platform/PlatformScreen.cpp
-static ScreenProperties& NODELETE screenProperties()
-{
- ASSERT(isMainThread());
- static NeverDestroyed<ScreenProperties> screenProperties;
- return screenProperties;
-}
+Ref<const PlatformScreen> PlatformScreen::singleton()
+{
+ Locker locker { platformScreenLock() };
+ return instance().get();
+}
+void PlatformScreen::updateSingletonProperties(ScreenProperties&& properties)
+{
+ Locker locker { platformScreenLock() };
+ Ref<PlatformScreen>& platformScreenRef = PlatformScreen::instance();
+ if (platformScreenRef->hasOneRef())
+ platformScreenRef->m_properties = WTF::move(properties);
+ else
+ platformScreenRef = PlatformScreen::create(WTF::move(properties));
+}
Patch Details
독립 함수인 screenData(), getScreenProperties(), primaryScreenDisplayID(), setScreenProperties()는 모두 제거되었습니다. PlatformScreen은 ThreadSafeRefCounted 클래스로 변경되었습니다. Concurrent reader가 존재하는 경우, writer는 slot에 새 인스턴스를 교체합니다. Reader는 Ref<const PlatformScreen> snapshot을 생성하고 refcount를 통해 이를 유지합니다. 모든 호출 지점(HTMLMediaElement, GPUCanvasContextCocoa, VP9/GStreamer 스캐너, PlatformScreen{Mac,iOS,GTK,WPE})은 PlatformScreen::singleton()->... 방식으로 마이그레이션되었습니다.
Singleton HashMap의 backing storage를 가리키는 pointer와 iterator를 reader가 외부로 노출하는 동안, 다른 thread가 동일한 HashMap을 변경하면서 발생하는 data race / use-after-free.
PlatformScreen은 PlatformDisplayID를 key로 하여 디스플레이별 상태(직사각형 영역, EDR headroom, color space)를 캐싱하는 프로세스별 캐시입니다. UIProcess는 WebProcess::setScreenProperties를 통해 업데이트를 전달하는데, 이전에는 file-scope setter를 호출하여 singleton을 덮어쓰는 방식이었습니다. WTF HashMap은 thread-safe하지 않습니다. Concurrent insert 또는 operator=가 발생하면 bucket array가 rehash되어 기존 배열이 해제되고, concurrent reader가 보유한 iterator가 무효화됩니다.
Aa Aa Aa Aaa Aaaaa Aaaaaa Aa Aaaa Aaaaaa Aaaa Aaa Aaaaa Aaa Aaa Aaaaaaaaaaa Aaaaaaaaa Aaaaaaa Aaa Aaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaa Aaaa Aaaaaa Aa Aaaaaaaaaa Aaaa Aaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaa Aaaa Aa Aa Aaa Aaaaaa Aaa Aaaa Aaaaa Aaaaaa Aaaa Aaaaa Aaaaaaa Aaaaaa Aaa Aaaaaaaaa Aaaaaa Aaaaaaa Aaaaaaaaaaaaaaaaaaaa a Aaa Aaa a Aaa Aaa Aa Aaaa Aaaaa Aaaa Aaaaa
a Aaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaa Aaa Aaaaa Aaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaa Aaaaaa Aaaaaa Aa Aa Aaaaaaaaaaaaaaaaa Aaaaa Aaaa Aaaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaaa Aaaaaa Aaaaaaaaaa Aaaaaaaaaa Aaa Aaaa Aaaaa
🔒The threading and ownership model behind this singleton rewrite is dissected, including how the copy-on-write fast path interacts with concurrent readers.
더 확인하려면 구독해 주세요
Audit directions
a Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaa Aaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaaaa Aaaaaaa Aaaaaaaaaaaaaaaa a Aaaaaaaaaa Aaaaa Aaaaa Aaaaaaaaaaaaaaa Aa Aa Aaa Aa Aaaa Aaaaaa
a Aaaaaaaaaaa Aaa Aaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaa Aaaaaaaaaaaaa Aaaaaa a Aaaaaaaa a Aaaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa a Aaaaaaaaaaaaa Aa Aaa Aaaaaa
a Aaaaaaaaaaaa Aaaaa Aaaaaaa Aaaaaaaa Aaaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaaaa Aaaaaaa Aaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaa Aaaaaa
a Aaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaaaaaaaaaaa a Aaaaaaaa Aaaaaaaaa Aaaa Aaa Aaa Aaaa Aaaaaa Aaaaaa Aaaaaaaa Aaaa Aa Aaaaaaa Aaaa Aaaa Aaa Aaaaa Aaaa Aaa Aaa Aaaa
🔒Four reusable audit patterns covering singleton caches, escaped HashMap pointers, IPC-driven mutation, and copy-on-write fast paths.
더 확인하려면 구독해 주세요