Zrozumienie raportów HWASan

Gdy narzędzie HWASan wykryje błąd pamięci, proces zostaje zakończony funkcją abort(), a raport jest drukowany na stderr i logcat. Podobnie jak wszystkie natywne awarie na Androidzie, błędy HWASan można znaleźć w /data/tombstones .

W porównaniu do zwykłych awarii natywnych, HWASan przenosi dodatkowe informacje w polu „Komunikat o przerwaniu” w górnej części nagrobka. Zobacz przykładową awarię opartą na stercie poniżej (w przypadku błędów stosu zobacz poniższą notatkę dotyczącą sekcji dotyczących stosu).

Przykładowy raport

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys'
Revision: 'DVT1.0'
ABI: 'arm64'
Timestamp: 2019-04-24 01:13:22+0000
pid: 11154, tid: 11154, name: sensors@1.0-ser  >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<<
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … regular crash dump follows …]

Jest to bardzo podobne do raportu AddressSanitizer . W przeciwieństwie do nich, prawie wszystkie błędy HWASan to „niezgodność znaczników”, tj. dostęp do pamięci, w którym znacznik wskaźnika nie pasuje do odpowiedniego znacznika pamięci. To może być jeden z

  • dostęp poza granicami na stosie lub stercie
  • użyj po zwolnieniu na stercie
  • użyj po powrocie na stos

Sekcje

Poniżej znajduje się wyjaśnienie każdej sekcji raportu HWASan:

Błąd dostępu

Zawiera informacje o złym dostępie do pamięci, w tym:

  • Typ dostępu („ODCZYT” vs. „ZAPIS”)
  • Rozmiar dostępu (ile bajtów próbowano uzyskać)
  • Numer wątku dostępu
  • Wskaźniki i znaczniki pamięci (do zaawansowanego debugowania)

Uzyskaj dostęp do śledzenia stosu

Ślad stosu złego dostępu do pamięci. Zobacz sekcję Symbolizacja , aby symbolizować.

Przyczyna

Potencjalna przyczyna złego dostępu. Jeśli jest wielu kandydatów, są oni wymienieni w kolejności malejącego prawdopodobieństwa. Poprzedza szczegółowe informacje o potencjalnej przyczynie. HWASan może zdiagnozować następujące przyczyny:

  • używać po-bezpłatnie
  • niedopasowanie tagów stosu: może to być użycie stosu po zwrocie/użycie po zakresie lub poza zakresem
  • przepełnienie bufora sterty
  • przepełnienie globalne

Informacje o pamięci

Opisuje, co HWASan wie o pamięci, do której uzyskuje się dostęp, i może się różnić w zależności od typu błędu.

Typ błędu Przyczyna Format raportu
niedopasowanie tagów używać po-bezpłatnie
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
przepełnienie bufora sterty Należy pamiętać, że może to być również niedomiar.
<address> is located N bytes to the right of M-byte region [<start>, <end>)
  allocated here:
niedopasowanie tagów stosu Raporty stosu nie rozróżniają błędów przepełnienia/niedopełnienia i błędów użycia po zwróceniu. Ponadto, aby znaleźć alokację stosu, która jest źródłem błędu, wymagany jest etap symbolizacji offline. Zobacz sekcję Opis raportów stosu poniżej.
wolny od inwalidztwa używać po-bezpłatnie Jest to podwójnie darmowy błąd. Jeśli stanie się to po zamknięciu procesu, może to oznaczać naruszenie ODR .
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
nie mogę opisać adresu Albo dzikie zwolnienie (wolne od pamięci, która nie została wcześniej przydzielona), albo podwójne zwolnienie po usunięciu przydzielonej pamięci z wolnego bufora HWASan.
0x… to pamięć cieniowa HWAsan. Jest to zdecydowanie wolne rozwiązanie, ponieważ aplikacja próbowała zwolnić pamięć wewnętrzną HWASan.

Śledzenie stosu delokalizacji

