Program do sprzątania adresów

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

ASan wykrywa:

  • Przepełnienie/niedopełnienie bufora stosu i sterty
  • Wykorzystanie sterty po bezpłatnym
  • Użycie stosu poza zakresem
  • Podwójny wolny/szlachetny

ASan działa w architekturze 32- i 64-bitowej ARM oraz architekturze x86 i x86-64. Obciążenie procesora przez ASan jest około 2-krotnie wyższy, narzut kodu wynosi od 50% do 2-krotnie, a dodatkowo wymaga dużej ilości pamięci. (w zależności od wzorców przydziału, ale w kolejności 2x).

Android 10 i główna gałąź AOSP w AArch64 obsługuje sprzętowy serwer AddressSanitizer (HWASan). podobnego narzędzia z mniejszym nadmiarem pamięci RAM i większym wykrywanych błędów. Oprócz błędów HWASan wykrywa również użycie stosu po powrocie wykryte przez ASan.

HWASan ma podobny narzut na procesor i rozmiar kodu, ale znacznie mniejszy nadmiar pamięci RAM (15%). HWASan nie jest deterministyczny. Istnieje tylko 256 możliwych wartości tagu, więc zostaje określona stała wartość 0,4%. prawdopodobieństwo pominięcia któregokolwiek błędu. HWASan nie ma czerwonych stref ASan o ograniczonym rozmiarze dla wykrywanie przepełnień i kwarantanna o ograniczonej pojemności w celu wykrywania przypadków użycia po wyczerpaniu; więc nie ma znaczenia dla HWASan, jak duże jest to obciążenie ani jak dawno temu został przeniesiony. Dzięki temu HWASan jest lepszy niż ASan. Więcej informacji na ten temat znajdziesz projekt HWASan lub informacje o korzystaniu z HWASan na Androidzie.

ASan wykrywa nadmiarowe treści stosu/globalne oprócz przepełnienia stosu, działa szybko i przy minimalnym nadmiarze pamięci.

W tym dokumencie opisujemy, jak stworzyć i uruchomić części/całość Androida ASan. Jeśli tworzysz aplikację SDK/NDK za pomocą ASan, zapoznaj się z artykułem Sanitizer adresu .

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

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

Po wykryciu błędu ASan wydrukuje szczegółowy raport na potrzeby standardu na dane wyjściowe i do logcat, a następnie powoduje awarię tego procesu.

Napraw biblioteki udostępnione za pomocą ASan

Ze względu na sposób działania ASan z biblioteki utworzonej przy użyciu tego języka może korzystać tylko który został utworzony w ASan.

Aby oczyścić bibliotekę współdzieloną, która jest używana w wielu plikach wykonywalnych, nie wszystkie które powstają w ASan, potrzebują 2 kopii biblioteki. Zalecany sposób to dodanie do Android.mk w odpowiednim module:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Spowoduje to przeniesienie biblioteki do języka /system/lib/asan, a nie /system/lib Następnie uruchom plik wykonywalny za pomocą polecenia:

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 używa bibliotek z /system/lib/asan gdy jest dostępny, odczytując treść /proc/$PID/maps. Jeśli nie, być może trzeba będzie aby 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 rejestruje stos za pomocą szybkiego elementu odwijającego opartego na wskaźnikach klatek śledzenie dla każdego zdarzenia alokacji pamięci i przydziału lokalizacji w programie. Większość aplikacji na Androida bez wskaźników klatek. W rezultacie często otrzymujesz tylko jedną lub dwie znaczące klatki. Aby rozwiązać ten problem, odbuduj bibliotekę przy użyciu ASan (zalecane) lub:

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

Lub ustaw ASAN_OPTIONS=fast_unwind_on_malloc=0 w procesie dla środowiska. Ten drugi tryb może znacznie obciążać procesor. i zwiększania obciążenia.

