Pamięć z zerowym zainicjalizowaniem

Nieinicjalizowana pamięć w językach C i C++ jest częstą przyczyną problemów z niezawodnością, błędów związanych z bezpieczeństwem pamięci i wycieków informacji. Aby uniknąć tych problemów, Android inicjalizuje tyle pamięci, ile to możliwe.

Pamięć w przestrzeni użytkownika z zerowym zainicjowaniem

Od Androida 12 pamięć stosu jest zerowana we wszystkich natywnych kodzie platformy (w tym JNI), a pamięć stosu jest zerowana we wszystkich natywnych procesach platformy (takich jak netd), ale nie w zygote ani w aplikacjach.

W przypadku aplikacji własnych i aplikacji innych firm tworzonych za pomocą NDK zdecydowanie zalecamy używanie parametru -ftrivial-auto-var-init=zero flagi kompilatora do zerowania lokalnych zmiennych stosu. Kompilator usuwa niepotrzebne zerowanie. Na przykład gdy zmienna lokalna jest jawnie inicjowana (np. zmienna int x = 123; inicjowana jest tylko raz).x Jeśli program ma duży bufor stosu w miejscu o wysokim obciążeniu, deweloper może wyłączyć inicjowanie za pomocą atrybutu kompilatora:

__attribute__((__uninitialized__)) char buf[BUFSIZ];

Aplikacje mogą też korzystać z inicjalizacji stosu 0 za pomocą atrybutu android:nativeHeapZeroInitialized w pliku manifestu. Możesz też kontrolować inicjowanie sterty zerowej w czasie wykonywania za pomocą:

int mallopt(M_BIONIC_ZERO_INIT, level)

Gdzie level to 0 lub 1.

Pamięć jądra z zerowym zainicjowaniem

Stos i stos dynamiczny jądra są inicjowane zerami równymi 0 w przypadku jąder GKI, co jest zdecydowanie zalecane przez zespół ds. jakości danych (CDD).

Do inicjalizacji stosu GKI używa konfiguracji CONFIG_INIT_STACK_ALL_ZERO, co powoduje kompilowanie jądra za pomocą flagi kompilatora -ftrivial-auto-var-init=zero. Do inicjowania stosu GKI używa funkcji CONFIG_INIT_ON_ALLOC_DEFAULT_ON, która sprawia, że wszystkie alokacje stosu strony, SLAB i SLUB są inicjowane do zera podczas tworzenia. Ta opcja jest w podstawie podobna do przekazywania wartości init_on_alloc=1 jako opcji jądra w czasie uruchamiania.

Raporty o błędach

Nasze narzędzia generują szczegółowe raporty o błędach, które zawierają dodatkowe informacje ułatwiające debugowanie. Dodatkowy ślad stosu alokacji i zwolnienia alokacji pomaga lepiej zrozumieć cykl życia danej alokacji i szybciej dotrzeć do pierwotnych przyczyn błędów związanych z bezpieczeństwem pamięci.

Przykład raportu o błędzie wygenerowanego przez narzędzie do sprawdzania bezpieczeństwa pamięci
Ilustracja 1. Raporty o błędach generowane przez narzędzia do sprawdzania bezpieczeństwa pamięci

W trakcie tworzenia dostawcy powinni sprawdzać, czy nie ma błędów, korzystając z funkcji /data/tombstoneslogcat w przypadku awarii natywnych. Więcej informacji o debugowaniu kodu natywnego na Androida znajdziesz tutaj.