Aby dowiedzieć się, jak interpretować raporty HWASan, przeczytaj artykuł Informacje o raportach HWASan.
Narzędzie do wykrywania błędów pamięci oparte na sprzęcie (HWASan) jest podobne do narzędzia AddressSanitizer. HWASan zużywa znacznie mniej pamięci RAM w porównaniu z ASan, co czyni go odpowiednim do sterylizacji całego systemu. HWASan jest dostępny tylko na Androidzie 10 i nowszych i wyłącznie na sprzęcie AArch64.
HWASan jest przydatny przede wszystkim w przypadku kodu C/C++, ale może też pomóc w debugowaniu kodu Javy, który powoduje awarie kodu C/C++ używanego do implementowania interfejsów Javy. Jest to przydatne, ponieważ pozwala wykrywać błędy pamięci w momencie ich wystąpienia i wskazywać bezpośrednio kod, który je wywołuje.
Gotowe obrazy HWASan można wgrać na obsługiwane urządzenia Pixel ze strony ci.android.com (szczegółowe instrukcje konfiguracji).
W porównaniu z klasyczną funkcją ASan funkcja HWASan:
- Podobny narzut procesora (~2x)
- Narzut związany z podobnym rozmiarem kodu (40–50%)
- znacznie mniejsze obciążenie pamięci RAM (10–35%),
HWASan wykrywa te same błędy co ASan:
- Przepełnienie/niedopełnienie bufora stosu i bufora stosu.
- Użycie sterty po zwalnianiu
- Użycie zasobów z poziomu zewnętrznego
- podwójne wolne/wolne
Dodatkowo HWASan wykrywa użycie stosu po powrocie.
HWASan (czyli ASan) jest zgodny z UBSan. Oba mogą być włączone w tym samym celu jednocześnie.
Szczegóły implementacji i ograniczenia
HWASan opiera się na podejściu tagowania pamięci, w którym mała losowa wartość tagu jest powiązana zarówno z wskaźnikami, jak i z zakresami adresów pamięci. Aby dostęp do pamięci był prawidłowy, tagi wskaźnika i pamięci muszą być zgodne. HWASan korzysta z funkcji ARMv8, która ignoruje najwyższy bajt (TBI), czyli tagowanie adresów wirtualnych, aby przechowywać tag wskaźnika w najwyższych bitach adresu.
Więcej informacji o projektowaniu HWASan znajdziesz w dokumentacji Clang.
Z założenia HWASan nie ma czerwonych stref o ograniczonym rozmiarze w ASan do wykrywania przepełnienia ani kwarantanny o ograniczonej pojemności w ASan do wykrywania użycia po okresie bezpłatnym. Z tego powodu HWASan może wykryć błąd niezależnie od tego, jak duży jest przepełniony obszar pamięci lub jak dawno został on zwolniony. Daje to HWASan dużą przewagę nad ASan.
HWASan ma jednak ograniczoną liczbę możliwych wartości tagów (256), co oznacza, że podczas jednego uruchomienia programu istnieje 0,4% prawdopodobieństwo, że nie zostanie wykryty żaden błąd.
Wymagania
Najnowsze wersje (4.14+) wspólnego jądra Androida obsługują HWAS „z pudełka”. Gałęzie przeznaczone do Androida 10 nie obsługują HWASan.
Obsługa przestrzeni użytkownika dla HWASan jest dostępna od Androida 11.
Jeśli używasz innego jądra, HWASan wymaga, aby jądro Linuxa akceptowało otagowane wskaźniki w argumentach wywołania systemu. Obsługa tej funkcji została zaimplementowana w tych zbiorach poprawek upstream:
- arm64 tagged address ABI
- arm64: usuń tagi ze wskaźników użytkownika przekazywanych do jądra
- mm: Avoid creating virtual address aliases in brk()/mmap()/mremap()
- arm64: zweryfikuj otagowane adresy w funkcji access_ok() wywołanej z wątków jądra
Jeśli kompilujesz za pomocą niestandardowego zestawu narzędzi, upewnij się, że zawiera on wszystko do commita LLVM c336557f.
Używanie HWASan
Aby utworzyć całą platformę za pomocą HWASan, użyj tych poleceń:
lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j
Dla wygody możesz dodać ustawienie SANITIZE_TARGET do definicji produktu, na przykład aosp_coral_hwasan.
Użytkownicy znający narzędzie AddressSanitizer nie muszą już zajmować się wieloma złożonymi kwestiami związanymi z kompilacją:
- Nie musisz uruchamiać make dwukrotnie.
- Kompilacje przyrostowe działają od razu po zainstalowaniu.
- Nie ma potrzeby aktualizowania danych użytkownika.
Zrezygnowaliśmy też z niektórych ograniczeń usługi AddressSanitizer:
- Obsługiwane są statyczne pliki wykonywalne.
- Możesz pominąć sterylizację dowolnego celu innego niż libc. W przeciwieństwie do ASan nie ma wymogu, aby biblioteka była skanowana, a wszystkie pliki wykonywalne, do których się odwołuje, również.
Przełączanie się między obrazami HWASan a zwykłymi obrazami o tym samym (lub wyższym) numerze kompilacji jest dowolne. Nie trzeba czyścić urządzenia.
Aby pominąć sterylizację modułu, użyj opcji LOCAL_NOSANITIZE := hwaddress
(Android.mk) lub sanitize: { hwaddress: false }
(Android.bp).
Sanitize individual targets
HWASan można włączyć w ramach poszczególnych docelowych wersji w zwykłej (nieoczyszczonej) kompilacji, o ile libc.so
jest również oczyszczona. Dodaj hwaddress: true
do bloku oczyszczania w pliku "libc_defaults"
w bionic/libc/Android.bp. Następnie zrób to samo w przypadku celu, nad którym pracujesz.
Pamiętaj, że sterylizacja biblioteki libc umożliwia oznaczanie alokacji pamięci stosu w całym systemie, a także sprawdzanie tagów pod kątem operacji na pamięci w funkcji libc.so
. Może to wykrywać błędy nawet w binarnych plikach, w których nie włączono HWASan, jeśli dostęp do pamięci jest nieprawidłowy (np.libc.so
pthread_mutex_unlock()
na zablokowanym delete()
.
Jeśli cała platforma jest kompilowana za pomocą HWASan, nie trzeba zmieniać żadnych plików kompilacji.
Flashstation
W celu ułatwienia procesu tworzenia możesz za pomocą Flashstation wgrać na urządzeniu Pixel z odblokowanym bootloaderem kompilację AOSP z obsługą HWAS. Wybierz cel _hwasan, np. aosp_flame_hwasan-userdebug. Więcej informacji znajdziesz w dokumentacji NDK dla HWASan dla programistów aplikacji.
Lepsze zrzuty stosu
HWASan używa szybkiego odwijacza opartego na wskazniku ramki do rejestrowania ścieżki stosu dla każdego zdarzenia przydzielenia i zwolnienia pamięci w programie. Android domyślnie włącza wskaźniki ramki w kodzie AArch64,
dzięki czemu działa to świetnie w praktyce. Jeśli chcesz odtworzyć kod zarządzany, ustaw zmienną HWASAN_OPTIONS=fast_unwind_on_malloc=0
w środowisku procesu. Pamiętaj, że śledzenie ścieżki wywołań w przypadku błędnego dostępu do pamięci jest domyślnie używane w trybie „wolnym”. To ustawienie dotyczy tylko ścieżek alokacji i zwolnienia alokacji. W zależności od obciążenia ta opcja może mocno obciążać procesor.
Symbole
Zapoznaj się z sekcją Interpretowanie raportów HWASan w artykule „Interpretowanie raportów HWASan”.
HWASan w aplikacjach
Podobnie jak narzędzie AddressSanitizer, HWASan nie może przeglądać kodu Java, ale może wykrywać błędy w bibliotekach JNI. Do Androida 14 uruchamianie aplikacji HWASan na urządzeniach innych niż HWASan nie było obsługiwane.
Na urządzeniu HWASan można sprawdzić aplikacje za pomocą HWASan, kompilując kod za pomocą parametru SANITIZE_TARGET:=hwaddress
w Make lub -fsanitize=hwaddress
w flagach kompilatora.
Na urządzeniu innym niż HWASan (z Androidem 14 lub nowszym) musisz dodać ustawienie pliku wrap.sh LD_HWASAN=1
.
Więcej informacji znajdziesz w dokumentacji dla deweloperów aplikacji.