Scudo to dynamiczny alokator pamięci w trybie użytkownika lub alokator sterty , zaprojektowany tak, aby był odporny na luki w zabezpieczeniach związane ze stertą (takie jak przepełnienie buforu na stercie, użycie po free i double free ) przy zachowaniu wydajności. Zapewnia standardowe operacje podstawowe alokacji i cofania alokacji języka C (takie jak malloc i free), a także elementy podstawowe C++ (takie jak new i delete).
Scudo jest bardziej środkiem łagodzącym niż pełnoprawnym wykrywaczem błędów pamięci, takim jak AddressSanitizer (ASan) .
Począwszy od wydania Androida 11, scudo jest używane dla całego kodu natywnego (z wyjątkiem urządzeń o małej ilości pamięci, gdzie nadal używany jest jemalloc). W czasie wykonywania wszystkie natywne alokacje sterty i cofnięcia alokacji są obsługiwane przez Scudo dla wszystkich plików wykonywalnych i ich zależności bibliotecznych, a proces jest przerywany, jeśli w stercie zostanie wykryte uszkodzenie lub podejrzane zachowanie.
W Androidzie 10 scudo musiało być włączone na zasadzie binarnej, ustawiając LOCAL_SANITIZE := scudo
w pliku .mk lub sanitize: { scudo: true, }
w pliku .bp.
Scudo jest oprogramowaniem typu open source i częścią projektu kompilatora-rt LLVM. Dokumentacja jest dostępna pod adresem https://llvm.org/docs/ScudoHardenedAllocator.html . Środowisko uruchomieniowe Scudo jest dostarczane jako część łańcucha narzędzi Androida, a wsparcie zostało dodane do Soong i Make , aby umożliwić łatwe włączanie alokatora w postaci binarnej.
Możesz włączyć lub wyłączyć dodatkowe środki łagodzące w alokatorze, korzystając z opcji opisanych poniżej.
Dostosowywanie
Niektóre parametry podzielnika można zdefiniować dla poszczególnych procesów na kilka sposobów:
- Statycznie: Zdefiniuj funkcję
__scudo_default_options
w programie, która zwraca ciąg opcji do przeanalizowania. Ta funkcja musi mieć następujący prototyp:extern "C" const char *__scudo_default_options()
. - Dynamicznie: użyj zmiennej środowiskowej
SCUDO_OPTIONS
zawierającej ciąg opcji do przeanalizowania. Opcje zdefiniowane w ten sposób zastępują wszelkie definicje wprowadzone przez__scudo_default_options
.
Dostępne są następujące opcje.
Opcja | Domyślna 64-bitowa | 32-bitowa domyślna | Opis |
---|---|---|---|
QuarantineSizeKb | 256 | 64 | Rozmiar (w KB) kwarantanny używany do opóźnienia faktycznego cofnięcia alokacji porcji. Niższa wartość może zmniejszyć użycie pamięci, ale zmniejszyć skuteczność łagodzenia; wartość ujemna wraca do wartości domyślnych. Ustawienie tego i ThreadLocalQuarantineSizeKb na zero całkowicie wyłącza kwarantannę. |
QuarantineChunksUpToSize | 2048 | 512 | Rozmiar (w bajtach), do którego porcje mogą zostać poddane kwarantannie. |
ThreadLocalQuarantineSizeKb | 64 | 16 | Rozmiar (w KB) pamięci podręcznej na wątek używanej do odciążenia globalnej kwarantanny. Niższa wartość może zmniejszyć użycie pamięci, ale może zwiększyć rywalizację o globalną kwarantannę. Ustawienie zarówno tego, jak i QuarantineSizeKb na zero, całkowicie wyłącza kwarantannę. |
DeallocationTypeMismatch | false | false | Włącza raportowanie błędów na malloc/usuń, nowy/wolny, nowy/usuń[] |
DeleteSizeMismatch | true | true | Włącza raportowanie błędów w przypadku niezgodności między rozmiarami nowych i usuniętych. |
ZeroContents | false | false | Włącza zerową zawartość porcji podczas alokacji i cofania alokacji. |
allocator_may_return_null | false | false | Określa, że alokator może zwrócić wartość null, gdy wystąpi błąd, który można naprawić, zamiast przerywać proces. |
hard_rss_limit_mb | 0 | 0 | Gdy RSS procesu osiągnie ten limit, proces zostaje zakończony. |
soft_rss_limit_mb | 0 | 0 | Gdy RSS procesu osiągnie ten limit, dalsze alokacje kończą się niepowodzeniem lub zwracają null (w zależności od wartości allocator_may_return_null ), dopóki RSS nie wróci w dół, aby umożliwić nowe alokacje. |
allocator_release_to_os_interval_ms | nie dotyczy | 5000 | Dotyczy tylko alokatora 64-bitowego. Jeśli jest ustawiona, próbuje zwolnić nieużywaną pamięć do systemu operacyjnego, ale nie częściej niż ten interwał (w milisekundach). Jeśli wartość jest ujemna, pamięć nie jest zwalniana do systemu operacyjnego. |
abort_on_error | true | true | Jeśli jest ustawiona, narzędzie wywołuje abort() zamiast _exit() po wydrukowaniu komunikatu o błędzie. |
Walidacja
Obecnie nie ma testów CTS specjalnie dla Scudo. Zamiast tego upewnij się, że testy CTS przechodzą z lub bez włączonej funkcji Scudo dla danego pliku binarnego, aby sprawdzić, czy nie ma to wpływu na urządzenie.
Rozwiązywanie problemów
W przypadku wykrycia problemu, którego nie można naprawić, alokator wyświetla komunikat o błędzie do standardowego deskryptora błędu, a następnie kończy proces. Ślady stosu, które prowadzą do zakończenia, są dodawane w dzienniku systemowym. Dane wyjściowe zwykle zaczynają się od Scudo ERROR:
po którym następuje krótkie podsumowanie problemu wraz ze wskazówkami.
Oto lista aktualnych komunikatów o błędach i ich potencjalnych przyczyn:
-
corrupted chunk header
: Weryfikacja sumy kontrolnej nagłówka porcji nie powiodła się. Jest to prawdopodobnie spowodowane jedną z dwóch rzeczy: nagłówek został nadpisany (częściowo lub całkowicie) lub wskaźnik przekazany do funkcji nie jest fragmentem. -
race on chunk header
: dwa różne wątki próbują manipulować tym samym nagłówkiem w tym samym czasie. Zwykle jest to objawem wyścigu lub ogólnego braku blokowania podczas wykonywania operacji na tym fragmencie. -
invalid chunk state
: porcja nie jest w stanie oczekiwanym dla danej operacji, na przykład nie jest przydzielona podczas próby jej zwolnienia lub nie jest poddawana kwarantannie podczas próby jej odtworzenia. Podwójna wolna jest typową przyczyną tego błędu. -
misaligned pointer
: mocno wymuszane są podstawowe wymagania dotyczące wyrównania: 8 bajtów na platformach 32-bitowych i 16 bajtów na platformach 64-bitowych. Jeśli wskaźnik przekazany do naszych funkcji nie pasuje do nich, wskaźnik przekazany do jednej z funkcji nie jest wyrównany. -
allocation type mismatch
: gdy ta opcja jest włączona, funkcja cofania alokacji wywoływana dla porcji musi być zgodna z typem funkcji, która została wywołana w celu jej alokacji. Ten rodzaj niezgodności może powodować problemy z bezpieczeństwem. -
invalid sized delete
: Gdy używany jest operator usuwania o rozmiarze C++14, a opcjonalna kontrola jest włączona, występuje niezgodność między rozmiarem, który został przekazany podczas cofania alokacji porcji, a rozmiarem żądanym podczas alokacji. Jest to zwykle problem z kompilatorem lub pomyłka typów w zwalnianym obiekcie. -
RSS limit exhausted
: Maksymalna określona opcjonalnie wartość RSS została przekroczona.
Jeśli debugujesz awarię samego systemu operacyjnego, możesz użyć kompilacji HWASan OS . Jeśli debugujesz awarię aplikacji, możesz również użyć kompilacji aplikacji HWASan .