Program do sprzątania adresów

AddressSanitizer (ASan) to szybkie narzędzie oparte na kompilatorze do wykrywania błędów pamięci w kodzie natywnym.

ASan wykrywa:

  • 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/bezpieczne dzikie

ASan działa na procesorach ARM 32- i 64-bitowych oraz x86 i x86-64. Narzut na procesor w ASan wynosi około 2 razy, narzut na rozmiar kodu – od 50% do 2 razy, a narzut na pamięć – około 2 razy (zależy od wzorca alokacji, ale jest to około 2 razy).

Android 10 i główna gałąź AOSP na AArch64 obsługują AddressSanitizer z obsługą sprzętową (HWASan), czyli podobne narzędzie z mniejszym obciążeniem pamięci RAM i większym zakresem wykrywanych błędów. HWASan wykrywa wykorzystanie stosu po powrocie, oprócz błędów wykrytych przez ASan.

HWASan ma podobny narzut na procesor i rozmiar kodu, ale znacznie mniejszy narzut na pamięć RAM (15%). HWASan jest niedeterministyczny. Istnieje tylko 256 możliwych wartości tagów, więc prawdopodobieństwo przeoczenia błędu wynosi 0,4%. HWASan nie ma stref czerwonych o ograniczonej wielkości, które służą do wykrywania przepełnienia, ani stref kwarantanny o ograniczonej pojemności, które służą do wykrywania użycia po zwolnieniu, więc nie ma znaczenia, jak duże jest przepełnienie ani jak dawno przydzielone było pamięci. Dzięki temu HWASan jest lepszy niż ASan. Więcej informacji o projektowaniu interfejsu HWASan oraz o używaniu HWASan na Androidzie.

ASan wykrywa przepełnienia stosu/globalne oprócz przepełnień stosu i jest szybki przy minimalnym narzutem na pamięć.

Z tego dokumentu dowiesz się, jak kompilować i uruchamiać części lub całość Androida za pomocą ASANA. Jeśli tworzysz aplikację z użyciem SDK lub NDK z użyciem ASan, zapoznaj się z artykułem Address Sanitizer.

Sanitize poszczególnych plików wykonywalnych za pomocą ASan

Dodaj LOCAL_SANITIZE:=address lub sanitize: { address: true } do reguły kompilacji pliku wykonywalnego. Możesz wyszukać w kodzie istniejące przykłady lub znaleźć inne dostępne środki do dezynfekcji.

Gdy zostanie wykryty błąd, ASan wypisuje obszerny raport zarówno do standardowego wyjścia, jak i do pliku logcat, a potem powoduje awarię procesu.

Czyszczenie bibliotek udostępnionych za pomocą ASan

Ze względu na sposób działania ASan biblioteki utworzone za pomocą ASan mogą być używane tylko przez plik wykonywalny utworzony za pomocą ASan.

Aby oczyścić bibliotekę współdzieloną, która jest używana w wielu plikach wykonywalnych, z których nie wszystkie są tworzone przy użyciu ASan, potrzebujesz 2 kopii biblioteki. Najlepszym sposobem na to jest dodanie do Android.mk dla danego modułu:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Spowoduje to umieszczenie biblioteki w folderze /system/lib/asan zamiast w folderze /system/lib. Następnie uruchom plik wykonywalny:

LD_LIBRARY_PATH=/system/lib/asan

W przypadku demonów systemowych dodaj poniższy kod do odpowiedniej sekcji /init.rc lub /init.$device$.rc.

setenv LD_LIBRARY_PATH /system/lib/asan

Sprawdź, czy proces korzysta z bibliotek z /system/lib/asan (jeśli jest dostępny), odczytując plik /proc/$PID/maps. Jeśli nie, być może musisz wyłączyć SELinux:

adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

Lepsze zrzuty stosu

ASan używa szybkiego odwijacza opartego na wskaźniku ramki, aby zapisywać informacje o ścieżce wywołań dla każdego zdarzenia przydzielenia i zwolnienia pamięci w programie. Większość Androida jest zbudowana bez wskaźników ramki. W rezultacie często otrzymujesz tylko 1 lub 2 znaczące klatki. Aby rozwiązać ten problem, utwórz ponownie bibliotekę za pomocą ASANA (zalecane!) lub za pomocą:

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

Możesz też ustawić parametr ASAN_OPTIONS=fast_unwind_on_malloc=0 w środowisku procesu. W zależności od obciążenia może ono mocno obciążać procesor.

Symbolizacja

