0으로 초기화된 메모리

C 및 C++에서 초기화되지 않은 메모리는 안정성 문제, 메모리 안전 버그, 정보 유출의 일반적인 원인입니다. 이러한 문제를 방지하기 위해 Android에서는 최대한 많은 메모리를 초기화합니다.

0으로 초기화된 사용자 공간 메모리

Android 12부터 스택 메모리는 모든 플랫폼 네이티브 코드(JNI 포함)에서 0으로 초기화되고 힙 메모리는 모든 플랫폼 네이티브 프로세스(예: netd)에서 0으로 초기화되지만 zygote 또는 앱에서는 0으로 초기화되지 않습니다.

NDK로 빌드된 퍼스트 파티 및 서드 파티 애플리케이션에서는 -ftrivial-auto-var-init=zero 컴파일러 플래그를 사용하여 스택 로컬 변수를 0으로 초기화하는 것이 좋습니다. 불필요한 0은 모두 컴파일러가 최적화합니다. 예를 들어 로컬 변수가 명시적으로 초기화되는 경우입니다(예: int x = 123; 변수 x는 한 번만 초기화됨). 프로그램의 성능 핫스팟에 큰 스택 버퍼가 있는 경우 개발자는 컴파일러 속성을 사용하여 초기화를 사용 중지할 수 있습니다.

__attribute__((__uninitialized__)) char buf[BUFSIZ];

애플리케이션은 android:nativeHeapZeroInitialized 매니페스트 속성을 사용하여 힙 0 초기화를 선택할 수도 있습니다. 또는 런타임 시 다음을 사용하여 힙 0 초기화를 제어할 수 있습니다.

int mallopt(M_BIONIC_ZERO_INIT, level)

여기서 수준은 0 또는 1입니다.

0으로 초기화된 커널 메모리

커널 스택과 힙은 GKI 커널의 경우 0으로 초기화되며 이는 CDD에서 적극 권장합니다.

스택 초기화의 경우 GKI는 CONFIG_INIT_STACK_ALL_ZERO 구성을 사용하므로 -ftrivial-auto-var-init=zero 컴파일러 플래그를 사용하여 커널이 빌드됩니다. 힙 초기화의 경우 GKI는 CONFIG_INIT_ON_ALLOC_DEFAULT_ON을 사용하므로 모든 페이지 힙, SLAB, SLUB 할당이 만들어질 때 0으로 초기화됩니다. 이 옵션은 init_on_alloc=1을 커널 부팅 시간 옵션으로 전달하는 것과 사실상 유사합니다.

버그 신고

Google 도구는 디버깅에 도움이 되는 추가 정보가 포함된 유용한 버그 신고를 생성합니다. 추가 할당 및 할당 해제 스택 트레이스를 통해 지정된 할당의 수명 주기를 더욱 잘 파악할 수 있어 근본 원인이 되는 메모리 안전 버그를 훨씬 빠르게 찾아낼 수 있습니다.

메모리 안전 도구에서 생성된 버그 신고의 예
그림 1: 메모리 안전 도구에서 생성된 버그 신고

개발 중에 공급업체는 /data/tombstoneslogcat에서 네이티브 충돌이 있는지 확인하여 버그의 존재를 모니터링해야 합니다. Android 네이티브 코드 디버깅에 관한 자세한 내용은 여기 정보를 참고하세요.