Ślad stosu wskazujący, gdzie pamięć została zwolniona. Obecne tylko w przypadku błędów, które nie są używane po użyciu lub są wolne od nieprawidłowych. Zobacz sekcję Symbolizacja , aby symbolizować.

Śledzenie stosu alokacji

Ślad stosu wskazujący, gdzie przydzielono pamięć. Zobacz sekcję Symbolizacja , aby symbolizować.

Zaawansowane informacje o debugowaniu

Raport HWASan zawiera również pewne zaawansowane informacje dotyczące debugowania, w tym (w kolejności):

  1. Lista wątków w procesie
  2. Lista wątków w procesie
  3. Wartość znaczników pamięci w pobliżu pamięci powodującej błędy
  4. Zrzut rejestrów w punkcie dostępu do pamięci

Zrzut znacznika pamięci

Zrzutu pamięci znacznika można użyć do wyszukania pobliskich alokacji pamięci z tym samym znacznikiem, co znacznik wskaźnika. Mogą one wskazywać na dostęp poza granicami z dużym przesunięciem. Jeden znacznik odpowiada 16 bajtom pamięci; znacznik wskaźnika to 8 górnych bitów adresu. Zrzut pamięci znacznika może dać wskazówki, na przykład przepełnienie bufora po prawej stronie:

tags: ad/5c (ptr/mem)
[...]
Memory tags around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: 0e  0e  0e  57  20  20  20  20  20  2e  5e  5e  5e  5e  5e  b5
=>0x006f33ae2000: f6  f6  f6  f6  f6  4c  ad  ad  ad  ad  ad  ad [5c] 5c  5c  5c
  0x006f33ae2010: 5c  04  2e  2e  2e  2e  2e  2f  66  66  66  66  66  80  6a  6a
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: ab  52  eb  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
=>0x006f33ae2000: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. [..] ..  ..  ..
  0x006f33ae2010: ..  5c  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
(zwróć uwagę na ciąg 6 × 16 = 96 bajtów znaczników „ad” po lewej stronie, które odpowiadają znacznikowi wskaźnika).

Jeśli rozmiar alokacji nie jest wielokrotnością 16, pozostała część rozmiaru będzie przechowywana jako znacznik pamięci , a znacznik będzie przechowywany jako krótki znacznik granulatu . W powyższym przykładzie tuż po pogrubionej alokacji oznaczonej reklamą mamy alokację tagu 5c o wielkości 5 × 16 + 4 = 84 bajtów.

Znacznik pamięci zerowej (np. tags: ad/ 00 (ptr/mem) ) zwykle wskazuje na błąd związany z użyciem stosu po zwróceniu.

Zarejestruj zrzut

Zrzut rejestru w raportach HWASan odpowiada faktycznej instrukcji, która wykonała nieprawidłowy dostęp do pamięci. Po nim następuje kolejny zrzut rejestru ze zwykłej procedury obsługi sygnału Androida - zignoruj ​​​​drugi , jest on wykonywany, gdy HWASan wywołuje abort() i nie ma związku z błędem.

Symbolizowanie

Aby uzyskać nazwy funkcji i numery linii w śladach stosu (oraz uzyskać nazwy zmiennych w przypadku błędów związanych z użyciem po zakresie), potrzebny jest etap symbolizacji offline.

Pierwsza konfiguracja: zainstaluj llvm-symbolizer

Aby symbolizować, twój system musi mieć zainstalowany llvm-symbolizer i dostępny z $PATH. W Debianie możesz go zainstalować za pomocą sudo apt install llvm .

Uzyskaj pliki symboli

Do symbolizacji potrzebujemy nieokrojonych plików binarnych zawierających symbole. Miejsce ich znalezienia zależy od typu kompilacji:

W przypadku kompilacji lokalnych pliki symboli można znaleźć w out/target/product/<product>/symbols/ .

W przypadku kompilacji AOSP (np. flashowanych z Flashstation ) kompilacje można znaleźć w systemie Android CI . W „Artefaktach” kompilacji będzie znajdować się plik `${PRODUCT}-symbols-${BUILDID}.zip`.