Początkowo raporty ASan zawierają odniesienia do przesunięcia w plikach binarnych i bibliotekach udostępnionych. Informacje o pliku źródłowym i wierszu można uzyskać na 2 sposoby:

  • Upewnij się, że plik binarny llvm-symbolizer znajduje się w folderze /system/bin. llvm-symbolizer zostało utworzone na podstawie źródeł w: third_party/llvm/tools/llvm-symbolizer.
  • Przefiltruj raport za pomocą skryptu external/compiler-rt/lib/asan/scripts/symbolize.py.

Drugie podejście może dostarczyć więcej danych (czyli file:line lokalizacji) ze względu na dostępność bibliotek symboli na hoście.

ASan w aplikacjach

ASan nie może przeglądać kodu Java, ale może wykrywać błędy w bibliotekach JNI. W tym celu musisz skompilować plik wykonywalny za pomocą ASan, który w tym przypadku to /system/bin/app_process(32|64). Włącza to ASan we wszystkich aplikacjach na urządzeniu jednocześnie, co jest dużym obciążeniem, ale urządzenie z 2 GB pamięci RAM powinno sobie z tym poradzić.

Dodaj LOCAL_SANITIZE:=address do reguły kompilacji app_processframeworks/base/cmds/app_process. Na razie zignoruj obiekt app_process__asan w tym samym pliku (jeśli jest on nadal obecny w momencie, gdy czytasz ten artykuł).

Edytuj sekcję service zygote odpowiedniego pliku system/core/rootdir/init.zygote(32|64).rc, dodając następujące wiersze do bloku z wcięciem zawierającego class main, także o takie same wcięcia:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

Kompilacja, synchronizacja za pomocą adb, uruchamianie z pamięci flash za pomocą Fastboot i restart.

Używanie właściwości nawiasów

Metoda opisana w poprzedniej sekcji powoduje, że ASan jest dodawana do każdej aplikacji w systemie (a właściwie do każdego potomka procesu Zygote). Za pomocą ASan można uruchomić tylko jedną (lub kilka) aplikację, tracąc w ten sposób trochę pamięci na rzecz wolniejszego uruchamiania aplikacji.

Aby to zrobić, uruchom aplikację za pomocą właściwości wrap.. W tym przykładzie aplikacja Gmail jest uruchamiana w ASan:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

W tym kontekście usługa asanwrapper zastępuje usługę /system/bin/app_process usługą /system/bin/asan/app_process, która została utworzona za pomocą ASANA. Dodaje też /system/lib/asan na początku ścieżki wyszukiwania dynamicznej biblioteki. W ten sposób biblioteki z /system/lib/asan z instrumentacją ASan są preferowane przed zwykłymi bibliotekami w /system/lib podczas uruchamiania z asanwrapper.

Jeśli zostanie znaleziony błąd, aplikacja ulegnie awarii, a raport zostanie wydrukowany do dziennika.

SANITIZE_TARGET

Android 7.0 i nowsze wersje obsługują kompilowanie całej platformy Androida za pomocą ASANA. (jeśli tworzysz wersję nowszą niż Android 9, lepszym wyborem będzie HWASan).

Uruchom te polecenia w tym samym drzewie kompilacji.

make -j42
SANITIZE_TARGET=address make -j42

W tym trybie userdata.img zawiera dodatkowe biblioteki i musi zostać wgrany na urządzenie. Użyj tego wiersza poleceń:

fastboot flash userdata && fastboot flashall

Spowoduje to utworzenie 2 zestawów bibliotek wspólnych: normalnej w /system/lib (pierwsze wywołanie make) i z instrumentacją ASan w /data/asan/lib (drugie wywołanie make). Pliki wykonywalne z drugiej kompilacji zastąpią te z pierwszej. Pliki wykonywalne z instrumentacją ASan mają inną ścieżkę wyszukiwania biblioteki, która zawiera /data/asan/lib przed /system/lib dzięki użyciu /system/bin/linker_asanPT_INTERP.

System kompilacji zastępuje pośrednie katalogi obiektów, gdy zmieni się wartość $SANITIZE_TARGET. Wymusza to odtworzenie wszystkich obiektów, zachowując zainstalowane pliki binarne w folderze /system/lib.

Niektórych celów nie można utworzyć za pomocą ASan:

  • Statyczni pliki wykonywalne
  • LOCAL_CLANG:=false celów
  • LOCAL_SANITIZE:=false nie są dostępne w przypadku SANITIZE_TARGET=address

Pliki wykonywalne takie jak te są pomijane w kompilacji SANITIZE_TARGET, a wersja z pierwszego wywołania tworzenia pozostaje w /system/bin.

Biblioteki takie jak ta są tworzone bez ASan. Mogą zawierać kod ASan z bibliotek statycznych, od których zależą.

Dokumenty pomocnicze