Oczyszczanie przepełnienia liczb całkowitych

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Niezamierzone przepełnienia liczb całkowitych mogą powodować uszkodzenie pamięci lub luki w zabezpieczeniach umożliwiające ujawnienie informacji w zmiennych skojarzonych z dostępem do pamięci lub alokacją pamięci. Aby temu zaradzić, dodaliśmy sanitizery UndefinedBehaviorSanitizer (UBSan) firmy Clang z podpisanymi i niepodpisanymi liczbami całkowitymi, aby wzmocnić strukturę mediów w systemie Android 7.0. W systemie Android 9 rozszerzyliśmy UBSan, aby obejmował więcej komponentów i poprawiliśmy obsługę systemu kompilacji.

Ma to na celu dodanie kontroli dotyczących operacji/instrukcji arytmetycznych — które mogą być przepełnione — aby bezpiecznie przerwać proces, jeśli wystąpi przepełnienie. Te środki odkażające mogą złagodzić całą klasę uszkodzeń pamięci i luk w zabezpieczeniach ujawniających informacje, których główną przyczyną jest przepełnienie liczby całkowitej, takie jak oryginalna luka Stagefright.

Przykłady i źródło

Integer Overflow Sanitization (IntSan) jest zapewniana przez kompilator i dodaje oprzyrządowanie do pliku binarnego w czasie kompilacji w celu wykrycia przepełnień arytmetycznych. Jest ona domyślnie włączona w różnych komponentach na całej platformie, na przykład /platform/external/libnl/Android.bp .

Realizacja

IntSan używa środków odkażających z podpisem i bez znaku liczby całkowitej UBSan. To łagodzenie jest włączone na poziomie modułu. Pomaga chronić krytyczne komponenty Androida i nie należy ich wyłączać.

Gorąco zachęcamy do włączenia oczyszczania przepełnienia liczb całkowitych dla dodatkowych komponentów. Idealnymi kandydatami są uprzywilejowany kod natywny lub kod natywny, który analizuje dane wejściowe niezaufanych użytkowników. Ze środkiem odkażającym wiąże się niewielki narzut wydajności, który jest zależny od użycia kodu i częstości operacji arytmetycznych. Spodziewaj się niewielkiego procentu kosztów ogólnych i sprawdź, czy wydajność jest problemem.

Obsługa IntSan w plikach makefile

Aby włączyć IntSan w pliku makefile, dodaj:

LOCAL_SANITIZE := integer_overflow
# Optional features
LOCAL_SANITIZE_DIAG := integer_overflow
LOCAL_SANITIZE_BLACKLIST := modulename_blacklist.txt
  • LOCAL_SANITIZE pobiera rozdzieloną przecinkami listę środków odkażających, przy czym integer_overflow jest wstępnie spakowanym zestawem opcji dla poszczególnych środków odkażających ze znakiem i bez znaku z domyślną czarną listą .
  • LOCAL_SANITIZE_DIAG włącza tryb diagnostyczny dla środków dezynfekujących. Używaj trybu diagnostycznego tylko podczas testowania, ponieważ nie zostanie przerwany w przypadku przepełnienia, całkowicie niwelując przewagę zabezpieczeń wynikającą z ograniczenia ryzyka. Zobacz Rozwiązywanie problemów , aby uzyskać dodatkowe informacje.
  • LOCAL_SANITIZE_BLACKLIST umożliwia określenie pliku czarnej listy, aby zapobiec oczyszczaniu funkcji i plików źródłowych. Zobacz Rozwiązywanie problemów , aby uzyskać dodatkowe informacje.

Jeśli chcesz uzyskać bardziej szczegółową kontrolę, włącz środki dezynfekujące pojedynczo, używając jednej lub obu flag:

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

Obsługa IntSan w plikach blueprint

Aby włączyć oczyszczanie przepełnienia liczb całkowitych w pliku projektu, takim jak /platform/external/libnl/Android.bp , dodaj:

   sanitize: {
      integer_overflow: true,
      diag: {
          integer_overflow: true,
      },
      blacklist: "modulename_blacklist.txt",
   },

Podobnie jak w przypadku plików make, właściwość integer_overflow jest wstępnie spakowanym zestawem opcji dla poszczególnych programów oczyszczania przepełnienia ze znakiem i bez znaku z domyślną czarną listą .

Zestaw właściwości diag włącza tryb diagnostyczny dla środków dezynfekujących. Używaj trybu diagnostycznego tylko podczas testowania. Tryb diagnostyki nie przerywa się w przypadku przepełnienia, co całkowicie neguje zalety zabezpieczeń wynikające z ograniczenia ryzyka w kompilacjach użytkownika. Zobacz Rozwiązywanie problemów , aby uzyskać dodatkowe informacje.

