Program sanitarny HWAddress

NDK na Androida obsługuje narzędzie HWAddress Sanitizer (znane też jako HWASan), począwszy od NDK r21 i Androida 10 (poziom interfejsu API 29). Interfejs HWASan jest dostępny tylko na urządzeniach 64-bitowych Arm.

HWASan to narzędzie do wykrywania błędów pamięci podobne do ASan. W porównaniu z klasycznym ASanem HWASan ma:

  • Podobny narzut procesora (ok. 2x)
  • Podobny rozmiar kodu (40–50%)
  • Znacznie mniejszy nadmiar pamięci RAM (10–35%)

HWASan wykrywa ten sam zestaw błędów co ASan:

  • Przepełnienie lub niedostateczna ilość bufora stosu i buforu sterty
  • Wykorzystanie sterty po bezpłatnym
  • Użycie stosu poza zakresem
  • Podwójny bezpłatny

HWASan wykrywa też:

  • Użycie stosu po zwrocie

Przykładowa aplikacja

Przykładowa aplikacja pokazuje, jak skonfigurować wariant kompilacji dla hwasan.

Budowanie

Aby utworzyć kod natywny (JNI) aplikacji przy użyciu HWAddress Sanitizer, wykonaj te czynności:

NK Build

W pliku Application.mk:

APP_STL := c++_shared # Or system, or none, but not c++_static.
APP_CFLAGS := -fsanitize=hwaddress -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=hwaddress

CMake

W pliku build.gradle modułu:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }
}

Dla każdego miejsca docelowego w pliku CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

Android 14 lub nowszy: dodaj plik wrap.sh

Jeśli masz Androida w wersji 14 lub nowszej, możesz użyć skryptu wrap.sh, aby uruchomić aplikację z możliwością debugowania na dowolnym urządzeniu z Androidem. Możesz pominąć ten krok, jeśli zdecydujesz się wykonać czynności podane w instrukcjach konfiguracji.

Wykonaj instrukcje spakowania skryptu wrap.sh, aby dodać ten skrypt wrap.sh dla arm64-v8a.

#!/system/bin/sh
LD_HWASAN=1 exec "$@"

Uruchom

Jeśli używasz Androida w wersji starszej niż 14 lub używasz skryptu wrap.sh, przed uruchomieniem aplikacji postępuj zgodnie z instrukcjami konfiguracji.

Uruchom aplikację w zwykły sposób. Po wykryciu błędu pamięci aplikacja ulega awarii za pomocą SIGABRT i wydrukuje szczegółowy komunikat w narzędziu logcat. Kopię wiadomości można znaleźć w pliku w lokalizacji /data/tombstones. Wygląda ona tak:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

Po komunikacie mogą znajdować się dodatkowe informacje na potrzeby debugowania, takie jak lista aktywnych wątków w aplikacji, tagi pobliskich przydziałów pamięci i wartości rejestrów procesora.

Więcej informacji o komunikatach o błędach HWASan znajdziesz w artykule z opisem raportów HWASan.

Tworzenie plików wykonywalnych wiersza poleceń

Na Androidzie 14 i nowszych możesz tworzyć i uruchamiać pliki wykonywalne używające narzędzia HWASan. Możesz użyć tej samej konfiguracji, co opisano w sekcji Build (kompilacja) dla ndk-build lub CMake w przypadku plików wykonywalnych. Wypchnij pliki wykonywalne na urządzenie z Androidem 14 lub nowszym i uruchom je w zwykły sposób za pomocą powłoki.

Jeśli używasz biblioteki libc++, pamiętaj, aby użyć udostępnionego pliku STL, przekazać go na urządzenie i ustawić LD_LIBRARY_PATH na katalog zawierający ten plik podczas uruchamiania pliku binarnego.

Jeśli nie korzystasz z Gradle, zapoznaj się z dokumentacją NDK, aby dowiedzieć się, jak tworzyć kompilacje z poziomu wiersza poleceń za pomocą CMake i ndk-build.

Android 13 lub starszy: konfiguracja

Jeśli masz urządzenie z Androidem 14 lub nowszym, możesz pominąć ten krok i postępować zgodnie z instrukcjami używania pliku wrap.sh w sekcji Tworzenie poniżej. Możesz też wykonać tę sekcję i pominąć instrukcje używania wrap.sh poniżej.

Przed Androidem 14 aplikacje HWASan muszą mieć kompilację Androida do obsługi HWASan. Na obsługiwanych urządzeniach Pixel możesz flashować gotowe obrazy HWASan. Kompilacje są dostępne na stronie ci.android.com, gdzie możesz kliknąć kwadrat odpowiadający jej dokładnej formie, aby uzyskać link do kompilacji Flash. Musisz znać kryptonim dla Twojego telefonu.

Flash do kompilacji urządzenia

Łatwiejszym rozwiązaniem może być przejście bezpośrednio na flash.android.com, ponieważ tam zaczyna się od wykrycia urządzenia i pokazuje tylko te kompilacje, których możesz używać. Poniższe obrazy ilustrują proces konfiguracji w tym narzędziu.

Włącz na urządzeniu tryb programisty i podłącz je do komputera kablem USB. Kliknij Dodaj nowe urządzenie, wybierz urządzenie w oknie i kliknij Połącz.

Wykrywanie lampy błyskowej Wybierz urządzenie, z którym chcesz się połączyć

Po połączeniu urządzenia kliknij je, aby skonfigurować kompilację. W polu Wybierz identyfikator kompilacji wybierz gałąź aosp-master-with-phones-throttled, aby automatycznie wybrać właściwy obraz dla połączonego urządzenia.

Wybierz urządzenie, które chcesz flashować Sprawdź opcje lampy błyskowej i wyszukaj urządzenie

Kliknij Zainstaluj, aby załadować urządzenie.

Więcej informacji o niezbędnej konfiguracji znajdziesz w dokumentacji Android Flash Tool. Instrukcje tworzenia obrazu HWASan na podstawie źródła znajdziesz też w dokumentacji AOSP.