ShadowCallStack

ShadowCallStack(SCS)은 nonleaf 함수의 함수 프롤로그에서 별도로 할당된 ShadowCallStack에 함수의 반환 주소를 저장하고 함수 에필로그의 ShadowCallStack에서 반환 주소를 로드하는 방식으로 반환 주소 덮어쓰기(예: 스택 버퍼 오버플로)를 방지하는 LLVM 계측 모드입니다. 반환 주소는 언와인더와의 호환성을 위해 정규 스택에도 저장되지만 다른 경우에는 사용되지 않습니다. 이렇게 하면 정규 스택의 반환 주소를 수정하는 공격이 프로그램 제어 흐름에 영향을 주지 않습니다.

aarch64에서 계측은 x18 레지스터를 사용하여 ShadowCallStack을 참조합니다. 즉, ShadowCallStack 참조를 메모리에 저장할 필요가 없습니다. 따라서 임의의 메모리를 읽을 수 있는 공격자에게 ShadowCallStack 주소가 노출되지 않도록 런타임을 구현할 수 있습니다.

구현

Android는 커널과 사용자 공간에서 모두 ShadowCallStack을 지원합니다.

커널에 SCS 사용 설정

커널에 ShadowCallStack을 사용 설정하려면 다음 행을 커널 구성 파일에 추가합니다.

CONFIG_SHADOW_CALL_STACK=y

사용자 공간에 SCS 사용 설정

사용자 공간 구성요소에서 ShadowCallStack을 사용 설정하려면 구성요소의 청사진 파일에 다음 행을 추가합니다.

    sanitize: {
      scs: true
    }
    

SCS는 x18 레지스터가 ShadowCallStack 주소를 저장하기 위해 예약되며 다른 용도로 사용되지 않는다고 가정합니다. 모든 시스템 라이브러리가 x18 레지스터를 예약하기 위해 컴파일되지만, SCS가 처리 중인 레거시 코드와 호환되는 사용자 공간 구성요소(예: 타사 애플리케이션에서 로드할 수 있는 라이브러리)에 사용 설정되는 경우 x18 레지스터를 클로버할 수 있으므로 잠재적으로 문제가 될 수 있습니다. 따라서 레거시 바이너리에 로드되지 않는 독립형 구성요소에만 SCS를 사용 설정하는 것이 좋습니다.

유효성 검사

SCS 전용 CTS 테스트는 없습니다. 대신 SCS를 사용 설정하거나 사용 중지한 상태에서 CTS 테스트를 통과하도록 하여 SCS가 기기에 영향을 미치지 않는지 확인할 수 있습니다.