Właściwość blacklist umożliwia określenie pliku czarnej listy, który umożliwia programistom zapobieganie oczyszczaniu funkcji i plików źródłowych. Zobacz Rozwiązywanie problemów , aby uzyskać dodatkowe informacje.

Aby włączyć środki dezynfekujące pojedynczo, użyj:

   sanitize: {
      misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
      diag: {
          misc_undefined: ["signed-integer-overflow",
                           "unsigned-integer-overflow",],
      },
      blacklist: "modulename_blacklist.txt",
   },

Rozwiązywanie problemów

Jeśli włączasz oczyszczanie po przepełnieniu całkowitym w nowych komponentach lub polegasz na bibliotekach platformy, które miały oczyszczanie po przepełnieniu całkowitym, możesz napotkać kilka problemów z łagodnymi przepełnieniami całkowitymi powodującymi przerwania. Należy przetestować komponenty z włączoną dezynfekcją, aby upewnić się, że łagodne przepełnienia mogą zostać ujawnione.

Aby znaleźć przerwania spowodowane oczyszczaniem w kompilacjach użytkownika, wyszukaj awarie SIGABRT z komunikatami Abort wskazującymi na przepełnienie przechwycone przez UBSan, takie jak:

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'ubsan: sub-overflow'

Ślad stosu powinien zawierać funkcję powodującą przerwanie, jednak przepełnienia występujące w funkcjach wbudowanych mogą nie być widoczne w śladzie stosu.

Aby łatwiej określić pierwotną przyczynę, włącz diagnostykę w bibliotece powodującą przerwanie i spróbuj odtworzyć błąd. Po włączeniu diagnostyki proces nie zostanie przerwany i będzie nadal działał. Brak przerywania pomaga zmaksymalizować liczbę łagodnych przepełnień w określonej ścieżce wykonywania bez konieczności ponownej kompilacji po naprawieniu każdego błędu. Diagnostyka generuje komunikat o błędzie zawierający numer wiersza i plik źródłowy 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 zlokalizowaniu problematycznej operacji arytmetycznej upewnij się, że przepełnienie jest łagodne i zamierzone (np. nie ma wpływu na bezpieczeństwo). Możesz zająć się aborcją środka dezynfekującego poprzez:

  • Refaktoryzacja kodu w celu uniknięcia przepełnienia ( przykład )
  • Przepełnienie jawnie za pomocą funkcji __builtin_*_overflow Clanga ( przykład )
  • Wyłączenie sanityzacji w funkcji poprzez określenie atrybutu no_sanitize ( przykład )
  • Wyłączanie sanityzacji funkcji lub pliku źródłowego za pomocą pliku czarnej listy ( przykład )

Powinieneś użyć możliwie najbardziej ziarnistego rozwiązania. Na przykład duża funkcja z wieloma operacjami arytmetycznymi i pojedynczą operacją przepełnienia powinna mieć refaktoryzację pojedynczej operacji, a nie całą funkcję na czarnej liście.

Typowe wzorce, które mogą powodować łagodne przepełnienia, obejmują:

  • Niejawne rzutowania, w których występuje przepełnienie bez znaku przed rzutowaniem na typ ze znakiem ( przykład )
  • Usunięcie listy połączonej, która zmniejsza indeks pętli przy usuwaniu ( przykład )
  • Przypisanie typu bez znaku do -1 zamiast określania rzeczywistej wartości maksymalnej ( przykład )
  • Pętle zmniejszające liczbę całkowitą bez znaku w warunku ( przykład , przykład )

Zaleca się, aby programiści upewnili się, że w przypadkach, w których program dezynfekujący wykryje przepełnienie, jest on rzeczywiście łagodny, bez niezamierzonych skutków ubocznych lub wpływu na bezpieczeństwo przed wyłączeniem czyszczenia.

Wyłączanie IntSan

Możesz wyłączyć IntSan za pomocą czarnych list lub atrybutów funkcji. Wyłącz oszczędnie i tylko wtedy, gdy refaktoryzacja kodu jest nieuzasadniona z innych względów lub jeśli występują problemy z wydajnością.

Więcej informacji na temat wyłączania IntSan z atrybutami funkcji i formatowaniem plików na czarnej liście można znaleźć w dokumentacji Clang. Czarna lista powinna być ograniczona do konkretnego narzędzia odkażającego przy użyciu nazw sekcji określających docelowy środek odkażający, aby uniknąć wpływu na inne środki odkażające.

Walidacja

Obecnie nie ma testu CTS przeznaczonego specjalnie dla oczyszczania przepełnienia liczb całkowitych. Zamiast tego upewnij się, że testy CTS przechodzą z lub bez włączonej funkcji IntSan, aby sprawdzić, czy nie ma to wpływu na urządzenie.