Symbole

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

  • Sprawdź, czy w pliku /system/bin znajduje się plik binarny llvm-symbolizer. Projekt llvm-symbolizer został utworzony na podstawie źródeł: third_party/llvm/tools/llvm-symbolizer
  • Przefiltruj raport według tych danych: external/compiler-rt/lib/asan/scripts/symbolize.py skrypt.

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

ASan w aplikacjach

ASan nie widzi kodu Java, ale może wykryć błędy w JNI biblioteki. Do tego musisz utworzyć plik wykonywalny przy użyciu ASan, który ten przypadek: /system/bin/app_process(32|64). Ten włącza ASan we wszystkich aplikacjach na urządzeniu jednocześnie, co jest duże obciążenie, ale urządzenie z 2 GB pamięci RAM powinno to dać.

Dodaj LOCAL_SANITIZE:=address do regułę kompilacji app_process w frameworks/base/cmds/app_process. Zignoruj obecnie miejsce docelowe app_process__asan w tym samym pliku (jeśli to w momencie przeczytania tego dokumentu).

Edytuj sekcję service zygote odpowiedni plik system/core/rootdir/init.zygote(32|64).rc, by dodać kolejnych wierszy do bloku z wcięciem zawierającego class main, a także z wcięciem o taką samą kwotę:

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

Kompilacja, synchronizacja adb, uruchamianie Flasha typu fastboot i ponowne uruchamianie.

Używanie właściwości „wrap”

Podejście z poprzedniej sekcji uwzględnia ASan w każdym aplikacji w systemie (a dokładnie do każdego elementu potomnego Zygote), ). Z ASan można uruchomić tylko jedną (lub kilka) aplikacji, i wymienić ją w pamięci, aby wolniej uruchamiać aplikacje.

Aby to zrobić, uruchom aplikację za pomocą właściwości wrap.. Poniższy przykład uruchamia aplikację Gmail pod ASan:

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

W tym kontekście asanwrapper zmienia treść /system/bin/app_process do usługi /system/bin/asan/app_process, która korzysta z ASan. Dodaje też /system/lib/asan na początku ścieżki wyszukiwania biblioteki dynamicznej. W ten sposób model ASan biblioteki z /system/lib/asan są preferowane do zwykłych bibliotek w /system/lib przy uruchomieniu z asanwrapper.

W przypadku znalezienia błędu aplikacja ulega awarii, a raport jest drukowany dziennika.

SANITIZE_TARGET

Android 7.0 i nowsze wersje obejmują obsługę tworzenia całej platformy Androida ASan. (Jeśli tworzysz wersję w wersji nowszej niż Androida 9, lepszym rozwiązaniem będzie HWASan).

Uruchom podane niżej polecenia w tym samym drzewie kompilacji.

make -j42
SANITIZE_TARGET=address make -j42

W tym trybie userdata.img zawiera dodatkowe biblioteki i musi być która również została pokazana na urządzeniu. Użyj tego wiersza poleceń:

fastboot flash userdata && fastboot flashall

Spowoduje to utworzenie 2 zestawów bibliotek udostępnionych: normalny w /system/lib (pierwsze wywołanie) i obsługiwane przez ASan /data/asan/lib (drugie wywołanie). Pliki wykonywalne z nadpisze te z pierwszej. Z systemem ASan pliki wykonywalne otrzymują inną ścieżkę wyszukiwania biblioteki zawierającą /data/asan/lib przed /system/lib za pomocą /system/bin/linker_asan w: PT_INTERP.

System kompilacji blokuje pośrednie katalogi obiektów, gdy Wartość $SANITIZE_TARGET uległa zmianie. Zmusza to do odbudowy docelowe przy jednoczesnym zachowaniu zainstalowanych plików binarnych na poziomie /system/lib.

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

  • Statycznie połączone pliki wykonywalne
  • LOCAL_CLANG:=false cel
  • LOCAL_SANITIZE:=false nie jest sygnalizowany przez: SANITIZE_TARGET=address

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

Tego typu biblioteki tworzy się bez ASan. Mogą zawierać niektóre elementy ASan. z bibliotek statycznych, na których bazują.

Dokumenty pomocnicze