W przypadku wewnętrznych kompilacji Twojej organizacji sprawdź dokumentację swojej organizacji, aby uzyskać pomoc w uzyskaniu plików symboli.

Symbolizować

hwasan_symbolize –-symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash

Zrozumienie raportów stosu

W przypadku błędów występujących w zmiennych stosu raport HWASan będzie zawierał takie szczegóły:

Cause: stack tag-mismatch
Address 0x007d4d251e80 is located in stack of thread T64
Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000)
Previously allocated frames:
  record_addr:0x7df7300c98 record:0x51ef007df3f70fb0  (/apex/com.android.art/lib64/libart.so+0x570fb0)
  record_addr:0x7df7300c90 record:0x5200007df3cdab74  (/apex/com.android.art/lib64/libart.so+0x2dab74)
  [...]
	

Aby umożliwić zrozumienie błędów stosu, HWASan śledzi ramki stosu, które miały miejsce w przeszłości. Obecnie HWASan nie przekształca tego w zrozumiałą dla człowieka treść w raporcie o błędzie i wymaga dodatkowego etapu symbolizacji .

Naruszenia ODR

Niektóre błędy wynikające z użycia po zwolnieniu zgłoszone przez HWASan mogą również wskazywać na naruszenie reguły jednej definicji (ODR). Naruszenie ODR ma miejsce, gdy ta sama zmienna jest zdefiniowana wielokrotnie w tym samym programie. Oznacza to również, że zmienna jest niszczona wielokrotnie, co może prowadzić do błędu użycia po zwolnieniu.

Po symbolizacji naruszenia ODR pokazują użycie po zwolnieniu z __cxa_finalize , zarówno na stosie nieprawidłowego dostępu, jak i na stosie „zwolniono tutaj”. Stos „wcześniej przydzielony tutaj” zawiera __dl__ZN6soinfo17call_constructorsEv i powinien wskazywać lokalizację w programie, która definiuje zmienną znajdującą się wyżej na stosie.

Jednym z powodów naruszenia ODR jest użycie bibliotek statycznych. Jeśli biblioteka statyczna definiująca globalę C++ jest połączona z wieloma bibliotekami współdzielonymi lub plikami wykonywalnymi, wiele definicji tego samego symbolu może ostatecznie istnieć w tej samej przestrzeni adresowej, co spowoduje błąd ODR.

Rozwiązywanie problemów

„HWAddressSanitizer nie może opisać adresu bardziej szczegółowo.”

Czasami w HWASan może zabraknąć miejsca na informacje o przeszłych alokacjach pamięci. W takim przypadku raport będzie zawierał tylko jeden ślad stosu umożliwiający natychmiastowy dostęp do pamięci, po którym będzie następująca uwaga:

  HWAddressSanitizer can not describe address in more detail.

W niektórych przypadkach można to rozwiązać, uruchamiając test kilka razy. Inną opcją jest zwiększenie rozmiaru historii HWASan. Można to zrobić globalnie w build/soong/cc/sanitize.go (poszukaj hwasanGlobalOptions ) lub w środowisku procesowym (spróbuj adb shell echo $HWASAN_OPTIONS aby zobaczyć bieżące ustawienia).

Może się to również zdarzyć, jeśli pamięć, do której uzyskano dostęp, nie jest mapowana lub alokowana przez alokator nie obsługujący HWASan. W tym przypadku znacznik mem wymieniony w nagłówku awarii będzie zazwyczaj miał 00 . Jeśli masz dostęp do całego nagrobka, pomocne może być sprawdzenie zrzutu map pamięci, aby dowiedzieć się, do jakiego mapowania (jeśli w ogóle) należy dany adres.

„zagnieżdżony błąd w tym samym wątku”

Oznacza to, że wystąpił błąd podczas generowania raportu o awarii HWASan. Zwykle jest to spowodowane błędem w środowisku wykonawczym HWASan. Zgłoś błąd i, jeśli to możliwe, podaj instrukcje, jak odtworzyć problem.