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.