Implementacja SELinuksa

SELinux jest ustawiony na domyślną odmowę, co oznacza, że ​​każdy dostęp, na który ma hak w jądrze, musi być wyraźnie dozwolony przez politykę. Oznacza to, że plik zasad składa się z dużej ilości informacji dotyczących reguł, typów, klas, uprawnień i nie tylko. Pełne omówienie SELinux wykracza poza zakres tego dokumentu, ale zrozumienie sposobu pisania reguł polityki jest teraz niezbędne przy wprowadzaniu nowych urządzeń z Androidem. Dostępnych jest już wiele informacji na temat SELinuksa. Zobacz dokumentację pomocniczą , aby zapoznać się z sugerowanymi zasobami.

Kluczowe pliki

Aby włączyć SELinux, zintegruj najnowsze jądro Androida , a następnie dołącz pliki znajdujące się w katalogu system/sepolicy . Po skompilowaniu pliki te obejmują politykę bezpieczeństwa jądra SELinux i obejmują nadrzędny system operacyjny Android.

Ogólnie rzecz biorąc, nie należy bezpośrednio modyfikować plików system/sepolicy . Zamiast tego dodaj lub edytuj własne pliki zasad specyficzne dla urządzenia w katalogu /device/ manufacturer / device-name /sepolicy . W Androidzie 8.0 i nowszych zmiany wprowadzone w tych plikach powinny mieć wpływ tylko na zasady w katalogu dostawców. Aby uzyskać więcej informacji na temat oddzielenia polityki publicznej w systemie Android 8.0 i nowszych, zobacz Dostosowywanie SEPolicy w systemie Android 8.0 lub nowszym . Niezależnie od wersji Androida nadal modyfikujesz te pliki:

Pliki zasad

Pliki kończące się na *.te to pliki źródłowe zasad SELinux, które definiują domeny i ich etykiety. Może być konieczne utworzenie nowych plików zasad w /device/ manufacturer / device-name /sepolicy , ale jeśli to możliwe, powinieneś spróbować zaktualizować istniejące pliki.

Pliki kontekstowe

Pliki kontekstowe służą do określania etykiet obiektów.

  • file_contexts przypisuje etykiety do plików i jest używany przez różne komponenty przestrzeni użytkownika. Podczas tworzenia nowych zasad utwórz lub zaktualizuj ten plik, aby przypisać nowe etykiety do plików. Aby zastosować nowy file_contexts , odbuduj obraz systemu plików lub uruchom restorecon na pliku, którego etykieta ma zostać zmieniona. Podczas aktualizacji zmiany w file_contexts są automatycznie stosowane do partycji systemowych i danych użytkownika w ramach aktualizacji. Zmiany można również automatycznie zastosować podczas aktualizacji na inne partycje, dodając wywołania restorecon_recursive do pliku init. board plik .rc po zamontowaniu partycji do odczytu i zapisu.
  • genfs_contexts przypisuje etykiety do systemów plików, takich jak proc lub vfat , które nie obsługują rozszerzonych atrybutów. Ta konfiguracja jest ładowana jako część polityki jądra, ale zmiany mogą nie zostać uwzględnione w przypadku i-węzłów w rdzeniu, co wymaga ponownego uruchomienia komputera lub odmontowania i ponownego zamontowania systemu plików, aby w pełni zastosować zmiany. Określone etykiety mogą być również przypisane do konkretnych montowań, np. vfat przy użyciu opcji context=mount .
  • property_contexts przypisuje etykiety do właściwości systemu Android, aby kontrolować, jakie procesy mogą je ustawiać. Konfiguracja ta jest odczytywana przez proces init podczas uruchamiania.
  • service_contexts przypisuje etykiety do usług segregatorów systemu Android, aby kontrolować, jakie procesy mogą dodawać (rejestrować) i znajdować (wyszukiwać) odniesienia do segregatorów dla usługi. Konfiguracja ta jest odczytywana przez proces servicemanager podczas uruchamiania.
  • seapp_contexts przypisuje etykiety procesom aplikacji i katalogom /data/data . Ta konfiguracja jest odczytywana przez proces zygote przy każdym uruchomieniu aplikacji i installd podczas uruchamiania.
  • mac_permissions.xml przypisuje znacznik seinfo do aplikacji na podstawie ich podpisu i opcjonalnie nazwy pakietu. Znacznik seinfo może następnie zostać użyty jako klucz w pliku seapp_contexts w celu przypisania określonej etykiety do wszystkich aplikacji z tym znacznikiem seinfo . Ta konfiguracja jest odczytywana przez system_server podczas uruchamiania.
  • keystore2_key_contexts przypisuje etykiety do przestrzeni nazw Keystore 2.0. Te przestrzenie nazw są wymuszane przez demona keystore2. Magazyn kluczy zawsze udostępniał przestrzenie nazw oparte na UID/AID. Magazyn kluczy 2.0 dodatkowo wymusza przestrzenie nazw zdefiniowane przez sepolicy. Szczegółowy opis formatu i konwencji tego pliku można znaleźć tutaj .

Plik Makefile BoardConfig.mk

Po edycji lub dodaniu plików zasad i kontekstu zaktualizuj plik makefile /device/ manufacturer / device-name /BoardConfig.mk aby odwoływał się do podkatalogu sepolicy i każdego nowego pliku polityki. Więcej informacji na temat zmiennych BOARD_SEPOLICY można znaleźć w pliku system/sepolicy/README .

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Po odbudowaniu Twoje urządzenie będzie mogło korzystać z SELinux. Możesz teraz dostosować zasady SELinux, aby uwzględnić własne dodatki do systemu operacyjnego Android, zgodnie z opisem w sekcji Dostosowywanie , lub zweryfikować istniejącą konfigurację zgodnie z opisem w sekcji Walidacja .

