[20] [JSC] DFG object allocation sinking shouldn't insert a check when given a PutByVal
DFG allocation sinking 단계에 잔존하던 특수 처리 코드가 현재 graph invariant를 위반하는 IR을 생성했기 때문에 Medium으로 분류되었습니다.
--validateGraph빌드에서는GetButterflyvalidator rule 위반이 발생했습니다. Release 빌드에서는 잘못 컴파일된 graph가 이후 단계에 전달되어 일관성 없는 exit-state metadata를 동반할 가능성이 있습니다.
ObjectAllocationSinkingPhase::run() 안에 남아 있던 if (node->op() == PutByVal) 블록이 합성된 PutHint 앞에 저장 값에 대한 Check를 삽입했습니다. 이 블록은 현재 교체된 array-sinking 구현을 위한 수정 코드였으며, 주변 코드의 invariant와 더 이상 일치하지 않았습니다.
Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp / DFGValidate.cpp
주변 알고리즘이 교체된 이후에도 잔존하여, 현재 DFG graph invariant를 위반하는 node를 생성하던 최적화 단계의 오래된 code path.
GetButterfly validator rule도 함께 제거되었습니다. 이는 allocation-sinking 처리 과정이 이제 이전 validator에서 금지했던 형태를 합법적으로 생성하게 되었음을 나타냅니다.
회귀 테스트는 --validateGraphAtEachPhase=1 --validateGraph=true 옵션 하에서 단순한 array-store loop를 실행합니다. 이는 fuzzer minimization 또는 내부 validation 기반 crash에서 비롯된 패턴으로 볼 수 있습니다. Apple은 commit의 rdar/backport metadata를 근거로 이 수정을 보안 관련 사항으로 분류했습니다. 다만 diff 자체는 해당 단계가 validator에서 금지된 graph 형태를 생성했음을 드러낼 뿐이며, release 빌드에서 나타나는 downstream 결과는 diff만으로는 드러나지 않습니다.
이 vulnerability는 renderer 내부에서 DFG compiler의 correctness 보장을 약화시킵니다. 패치 이전에는 해당 단계가 DFG validation invariant를 위반하는 graph를 생성할 수 있었습니다. 결과적으로 이후 단계들이 일관성 없는 IR을 기반으로 동작하게 될 가능성이 있었습니다.
Audit directions
- 교체된 compiler 단계 이후 잔존하는 node 삽입.
DFGObjectAllocationSinkingPhase.cpp와DFGValidate.cpp에 대해git log -p를 실행하여 제거된 알고리즘을 참조하는 주석이 달린 guard 블록을 확인합니다. 범용 loop 내부에서 단일 opcode만을 처리하는if (node->op() == ...)분기를 검색합니다. - exit-state clobberization이 삽입 지점과 일치해야 하는 phase 생성 node.
ObjectAllocationSinkingPhase,ArgumentsEliminationPhase,PutStackSinkingPhase에서Check/CheckInBounds/Phantom삽입 지점을 전수 점검합니다. - phase 수정과 함께 삭제된 DFG validator rule. 해당 완화 조치가 IR semantics에 의해 정당화된 것인지, 즉각적인 수정으로 단순히 억제된 것인지 확인합니다.