Pamięć tylko do wykonywania (XOM) dla plików binarnych AArch64

Sekcje kodu wykonywalnego w przypadku systemowych plików binarnych AArch64 są domyślnie oznaczone dostępny tylko do wykonania (nieczytelny) jako środek wzmacniający ochronę przed kodem w czasie rzeczywistym ponownego ataków. Kod łączący dane z kodem, który celowo łączy w sobie kod sprawdza te sekcje (bez uprzedniego przyporządkowywania segmentów pamięci jako czytelnych) już nie działają. Aplikacje z docelowym pakietem SDK 10 (poziom interfejsu API 29 lub wyższy), jeśli aplikacja próbuje odczytać sekcje kodu Biblioteki systemowe z włączoną pamięcią tylko do wykonania (XOM) w pamięci bez wcześniejszego oznaczając sekcję jako czytelną.

Aby można było w pełni korzystać z tego rozwiązania, obsługa sprzętu i jądra Bez tej obsługi środki zaradcze mogą być wyegzekwowane tylko częściowo. Popularne jądro Androida 4.9 zawiera odpowiednie poprawki, które zapewniają pełną na urządzeniach z architekturą ARM 8.2.

Implementacja

W plikach binarnych AArch64 wygenerowanych przez kompilator zakłada, że kod i dane nie są przemieszane. Włączenie tej funkcji nie wpływa negatywnie na wydajność urządzenia.

W przypadku kodu, który musi przeprowadzać zamierzone introspekcję pamięci segmentów wykonywalnych, zalecamy wywołanie metody mprotect na fragmenty kodu, które wymagają kontroli, aby były czytelne, usunąć czytelność po zakończeniu inspekcji.
Ta implementacja powoduje odczyty do segmentów pamięci oznaczonych jako tylko wykonanie, co spowoduje błąd segmentacji (SEGFAULT). Może to nastąpić w wyniku błędu, luki w zabezpieczeniach, danych pomieszanych kod (dosłowne łączenie w puli) lub celowa introspekcja pamięci.

Obsługa urządzeń i jej wpływ

Urządzenia z wcześniejszymi jądrami sprzętowymi lub wcześniejszymi jądrami (starszymi niż 4.9) bez wymagane poprawki mogą nie obsługiwać tej funkcji w pełni lub nie korzystać z niej. Urządzenia bez obsługi jądra systemu może nie wymuszać dostępu użytkownika do pamięci tylko do wykonania, jednak kod jądra, który jednoznacznie sprawdza, czy strona jest czytelna, może wymuszać tę właściwość, na przykład process_vm_readv().

Flaga jądra CONFIG_ARM64_UAO musi być ustawiona w jądrze na upewnij się, że jądro respektuje strony użytkowników oznaczone jako przeznaczone tylko do wykonania. Wcześniejsza wersja ARM w wersji 8 urządzeń i urządzeń z architekturą ARMv8.2 z wyłączonym zastąpieniem dostępu użytkownika (UAO) nie mogą w pełni korzystać z możliwości tej funkcji i nadal być w stanie odczytać strony przeznaczone tylko do wykonania za pomocą funkcji syscall.

Refaktoryzacja istniejącego kodu

Kod przeniesiony z AArch32 może zawierać przemieszane dane przez kod, co powoduje problemy. W wielu przypadkach rozwiązanie tych problemów jest równie proste jak przeniesienie stałych do sekcji .data w pliku montażu.

Odręcznie napisany zestaw może wymagać refaktoryzacji, aby oddzielić lokalnie stałe.

Przykłady:

W plikach binarnych wygenerowanych przez kompilator Clang nie powinno być problemów z danymi nie jest wymieszana w kodzie. Jeśli kod wygenerowany przez kompilator GNU (GCC) będzie z biblioteki statycznej, sprawdź wyjściowy plik binarny by sprawdzić, czy stałe nie zostały połączone w sekcje kodu.

Jeśli introspekcja kodu jest wymagana w przypadku sekcji kodu wykonywalnego, Najpierw wywołaj mprotect, aby oznaczyć kod jako czytelny. Później po wykonaniu operacji zakończono, wywołaj ponownie mprotect, by oznaczyć go jako nieczytelny.

Włącz XOM

Funkcja „Tylko uruchamianie” jest domyślnie włączona dla wszystkich 64-bitowych plików binarnych w kompilacji systemu.

Wyłącz XOM

Możesz wyłączyć funkcję „Tylko wykonanie” na poziomie modułu, całego drzewa podkatalogów lub globalnie dla całej kompilacji.

XOM można wyłączyć w przypadku pojedynczych modułów, których nie można przeprowadzić refaktoryzacji, lub wymagających kodu wykonywalnego przez ustawienie atrybutu LOCAL_XOM i xom do false.

// Android.mk
LOCAL_XOM := false

// Android.bp
cc_binary { // or other module types
   ...
   xom: false,
}

Jeśli w bibliotece statycznej pamięć tylko do wykonywania jest wyłączona, system kompilacji zostanie zastosowany do wszystkich modułów zależnych tej biblioteki statycznej. Możesz zastąpić w tym celu za pomocą funkcji xom: true,.

Aby wyłączyć pamięć tylko do wykonania w konkretnym podkatalogu (na przykład foo/bar/), przekaż wartość do funkcji XOM_EXCLUDE_PATHS.

make -j XOM_EXCLUDE_PATHS=foo/bar

Możesz też ustawić PRODUCT_XOM_EXCLUDE_PATHS w konfiguracji produktu.

Możesz globalnie wyłączyć pliki binarne tylko do wykonania, przesyłając ENABLE_XOM=false do polecenia make.

make -j ENABLE_XOM=false

Weryfikacja

Nie są dostępne żadne testy CTS ani testy weryfikacyjne dostępne tylko w ramach wykonywania pamięci. Możesz ręcznie weryfikować pliki binarne za pomocą readelf i sprawdzając we flagach segmentu.