Po zainstalowaniu nowych plików zasad i aktualizacji BoardConfig.mk nowe ustawienia zasad zostaną automatycznie wbudowane w ostateczny plik zasad jądra. Aby uzyskać więcej informacji na temat tworzenia sepolicy na urządzeniu, zobacz Tworzenie sepolicy .

Realizacja

Aby rozpocząć pracę z SELinuxem:

  1. Włącz SELinux w jądrze: CONFIG_SECURITY_SELINUX=y
  2. Zmień parametr kernel_cmdline lub bootconfig tak, aby:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    lub
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    To służy tylko do wstępnego opracowania polityki dla urządzenia. Po ustaleniu początkowej zasady ładowania początkowego usuń ten parametr, aby urządzenie egzekwowało zasady, w przeciwnym razie CTS nie powiedzie się.
  3. Uruchom system w trybie zezwalającym i zobacz, jakie odmowy występują podczas uruchamiania:
    W systemie Ubuntu 14.04 lub nowszym:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    W systemie Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Oceń wynik pod kątem ostrzeżeń przypominających init: Warning! Service name needs a SELinux domain defined; please fix! Zobacz Walidacja , aby uzyskać instrukcje i narzędzia.
  5. Identyfikuj urządzenia i inne nowe pliki wymagające etykietowania.
  6. Użyj istniejących lub nowych etykiet dla swoich obiektów. Przejrzyj pliki *_contexts , aby zobaczyć, jak rzeczy były wcześniej oznaczone, i wykorzystaj wiedzę o znaczeniu etykiet, aby przypisać nowe. W idealnym przypadku będzie to istniejąca etykieta, która będzie pasować do polityki, ale czasami potrzebna będzie nowa etykieta i zasady dostępu do tej etykiety. Dodaj etykiety do odpowiednich plików kontekstowych.
  7. Zidentyfikuj domeny/procesy, które powinny mieć własne domeny zabezpieczeń. Prawdopodobnie będziesz musiał napisać dla każdego z nich zupełnie nową polisę. Na przykład wszystkie usługi zrodzone z init powinny mieć własne. Poniższe polecenia pomagają odkryć te, które pozostają uruchomione (ale WSZYSTKIE usługi wymagają takiego traktowania):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Przejrzyj init. device .rc aby zidentyfikować domeny, które nie mają typu domeny. Daj im domenę na początku procesu programowania, aby uniknąć dodawania reguł do init lub w inny sposób mylenia dostępu init z tymi, które są w ich własnych zasadach.
  9. Skonfiguruj BOARD_CONFIG.mk tak, aby używał zmiennych BOARD_SEPOLICY_* . Zobacz README w system/sepolicy aby uzyskać szczegółowe informacje na temat konfiguracji.
  10. Sprawdź init. device .rc i fstab. device i upewnij się, że każde użycie mount odpowiada odpowiednio oznaczonemu systemowi plików lub że określono opcję context= mount .
  11. Przejrzyj każdą odmowę i utwórz politykę SELinux, aby prawidłowo obsłużyć każdą odmowę. Zobacz przykłady w Dostosowywanie .

Powinieneś zacząć od zasad w AOSP, a następnie wykorzystać je do własnych dostosowań. Aby uzyskać więcej informacji na temat strategii polityki i bliżej przyjrzeć się niektórym z tych kroków, zobacz Pisanie polityki SELinux .

Przypadków użycia

Oto konkretne przykłady exploitów, które należy wziąć pod uwagę podczas tworzenia własnego oprogramowania i powiązanych zasad SELinux:

Dowiązania symboliczne — ponieważ dowiązania symboliczne pojawiają się w postaci plików, często są odczytywane jako pliki, co może prowadzić do exploitów. Na przykład niektóre uprzywilejowane komponenty, takie jak init , zmieniają uprawnienia niektórych plików, czasami powodując ich nadmierne otwarcie.

Osoby atakujące mogą następnie zastąpić te pliki dowiązaniami symbolicznymi do kontrolowanego przez siebie kodu, umożliwiając osobie atakującej zastąpienie dowolnych plików. Ale jeśli wiesz, że Twoja aplikacja nigdy nie przejdzie przez dowiązanie symboliczne, możesz zabronić jej tego w SELinux.

Pliki systemowe — rozważ klasę plików systemowych, które powinny być modyfikowane tylko przez serwer systemowy. Mimo to, ponieważ netd , init i vold działają jako root, mogą uzyskać dostęp do tych plików systemowych. Jeśli więc netd zostanie naruszony, może zagrozić tym plikom i potencjalnie samemu serwerowi systemowemu.

Dzięki SELinux możesz zidentyfikować te pliki jako pliki danych serwera systemowego. Dlatego jedyną domeną, która ma do nich dostęp do odczytu/zapisu, jest serwer systemowy. Nawet jeśli netd zostałby naruszony, nie mógłby przełączyć domen na domenę serwera systemowego i uzyskać dostępu do plików systemowych, mimo że działa jako root.

Dane aplikacji — innym przykładem jest klasa funkcji, które muszą działać jako root, ale nie powinny mieć dostępu do danych aplikacji. Jest to niezwykle przydatne, ponieważ można sformułować szerokie twierdzenia, na przykład zakaz dostępu do Internetu dla niektórych domen niezwiązanych z danymi aplikacji.

setattr — w przypadku poleceń takich jak chmod i chown można zidentyfikować zestaw plików, w których powiązana domena może wykonać setattr . Wszystko poza tym może być zabronione w przypadku tych zmian, nawet przez rootowanie. Zatem aplikacja może uruchomić chmod i chown względem plików oznaczonych jako app_data_files , ale nie shell_data_files lub system_data_files .