Remove code guarded by !HAVE(WK_SECURE_CODING_NSURLREQUEST)
Component: WebKit Cocoa IPC serialization | 36f536e
Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.h
Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.cpp
WebKit의 Cocoa IPC는 원래 임의의 NSSecureCoding 객체를 NSKeyedArchiver로 encode했습니다.
수신 process에서는 이를 NSKeyedUnarchiver로 decode했고, allowed-class 목록으로 허용 범위를 제한했습니다.
문제는 compromise되었을 수 있는 WebContent process가 보낸 데이터를 unarchive한다는 점입니다.
class allow-list는 중첩 class나 gadget class를 통해 우회될 수 있어, 이 구조는 오랫동안 sandbox escape 버그의 출처가 되어 왔습니다.
그래서 WebKit은 type 단위로 이 방식을 CoreIPC* wrapper class로 대체해 왔습니다.
이 wrapper는 명시적인 필드만 serialize하고, 수신 측에서 ObjC 객체를 다시 구성합니다.
NSURLRequest는 마지막으로 전환된 type이었습니다.
다만 Cocoa에서 해당 flag가 무조건 설정된 이후에도, legacy 경로는 !HAVE(WK_SECURE_CODING_NSURLREQUEST) 뒤에 그대로 남아 있었습니다.
이 commit은 legacy decode 경로를 제거했습니다. 이 경로의 대부분은 이미 해당 guard로 인해 컴파일에서 제외된 상태였습니다.
함께 제거된 인프라는 다음과 같습니다.
CoreIPCRetainPtr.h, CoreIPCSecureCoding.serialization.in, 그리고 CoreIPCSecureCoding.{h,mm} 내부 구현(constructor, toID, objectClass, crashWithClassName, exemption helper)이 삭제되었습니다.
SecureCodingAllowed serializer attribute, Decoder::decodeWithAllowedClasses, WKSecureCodingURLWrapper/WKSecureCodingCGColorWrapper archiving shim도 제거되었습니다.
classNamesExemptFromSecureCodingCrash process 생성 파라미터 역시 제거 대상에 포함되었습니다.
한편 이 파라미터와 SecureCoding::applyProcessCreationParameters 호출은 guard 밖에 있었습니다.
결과적으로 이번 제거는 AuxiliaryProcessCreationParameters의 IPC wire format에도 변경을 가져왔습니다.
Before (HAVE=1 on Cocoa):
RetainPtr<T> decode
└─► decodeWithAllowedClasses<T> [live]
├─► m_allowedClasses = ... [compiled out]
└─► decodeRequiringAllowedClasses<T> [live]
├─► decodeObjectDirectlyRequiringAllowedClasses<T>
│ ├─► per-type CoreIPC decoder [live path]
│ └─► NSObject<NSSecureCoding> specialization
│ └─► NSKeyedUnarchiver [compiled out]
└─► ASSERT(isObjectClassAllowed) [compiled out]
After:
RetainPtr<T> decode
└─► decodeObjectDirectly<T>
└─► per-type CoreIPC decoder
Significance
PlatformHave.h는 이미 모든 Cocoa 플랫폼에서 HAVE_WK_SECURE_CODING_NSURLREQUEST를 1로 정의하고 있었으므로, guard 안의 NSKeyedUnarchiver 코드와 allow-list 관련 코드는 도달할 수 없는 상태였습니다. 이를 제거하면서 점검이 필요한 IPC decoding surface가 줄어들었습니다.
반면 guard 밖의 classNamesExemptFromSecureCodingCrash 관련 코드는 컴파일에는 포함되어 있었습니다. 다만 실제로는 아무 효과가 없었을 가능성이 높습니다.
이번 commit으로 2022년에 시작된 migration이 마무리되었습니다.
Audit directions
대부분은 이미 도달 불가능했던 코드를 걷어낸 attack surface 축소입니다.
다만 이 정리 작업은 남아 있는 공용 decoding 코드에도 영향을 줍니다.
먼저 ArgumentCoder<RetainPtr<T>>::decode가 이제 decodeObjectDirectly<U>를 직접 호출하며, decodeObjectDirectlyRequiringAllowedClasses는 이름이 변경되었습니다.
또한 CoreIPCNSCFObject::valueIsAllowed가 삭제되었고 valueFromID는 수정되었습니다.
generate-serializers.py에서도 allowed-classes decode 분기가 제거되었습니다.
제거된 isObjectClassAllowed check는 assertion 전용이었고 !HAVE로 guard되어 있었습니다.
따라서 이 부분에서 release 빌드의 validation이 사라지지는 않았습니다.
반면 CoreIPCNSCFObject::valueIsAllowed는 사정이 다릅니다. 이 함수는 삭제되었고, 같은 시점에 valueFromID가 수정되었습니다.
valueIsAllowed가 release 빌드에서 실제로 검증을 수행했는지 확인할 필요가 있습니다.
만약 그랬다면, 수정된 valueFromID가 그 검증을 대신하는지도 살펴봐야 합니다.
좁은 범위: 이름이 변경된 경로에서 기계적인 rename 과정의 실수가 없는지 점검합니다. 이제 type별 validation에만 의존하게 된 generated decoder도 함께 살펴볼 필요가 있습니다.
넓은 범위: 범용 NSSecureCoding fallback을 전제로 했던 호출 지점이나 serialization spec이 남아 있는지 검색합니다.