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 binarnyllvm-symbolizer
. Projektllvm-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
celLOCAL_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ą.