HWAddressSanitizer

HWASan 비정상 종료를 읽는 방법에 관한 자세한 내용은 HWASan 보고서 이해하기를 참고하세요.

하드웨어 지원 AddressSanitizer(HWASan)는 AddressSanitizer와 유사한 메모리 오류 감지 도구입니다. HWASan은 ASan에 비해 RAM을 훨씬 적게 사용하므로 전체 시스템 정리에 적합합니다. HWASan은 Android 10 이상 및 AArch64 하드웨어에서만 사용할 수 있습니다.

주로 C/C++ 코드에 유용하지만 HWASan은 자바 인터페이스를 구현하는 데 사용되는 C/C++에서 비정상 종료를 일으키는 자바 코드를 디버그하는 데도 도움이 될 수 있습니다. 메모리 오류가 발생할 때 이를 포착하여 원인이 된 코드를 직접 가리키므로 유용합니다.

미리 빌드된 HWASan 이미지를 ci.android.com에서 지원되는 Pixel 기기에 플래시할 수 있습니다(자세한 설정 안내).

HWASan은 기본 ASan과 비교하여 다음과 같은 이점이 있습니다.

  • 유사한 CPU 오버헤드(최대 2배)
  • 유사한 코드 크기 오버헤드(40~50%)
  • RAM 오버헤드가 훨씬 적음(10%~35%)

HWASan은 다음과 같이 ASan과 동일한 버그 집합을 감지합니다.

  • 스택 및 힙 버퍼 오버플로우/언더플로우
  • 프리 후 힙 사용
  • 범위를 벗어난 스택 사용
  • 더블 프리/와일드 프리

또한 HWASan은 반환 후에 스택 사용을 감지합니다.

HWASan은 ASan과 마찬가지로 UBSan과 호환됩니다. 타겟에서 동시에 이 둘을 사용 설정할 수 있습니다.

구현 세부정보 및 제한사항

HWASan은 메모리 태그하기 접근 방식을 기반으로 하며, 작은 임의 태그 값이 포인터 및 메모리 주소 범위와 연결됩니다. 메모리 액세스가 유효하려면 포인터와 메모리 태그가 일치해야 합니다. HWASan은 포인터 태그를 주소의 최상위 비트에 저장하기 위해 가상 주소 태그하기라고도 하는 ARMv8의 기능인 TBI(Top Byte Ignore)를 사용합니다.

HWASan의 설계에 관한 자세한 내용은 Clang 문서 사이트를 참조하세요.

의도적으로, HWASan에는 오버플로우 감지를 위한 ASan의 크기가 제한된 Redzone 또는 해제 후 사용 감지를 위한 ASan의 제한된 용량 격리 저장소가 없습니다. 따라서 HWASan은 오버플로우의 크기 또는 메모리 할당 취소 기간에 상관없이 버그를 감지할 수 있습니다. 덕분에 HWASan은 ASan에 비해 큰 이점을 갖습니다.

하지만 HWASan은 가능한 태그 값이 256개로 제한되어 있으므로 프로그램을 한 번 실행하는 동안 버그가 누락될 확률은 0.4%입니다.

요구사항

Android 일반 커널의 최신 버전(4.14 및 이후 버전)은 추가 설정 없이 HWASan을 지원합니다. Android 10의 특정 브랜치는 HWASan을 지원하지 않습니다.

HWASan의 사용자 공간 지원은 Android 11부터 사용할 수 있습니다.

다른 커널을 사용하는 경우 HWASan이 지원되려면 Linux 커널이 시스템 호출 인수에서 태그된 포인터를 받아야 합니다. 이를 위한 지원은 다음 업스트림 패치 세트에 구현되었습니다.

맞춤 도구 모음을 사용하여 빌드하는 경우에는 LLVM 커밋 c336557f까지 모두 포함되어 있는지 확인해야 합니다.

HWASan 사용

다음 명령어를 사용하여 HWASan을 사용하는 전체 플랫폼을 빌드합니다.

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

편의상 aosp_coral_hwasan과 유사하게 제품 정의에 SANITIZE_TARGET 설정을 추가할 수 있습니다.

