UndefinedBehaviorSanitizer (UBSan) wykonuje instrumentację w czasie kompilacji, aby służą do wykrywania różnych rodzajów niezdefiniowanych zachowań. Chociaż UBSan może wykrywanie wiele niezdefiniowane błędy w zachowaniu, Android obsługuje:
- wyrównanie
- wartość logiczna
- granice
- typ wyliczeniowy
- float-cast-overflow,
- dzielenie przez zero
- dzielenie liczby całkowitej przez zero
- atrybut niepusty
- null
- powrót
- atrybut zwraca inny niż null
- Shift+base
- Shift+wykładnik
- signed-integer-overflow,
- nieosiągalny
- unsign-integer-overflow,
- związane z vla
unsign-integer-overflow, niezdefiniowane technicznie działania tej funkcji, są uwzględniane w narzędziu do dezynfekcji i wykorzystywane w wielu modułach Androida, łącznie z komponentami serwera mediów, aby wyeliminować wszelkie utajone przepełnienie całkowite Luki w zabezpieczeniach.
Implementacja
W systemie kompilacji Androida możesz włączyć UBSan globalnie lub lokalnie. Aby włączyć UBSan na całym świecie, ustaw SANITIZE_TARGET w Android.mk. Aby włączyć UBSan na na poziomie modułu, ustaw LOCAL_SANITIZE i zdefiniuj niezdefiniowane zachowanie, które które chcesz wyszukać w pliku Android.mk. Na przykład:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0 LOCAL_SRC_FILES:= sanitizer-status.c LOCAL_MODULE:= sanitizer-status LOCAL_SANITIZE := alignment bounds null unreachable integer LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer include $(BUILD_EXECUTABLE)
I odpowiednia konfiguracja planu (Android.bp):
cc_binary { cflags: [ "-std=c11", "-Wall", "-Werror", "-O0", ], srcs: ["sanitizer-status.c"], name: "sanitizer-status", sanitize: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], diag: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], }, }, }
Skróty UBSan
Android ma też 2 skróty: integer
oraz
default-ub
, aby włączyć zestaw środków dezynfekujących jednocześnie. Liczba całkowita
włącza integer-divide-by-zero
,
signed-integer-overflow
i unsigned-integer-overflow
.
default-ub
włącza testy z minimalną ilością kompilatora
problemy z wydajnością: bool, integer-divide-by-zero, return,
returns-nonnull-attribute, shift-exponent, unreachable and vla-bound
.
klasy sanitizera można używać z klasą sanitizerową SANITIZE_TARGET i LOCAL_SANITIZE,
, natomiast plik default-ub może być używany tylko z SANITIZE_TARGET.
Dokładniejsze raportowanie błędów
Domyślna implementacja UBSan Androida wywołuje określoną funkcję, gdy napotkano niezdefiniowane zachowanie. Domyślnie ta funkcja jest przerywana. Pamiętaj jednak: od października 2016 r. UBSan na Androidzie ma opcjonalną bibliotekę środowiska wykonawczego, udostępnia bardziej szczegółowe raporty o błędach, w tym typ niezdefiniowanego zachowania. pliku i wiersza kodu źródłowego. Aby włączyć ten błąd w raportach zawierających liczby całkowite dodają do pliku Android.mk te informacje:
LOCAL_SANITIZE:=integer LOCAL_SANITIZE_DIAG:=integer
Wartość LOCAL_SANITIZE włącza środek do dezynfekcji podczas kompilacji. LOCAL_SANITIZE_DIAG włącza tryb diagnostyczny dla określonego środka do dezynfekcji. Jest można ustawić różne wartości dla LOCAL_SANITIZE i LOCAL_SANITIZE_DIAG, ale włączone są tylko kontrole w lokalizacji LOCAL_SANITIZE. Jeśli kontrola nie została określona w LOCAL_SANITIZE, ale zostało określone w LOCAL_SANITIZE_DIAG, sprawdzanie nie jest włączone i komunikaty diagnostyczne.
Oto przykład informacji dostarczanych przez bibliotekę środowiska wykonawczego UBSan:
pixel-xl:/ # sanitizer-status ubsan sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Sanityzacja nadmiarowej liczby całkowitej
Niezamierzone przekroczenie liczby całkowitej może spowodować uszkodzenie pamięci lub dostęp do informacji w zabezpieczeniach związanych z ujawnianiem informacji w zmiennych związanych z dostępem do pamięci lub alokacje pamięci. Aby temu zapobiec, dodaliśmy UndefinedBehaviorSanitizer (UBSan) – środki sanitizerujące nadmiarowe liczby całkowite z podpisem i bez znaku (UBSan) wzmocnij platformy multimedialnej w Androidzie 7.0. W Androidzie 9 rozwinięto UBSan, aby uwzględnić więcej komponentów i ulepszyć obsługę tego systemu.
Ma to na celu dodanie mechanizmów kontroli dotyczących arytmetyki operacje / instrukcje, overflow – aby bezpiecznie przerwać proces w przypadku jego nadmiaru. Te środki dezynfekcji mogą zniwelować całą klasę uszkodzenia pamięci i luk w zabezpieczeniach związanych z ujawnianiem informacji, których główną przyczyną jest liczba całkowita takich jak pierwotna luka w zabezpieczeniach Stagefright.
Przykłady i źródło
Integer Overflow Sanitization (IntSan) dostarcza kompilator i dodaje
instrumentacja do pliku binarnego podczas kompilowania w celu wykrywania funkcji arytmetycznych;
nie mieści się w nich. Jest on domyślnie włączony w różnych komponentach
platformy,
/platform/external/libnl/Android.bp
Implementacja
IntSan korzysta z dostępnych w UBSan rozwiązań do sanityzacji nadmiarowych liczb całkowitych z podpisem i bez znaku. Ten ograniczanie ryzyka jest włączone dla poszczególnych modułów. Pomaga utrzymać kluczowe komponenty i nie należy go wyłączać.
Zdecydowanie zachęcamy do włączenia sanitu w ramach nadmiarowej liczby całkowitej, aby zapewnić dodatkowe Idealnymi kandydatami są uprzywilejowany kod natywny lub kod natywny, analizuje niezaufane dane wejściowe użytkownika. Wiąże się to z niewielkim narzutem wydajności, za pomocą środka do dezynfekcji, który zależy od użycia kodu arytmetyczne. Oczekuj niewielki procent narzutu i sprawdź, czy na skuteczność reklam.
Obsługa IntSan w makefiles
Aby włączyć IntSan w pliku Makefile, dodaj:
LOCAL_SANITIZE := integer_overflow # Optional features LOCAL_SANITIZE_DIAG := integer_overflow LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZE
tworzy listę środków do dezynfekcji rozdzielonych przecinkami, ainteger_overflow
to gotowy zestaw opcji dla z podpisem lub bez podpisu, domyślna LISTA ZABLOKOWANYCH.LOCAL_SANITIZE_DIAG
włącza tryb diagnostyczny urządzenia środki dezynfekcyjne. Używaj trybu diagnostycznego tylko podczas testowania, ponieważ przerywać ładowanie przy przepełnieniach, negując korzystny wpływ na bezpieczeństwo środków zaradczych. Zobacz Rozwiązywanie problemów aby dowiedzieć się więcej.- Funkcja
LOCAL_SANITIZE_BLOCKLIST
umożliwia określenie LISTY BLOKADÓW w celu zapobieżenia oczyszczaniu funkcji i plików źródłowych. Zobacz Rozwiązywanie problemów w celu uzyskania dodatkowych .
Jeśli chcesz mieć dokładniejszą kontrolę, włączaj środki dezynfekcyjne pojedynczo lub obie te flagi:
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Obsługuj IntSan w plikach planów
Aby włączyć oczyszczanie nadmiarowej liczby całkowitej w pliku planu, taki jak
/platform/external/libnl/Android.bp
dodaj:
sanitize: { integer_overflow: true, diag: { integer_overflow: true, }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Podobnie jak w przypadku tworzenia plików, właściwość integer_overflow
jest wstępnie rozpakowana
zestaw opcji dla pojedynczego nadmiaru liczb całkowitych ze znakiem i bez znaku
środki dezynfekcyjne z wartością domyślną
LISTA ZABLOKOWANYCH.
Zbiór właściwości diag
włącza tryb diagnostyczny usługi
środki dezynfekcyjne. Używaj trybu diagnostycznego tylko podczas testowania. Tryb diagnostyczny nie
przerywać działania w przypadku jego nadmiaru, co neguje korzyści zapewniane przez
i ograniczania ryzyka
w kompilacjach użytkowników. Więcej informacji znajdziesz w artykule Rozwiązywanie problemów.
Właściwość BLOCKLIST
umożliwia określenie pliku BLOCKLIST
który pozwala programistom uniemożliwić
oczyszczony. Zobacz Rozwiązywanie problemów z:
dodatkowe informacje.
Aby pojedynczo włączyć środki dezynfekcyjne, użyj:
sanitize: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"], diag: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow",], }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Rozwiązywanie problemów
Jeśli w nowych komponentach włączysz oczyszczanie polegające na przepełnieniu liczby całkowitej w nowych komponentach lub biblioteki platformy, które zostały oczyszczone z przekroczenia liczby całkowitej, możesz napotkać kilka problemów z łagodnymi przepełnieniem liczb całkowitych, które powodują przerwy. Przetestuj komponentów z włączoną dezynfekcją, by umożliwić wykrycie niegroźnych przebarwień.
Aby znaleźć informacje o przerwach spowodowanych dezynfekcją w kompilacjach użytkowników, wyszukaj
SIGABRT
awarii i komunikatów o przerwie, które wskazują na przekroczenie limitu
przez UBSan, na przykład:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/surfaceflinger <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: sub-overflow'
Zrzut stosu powinien jednak zawierać funkcję powodującą przerwanie, przepełnienia występujące w funkcjach wbudowanych mogą nie być widoczne w zrzucie stosu.
Aby ułatwić sobie określenie głównej przyczyny, włącz diagnostykę w bibliotece aktywuje przerwanie i spróbuje odtworzyć błąd. Z czy diagnostyka jest włączona, proces nie zostanie przerwany i zamiast tego aby kontynuować. Brak przerw pomaga zmaksymalizować liczbę łagodnych przepełnień w konkretnej ścieżce wykonania bez konieczności jej ponownej kompilacji po naprawieniu każdego błędu. Narzędzie Diagnostyka generuje komunikat o błędzie zawierający numer wiersza i źródło plik powodujący przerwanie:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Po znalezieniu problematycznej operacji arytmetycznej upewnij się, że nadmiar jest nieszkodliwy i zamierzony (np. nie ma wpływu na bezpieczeństwo). Możesz kierować się Przerwanie działania narzędzia sanitizer:
- Refaktoryzacja kodu w celu uniknięcia przepełnienia (przykład)
- Wyraźne przekroczenie za pomocą funkcji __builtin_*_overflow w Clang funkcje (przykład)
- Wyłączenie oczyszczania w funkcji przez określenie atrybutu
no_sanitize
(przykład) - Wyłączenie oczyszczania funkcji lub pliku źródłowego za pomocą pliku BLOCKLIST (przykład)
Należy zastosować rozwiązanie o największym stopniu szczegółowości. Na przykład duży plik funkcja z wieloma operacjami arytmetycznymi i pojedynczą operacją przekraczającą powinna refaktoryzować pojedynczą operację, a nie całą funkcję Zablokowane.
Do częstych przyczyn, które mogą powodować łagodne przelanie, są m.in.:
- Pośredni rzutowanie – w przypadku, gdy przed rzutowaniem na typ podpisany występuje niepodpisane przepełnienie (przykład).
- Usunięcia z połączonej listy, które zmniejszą indeks pętli w przypadku usunięcia (przykład)
- przypisywanie niepodpisanego typu do wartości -1 zamiast określania rzeczywistej wartości maksymalnej (przykład).
- Pętle, które zmniejszą liczbę całkowitą bez znaku w warunku (przykład, przykład)
Programiści powinni upewnić się, że w przypadku wykrycia przez środki dezynfekcyjne przepełnienie, że jest w rzeczywistości niegroźne, bez niezamierzonych skutków ubocznych i bezpieczeństwa konsekwencje przed wyłączeniem dezynfekcji.
Wyłącz IntSan
IntSan można wyłączyć za pomocą funkcji BLOCKLIST lub atrybutów funkcji. Wyłącz z umiarem i tylko wtedy, gdy refaktoryzacja kodu jest bezzasadna lub i zwiększyć wydajność.
Więcej informacji o wyłączaniu IntSan znajdziesz w nadrzędnej dokumentacji Clang. z funkcją atrybutów i BLOCKLIST Formatowanie. Lista BLOCKLIST powinna być ograniczona do konkretnego środka dezynfekcyjnego, używając nazw sekcji z określeniem docelowego środka dezynfekcyjnego, aby nie wpłynąć na inne środki dezynfekcyjne.
Weryfikacja
Obecnie nie ma żadnego testu CTS przeznaczonego specjalnie do sanityzacji przez przepełnienie całkowite. Zamiast tego sprawdź, czy testy CTS zakończą się powodzeniem z włączoną lub wyłączoną usługą IntSan, aby zweryfikować że nie ma to wpływu na urządzenie.
Oczyszczanie granic
BoundsSanitizer (BoundSan) dodaje instrumentację do plików binarnych w celu wstawiania granic sprawdza dostęp do tablicy. Te kontrole są dodawane, jeśli kompilator nie może podczas kompilowania udowodnić, że dostęp będzie bezpieczny, a rozmiar tablicy będzie znana w czasie działania, aby można było ją sprawdzić. Android 10 wdraża BoundSan Bluetooth i kodeki. Rozwiązanie BoundSan jest dostarczane przez kompilator i włączone przez w różnych komponentach platformy.
Implementacja
BoundSan wykorzystuje kod UBSan sanitizer. To rozwiązanie jest włączone na poziomie modułu. To pomaga Dbaj o bezpieczeństwo kluczowych komponentów Androida i nie należy ich wyłączać.
Zdecydowanie zalecamy włączenie BoundSan w przypadku dodatkowych komponentów. Idealnymi kandydatami są kod natywny z podwyższonymi uprawnieniami lub złożony kod natywny, który analizuje niezaufanych danych wejściowych użytkownika. Narzut związany z wydajnością związany z włączeniem BoundSan zależy od liczby dostępów do tablicy, których nie można potwierdzić bezpiecznie. Spodziewaj się średni procent narzutu jest niewielki i sprawdź, czy wydajność jest ważna.
Włącz BoundSan w plikach planów
Funkcję BoundSan można włączyć w plikach planów przez dodanie parametru "bounds"
z właściwością „sanitize misc_undefined
” dla plików binarnych i bibliotek
moduły:
sanitize: { misc_undefined: ["bounds"], diag: { misc_undefined: ["bounds"], }, BLOCKLIST: "modulename_BLOCKLIST.txt",
diagnostyka
Właściwość diag
włącza tryb diagnostyczny środków do dezynfekcji.
Używaj trybu diagnostycznego tylko podczas testowania. Tryb diagnostyczny nie przerywa działania
przepełnienia, które negują korzyści w zakresie bezpieczeństwa wynikające z zastosowania środków ograniczających ryzyko i niosą ze sobą
ma większą wydajność, dlatego nie jest zalecana w przypadku kompilacji produkcyjnych.
LISTA ZABLOKOWANYCH
Właściwość BLOCKLIST
umożliwia określenie listy BLOCKLIST
który umożliwia programistom blokowanie funkcji i plików źródłowych
oczyszczony. Używaj tej właściwości tylko w przypadku problemów ze skutecznością,
pliki i funkcje. Ręczne sprawdzanie tych plików i funkcji
, aby zapewnić, że dostęp do tablicy jest bezpieczny. Dodatkowe informacje znajdziesz w sekcji Rozwiązywanie problemów.
.
Włącz BoundSan w makefiles
Funkcję BoundSan można włączyć w plikach tworzenia plików przez dodanie parametru "bounds"
do zmiennej LOCAL_SANITIZE
w przypadku modułów binarnych i bibliotecznych:
LOCAL_SANITIZE := bounds # Optional features LOCAL_SANITIZE_DIAG := bounds LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZE
akceptuje listę środków dezynfekcyjnych oddzielonych znakiem
przecinek.
LOCAL_SANITIZE_DIAG
włącza tryb diagnostyczny. Użyj diagnostyki
tylko w trybie testowym. Tryb diagnostyczny nie przerywa działania w przypadku przepełnienia,
neguje korzyści w zakresie bezpieczeństwa wynikające z zastosowania środków ograniczających ryzyko i niesie ze sobą większe
ale nie jest zalecana w przypadku kompilacji produkcyjnych.
LOCAL_SANITIZE_BLOCKLIST
pozwala na określenie BLOCKLIST
który pozwala programistom uniemożliwić
oczyszczony. Używaj tej właściwości tylko w przypadku problemów ze skutecznością,
pliki i funkcje. Ręczne sprawdzanie tych plików i funkcji
, aby zapewnić, że dostęp do tablicy jest bezpieczny. Dodatkowe informacje znajdziesz w sekcji Rozwiązywanie problemów.
.
Wyłącz BoundSan
Możesz wyłączyć funkcję BoundSan w funkcjach i plikach źródłowych za pomocą funkcji BLOCKLIST lub atrybutów funkcji. Komponent BoundSan najlepiej pozostawić włączony, więc wyłączaj go tylko wtedy, funkcja lub plik powoduje duże obciążenie wydajności, źródło zostało ręcznie sprawdzone.
Więcej informacji o wyłączaniu BoundSan za pomocą funkcji atrybutów i BLOCKLIST formatowania, zapoznaj się z dokumentacją Clang LLVM. Określ zakres BLOCKLIST do określonego środka do dezynfekcji przy użyciu nazw sekcji określających wartość nie oddziałuje na inne środki dezynfekcyjne.
Weryfikacja
Nie ma żadnego testu CTS dotyczącego konkretnie BoundSan. Upewnij się, że CTS testy zaliczone z włączoną lub wyłączoną funkcją BoundSan pozwalają sprawdzić, czy nie ma to wpływu urządzenia.
Rozwiązywanie problemów
Po włączeniu BoundSan dokładnie przetestuj komponenty, aby mieć pewność, adresowane są niewykryte przypadki dostępu poza granicami organizacji.
Błędy BoundSan można łatwo zidentyfikować, ponieważ obejmują: wiadomość o przerwaniu tombstone:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/foobar <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: out-of-bounds'
W trybie diagnostycznym plik źródłowy, numer wiersza i indeks
są drukowane na logcat
. Domyślnie ten tryb nie
generuje komunikat o przerwie. Sprawdź logcat
, aby sprawdzić, czy są jakieś
.
external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'