Niezdefiniowane zachowanie sanitizera

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, a integer_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]'