AddressSanitizer에 익숙한 사용자의 경우 다음과 같은 여러 빌드 복잡성이 사라집니다.

  • make를 두 번 실행할 필요가 없습니다.
  • 증분 빌드를 추가 설정 없이 사용할 수 있습니다.
  • 사용자 데이터를 플래시할 필요가 없습니다.

다음과 같은 AddressSanitizer 제한도 사라졌습니다.

  • 정적 실행 파일이 지원됩니다.
  • libc를 제외한 모든 타겟의 제거를 건너뛰어도 괜찮습니다. ASan과 달리, 라이브러리가 제거된 경우 이 라이브러리를 연결하는 모든 실행 파일도 제거되어야 한다는 요구사항이 없습니다.

HWASan 및 동일한(또는 보다 높은) 빌드 번호를 갖는 일반 이미지 간에 자유롭게 전환할 수 있습니다. 기기를 완전 삭제할 필요가 없습니다.

모듈 제거를 건너뛰려면 LOCAL_NOSANITIZE := hwaddress(Android.mk) 또는 sanitize: { hwaddress: false }(Android.bp)를 사용합니다.

개별 타겟 제거

HWASan은 libc.so도 함께 제거되는 한 일반(제거되지 않은) 빌드에서 타겟별로 사용 설정할 수 있습니다. bionic/libc/Android.bp의 "libc_defaults"에 있는 제거 블록에 hwaddress: true를 추가합니다. 그런 다음 작업 중인 타겟에서도 동일한 작업을 적용합니다.

libc를 제거하면 시스템 전체의 힙 메모리 할당을 태그할 수 있고 libc.so 내부의 메모리 작업 태그를 확인할 수 있습니다. 이를 통해 잘못된 메모리 액세스가 libc.so에 있는 경우(예: delete()된 뮤텍스의 pthread_mutex_unlock()) HWASan이 사용 설정되지 않은 바이너리에서도 버그를 발견할 수 있습니다.

플랫폼 전체가 HWASan을 사용하여 빌드되었다면 빌드 파일을 변경할 필요가 없습니다.

Flashstation

부트로더가 잠금 해제된 Pixel 기기에 HWASan이 사용 설정된 AOSP 빌드를 Flashstation을 사용하여 개발용으로 플래시할 수 있습니다. _hwasan 타겟(예: aosp_flame_hwasan-userdebug)을 선택합니다. 자세한 내용은 앱 개발자를 위한 HWASan NDK 문서를 참고하세요.

향상된 스택 트레이스

HWASan은 고속 프레임 포인터 기반 언와인더를 사용하여 프로그램의 모든 메모리 할당 및 할당 취소 이벤트에 관한 스택 트레이스를 기록합니다. Android는 기본적으로 AArch64 코드에서 프레임 포인터를 사용 설정하므로 실제로 매우 잘 작동합니다. 관리 코드를 통해 해제해야 하는 경우 프로세스 환경에서 HWASAN_OPTIONS=fast_unwind_on_malloc=0을 설정합니다. 잘못된 메모리 액세스 스택 트레이스는 기본적으로 '느린' 언와인더를 사용합니다. 이 설정은 할당 및 할당 취소 트레이스에만 영향을 미칩니다. 이 옵션은 로드에 따라 CPU를 매우 많이 사용할 수 있습니다.

기호화

'HWASan 보고서 이해하기'의 기호화를 참고하세요.

앱 내 HWASan

AddressSanitizer와 마찬가지로 HWASan에서는 자바 코드를 볼 수 없지만 JNI 라이브러리에서 버그를 감지할 수 있습니다. ASan과 달리 HWASan 기기 이외의 기기에서는 HWASan 앱을 실행할 수 없습니다.

HWASan 기기에서 Make에서는 SANITIZE_TARGET:=hwaddress로, 컴파일러 플래그에서는 -fsanitize=hwaddress로 앱 코드를 빌드하여 HWASan으로 앱을 확인할 수 있습니다. 자세한 내용은 앱 개발자 문서를 참조하세요.