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가 기기에 영향을 미치지 않는지 확인할 수 있습니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# ShadowCallStack\n\n| **Note:** ShadowCallStack is only implemented for aarch64.\n\nShadowCallStack (SCS) is an [LLVM instrumentation](https://clang.llvm.org/docs/ShadowCallStack.html) mode that protects against\nreturn address overwrites (like stack buffer overflows) by saving a function's\nreturn address to a separately allocated **ShadowCallStack** in\nthe function prolog of nonleaf functions and loading the return address from\nthe ShadowCallStack in the function epilog. The return address is also stored\non the regular stack for compatibility with unwinders, but is otherwise unused.\nThis ensures that attacks that modify the return address on the regular stack\nhave no effect on program control flow.\n\nOn aarch64, the instrumentation makes use of the `x18`\nregister to reference the ShadowCallStack, meaning that references\nto the ShadowCallStack don't have to be stored in memory.\nThis makes it possible to implement a runtime that avoids exposing\nthe address of the ShadowCallStack to attackers that can read\narbitrary memory.\n\nImplementation\n--------------\n\nAndroid supports ShadowCallStack for both kernel and userspace.\n\n### Enable SCS for the kernel\n\nTo enable ShadowCallStack for the kernel, add the following line to the\nkernel config file: \n\n```\nCONFIG_SHADOW_CALL_STACK=y\n```\n\n### Enable SCS in userspace\n\nTo enable ShadowCallStack in userspace components, add the\nfollowing lines to a component's blueprint file: \n\n```\nsanitize: {\n scs: true\n}\n```\n\nSCS assumes that the `x18` register is reserved to store the address of the\nShadowCallStack, and isn't used for any other purposes. While all system\nlibraries are compiled to reserve the `x18` register, this is potentially\nproblematic if SCS is enabled for userspace components that interoperate with\nin-process legacy code (for example, libraries that could be loaded by third-party\napps), which may clobber the `x18` register. As such, we only recommend\nenabling SCS in self-contained components that won't be loaded into legacy\nbinaries.\n\nValidation\n----------\n\nThere are no CTS test specifically for SCS. Instead, make sure that CTS tests\npass with and without SCS enabled to verify that SCS isn't impacting the\ndevice."]]