REGRESSION(314479@main): Crash in WebPushD::Connection::connectionReceivedEvent() due to xpc_object_t ODR violation
// Source/WebKit/NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm
+// 이 destructor는 반드시 이 .mm 파일에 정의되어야 합니다 (WebPushDaemonConnection.cpp에는 두면 안 됩니다).
+// pure하지 않고 inline도 아닌 첫 번째 virtual로서 Connection의 key function에 해당하며,
+// vtable은 이와 동일한 translation unit에서 생성됩니다. xpc_object_t는 .mm TU에서는
+// OS_xpc_object*로, .cpp TU에서는 void*로 해석됩니다. .cpp TU에서 vtable을 생성하면
+// 슬롯이 void* discriminator로 서명되어, .mm 호출 지점마다 arm64e PAC 실패가 발생합니다.
+Connection::~Connection() = default;
arm64e는 각 virtual function의 mangled name을 기반으로 PAC discriminator를 산출하고, vtable function pointer에 서명합니다. C 헤더 <os/object.h>는 __OBJC__ 여부에 따라 OS_OBJECT_USE_OBJC를 제어합니다. 그 결과, .mm TU에서는 xpc_object_t가 ObjC object pointer(OS_xpc_object*)로 해석되어 특정 mangled name을 생성하고, .cpp TU에서는 void*로 해석되어 다른 mangled name이 생성됩니다. C++ vtable 생성은 key function 규칙을 따릅니다. vtable은 key function(pure하지 않고 inline도 아닌 첫 번째 out-of-line virtual)을 정의하는 TU에서 strong external symbol로 단 한 번 방출됩니다.
이 commit은 WebPushD::Connection::~Connection()을 WebPushDaemonConnection.cpp에서 WebPushDaemonConnectionCocoa.mm으로 이동시켰습니다. destructor가 key function이므로, vtable은 이제 .mm TU에서 방출됩니다. 이에 따라 모든 슬롯이 .mm 호출 지점에서 기대하는 ObjC OS_xpc_object* discriminator로 서명됩니다. 수정 이전에는 vtable이 .cpp에서 방출되어 void* 기반 discriminator가 적용되었고, .mm 호출 지점마다 NetworkProcess에서 EXC_ARM_PAC_FAIL이 발생했습니다.
Significance
감지되기 어려운 ODR violation으로 인해 WebPushD::Connection의 vtable이 잘못된 PAC discriminator로 서명되어 arm64e crash를 유발하는 문제를 수정합니다. 동일한 패턴이 Cocoa 연동 WebKit 코드 전반에서 반복될 경우, arm64e PAC 보호가 눈에 띄지 않게 약화될 수 있는 구조적 함정입니다.
Audit directions
- 헤더가
.cpp및.mmTU 양쪽에 포함되고, key function이.cppTU에 위치하면서, XPC 또는 libdispatch가 제공하는 타입(xpc_object_t,dispatch_object_t,dispatch_queue_t)을 인수로 받는 virtual method를 가진 WebKit 클래스. 이 조건에 해당하는 클래스는 vtable이void*discriminator로 서명되어, 해당 virtual dispatch 지점에서 PAC가 약화됩니다. - key function의 위치와 헤더 내 타입 해석 결과를 교차 검증해야 합니다. commit에서는
PCM::Connection의 경우 key function이 이미.mm에 위치해 있어 우연히 안전한 상태였다고 언급합니다. 이는 이 문제가 체계적으로 발견된 것이 아니라 우연히 드러났음을 시사합니다.Source/WebKit/NetworkProcess,Source/WebKit/GPUProcess,Source/WebKit/Shared하위의 XPC 관련 virtual interface 전체를 점검할 필요가 있습니다. - 이러한 호출 지점에 도달하는 type confusion 또는 vtable corruption primitive는 주변 코드의 전제보다 실제 인증 강도가 낮습니다. XPC 처리 virtual을 통해 primitive를 연결하는 시나리오에서는 이 점이 중요하게 작용합니다.