메모리 오류 디버깅 및 완화

Android는 메모리 오류 디버깅을 위한 여러 도구를 지원합니다. 도구별로 장단점이 있으니 아래 내용을 참고하여 사용 사례에 가장 적합한 방법을 결정하세요. 이 문서에서는 더 자세히 살펴볼 수 있도록 각 도구를 간략하게 설명합니다. 설명이 자세하지 않으니 자세한 내용은 각 도구의 문서를 참고하세요.

요약 정리

  • 가능한 경우 메모리 안전 언어를 사용하여 메모리 오류를 방지합니다.
  • 항상 PAC/BTI를 사용하여 ROP/JOP 공격을 완화합니다.
  • 프로덕션에서 드물게 발생하는 메모리 오류를 감지하려면 항상 GWP-ASan을 사용합니다.
  • 테스트 중에 메모리 오류를 감지하려면 HWASan을 사용합니다.
  • MTE 지원 기기는 2023년에 정식 버전으로 출시되지 않지만, 프로덕션에서 오류를 감지할 수 있는 경우에 사용합니다.
  • 테스트 중에는 ASan을 마지막 수단으로만 사용합니다.

메모리 안전 언어

메모리 안전 언어는 메모리 오류를 완전히 방지하고 완화할 수 있는 유일한 방법입니다. 이 페이지에서 설명하는 다른 도구를 사용하면 메모리에 안전하지 않은 코드를 더 안전하고 안정적으로 만드는 데 도움이 될 수 있으나, 메모리 안전 언어를 사용하면 모든 유형의 문제가 사라집니다.

Android에서 공식적으로 지원되는 메모리 안전 언어는 Java와 Kotlin입니다. 대부분의 Android 애플리케이션은 이러한 언어 중 하나로 개발하는 것이 쉽습니다.

그러나 시중에는 Rust로 작성된 코드를 제공하는 앱 개발자가 있으며, 이 페이지를 보고 있다는 것은 네이티브 코드가 필요한 이유가 있기 때문일 것입니다(이동성, 성능 또는 둘 다). Rust는 Android의 메모리 안전 네이티브 코드에 가장 적합합니다. 이 방법을 사용할 경우 NDK팀에서 문제 해결을 지원하지 못할 수 있지만, 저희에게 알려주시면 도움이 됩니다.

PAC/BTI

포인터 인증 및 브랜치 타겟 식별(PAC/BTI)은 프로덕션에서 사용하기에 적합한 완화 도구입니다. 이 두 가지는 서로 다른 기술이긴 하나, 동일한 컴파일러 플래그로 제어되므로 항상 함께 사용됩니다.

이러한 기능은 이를 지원하지 않는 기기와 하위 호환됩니다. 이전 기기에서 사용된 새 명령이 노옵스(no-ops)이기 때문입니다. 또한 최신 커널과 최신 버전의 OS가 있어야 합니다. /proc/cpuinfo에서 pacabti를 찾으면 최신 하드웨어와 최신 커널이 있는지 알 수 있습니다. Android 12(API 31)에는 필요한 사용자 공간이 지원됩니다.

장점:

  • 이전 기기나 커널에서 문제를 일으키지 않고 모든 빌드에서 사용 설정할 수 있습니다. 하지만 이를 지원하는 기기/커널/OS 조합에서 실제로 테스트했는지 확인하세요.

단점:

  • 64비트 앱에서만 사용할 수 있습니다.
  • 지원하지 않는 기기의 오류는 완화하지 않습니다.
  • 코드 크기의 1%에 해당하는 오버헤드가 발생합니다.

GWP-Asan

GWP-ASan은 필드에서 메모리 오류를 감지하는 데 사용할 수 있으나, 샘플링 레이트가 너무 낮아서 효과적인 완화가 어렵습니다.

장점:

  • 큰 CPU 또는 메모리 오버헤드가 없습니다.
  • 간편한 배포: 네이티브 코드를 다시 빌드할 필요가 없습니다.
  • 32비트 앱에서 작동합니다.

단점:

  • 샘플링 레이트가 낮은 경우 버그를 효과적으로 찾으려면 많은 사용자가 필요합니다.
  • 힙 오류만 감지하고 스택 오류는 감지하지 않습니다.

HWASan

Hardware Address Sanitizer(HWASan)는 테스트 중에 메모리 오류를 포착하는 데 가장 적합합니다. 자동 테스트와 함께 사용할 때, 특히 퍼징 테스트를 실행하는 경우에 가장 유용하지만, 앱의 성능에 따라 dogfood 설정의 고급형 휴대전화에서도 사용할 수 있습니다.

장점:

  • 거짓양성이 없습니다.
  • ASan이 감지하지 못하는 추가적인 유형의 오류를 감지합니다(반환 후 스택 사용).
  • MTE보다 거짓음성률이 낮습니다(HWASan: 256개 중 1개, MTE: 16개 중 1개).
  • 가장 가까운 대안인 ASan보다 메모리 오버헤드가 낮습니다.

단점:

  • CPU(~100%), 코드 크기(~50%), 메모리(10%~35%) 오버헤드가 큽니다.
  • API 34 및 NDK r26까지는 HWASan 호환 이미지를 플래시해야 합니다.
  • 64비트 앱에서만 작동합니다.

MTE

Memory Tagging Extension(MTE)은 HWASan의 저렴한 대안입니다. MTE는 디버깅 및 테스트 기능을 제공하지만 그밖에 프로덕션 환경에서 메모리 손상을 감지하고 완화하는 데 사용할 수도 있습니다. MTE 빌드를 테스트할 하드웨어가 있는 경우 이를 사용 설정해야 합니다.

장점:

  • 여러 앱에서 프로덕션에 사용할 수 있을 만큼 오버헤드가 낮습니다.
  • 거짓양성이 없습니다.
  • 힙 오류를 감지하기 위해 코드를 다시 빌드할 필요가 없습니다(단, 스택 오류를 감지하려면 다시 빌드해야 함).

단점:

  • 2024년에 MTE가 기본적으로 사용 설정된 상업용 기기는 없지만 Arm 문서에서는 Pixel 8/Pixel 8 Pro에서 테스트하기 위해 MTE를 사용 설정하는 방법을 설명하고 있습니다.
  • 거짓음성률이 16개 중 1개입니다(HWASan: 256개 중 1개).
  • 64비트 앱에서만 사용할 수 있습니다.
  • MTE 지원 기기와 비 MTE 지원 기기를 모두 타겟팅하려면 별도의 라이브러리를 빌드해야 합니다.

ASan

Address Sanitizer(ASan)는 사용 가능한 도구 중에서 가장 오래되고 가장 널리 사용되는 도구입니다. 다른 도구를 사용할 수 없는, 이전 기기에만 영향을 주는 문제를 테스트 및 디버깅할 때 메모리 오류를 포착하는 데 유용합니다. 가능한 경우 항상 HWASan을 사용하세요.

장점:

  • 널리 사용됩니다. KitKat과 같은 이전 기기에서 작동할 수 있습니다.
  • 올바르게 사용할 경우 거짓양성이나 거짓음성이 없습니다.

단점:

  • 올바르게 빌드하고 패키징하기가 어렵습니다.
  • CPU ~100%, 코드 크기 ~50%, 메모리 사용량 ~100% 등 모든 옵션 중에서 오버헤드가 가장 큽니다.
  • 더 이상 지원되지 않습니다.
  • 앞으로 수정되지 않을 알려진 버그가 있습니다.