Wdrażanie SELinux

SELinux jest ustawiony na default-deny, co oznacza, że ​​każdy dostęp, do którego ma zaczep w jądrze, musi być jawnie 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 rozważenie SELinux jest poza zakresem tego dokumentu, ale zrozumienie, jak pisać reguły zasad, jest teraz niezbędne przy wprowadzaniu nowych urządzeń z Androidem. Dostępnych jest już wiele informacji dotyczących SELinux. Zobacz dokumentację pomocniczą, aby uzyskać sugerowane zasoby.

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 zawierają 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 dla poszczególnych urządzeń w katalogu /device/ manufacturer / device-name /sepolicy . W systemie Android 8.0 i nowszych zmiany wprowadzone w tych plikach powinny mieć wpływ tylko na zasady w katalogu dostawcy. Aby uzyskać więcej informacji na temat separacji publicznej sepolicy w systemie Android 8.0 i nowszych, zobacz Dostosowywanie SEPolicy w systemie Android 8.0+ . Niezależnie od wersji Androida nadal modyfikujesz te pliki:

Pliki polityki

Pliki, które kończą się na *.te , są plikami źródłowymi strategii SELinux, które definiują domeny i ich etykiety. Może być konieczne utworzenie nowych plików zasad w /device/ manufacturer / device-name /sepolicy , ale w miarę możliwości należy spróbować zaktualizować istniejące pliki.

Pliki kontekstowe

Pliki kontekstowe to miejsca, w których określasz etykiety dla swoich 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ć do plików nowe etykiety. Aby zastosować nowe file_contexts , przebuduj obraz systemu plików lub uruchom restorecon na pliku, który ma zostać oznaczony. Podczas aktualizacji zmiany w file_contexts są automatycznie stosowane do partycji systemowych i partycji 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 swojego init. board .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 odnosić się do i-węzłów w rdzeniu, wymagając ponownego uruchomienia 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ń, takich jak vfat za pomocą opcji context=mount .
  • property_contexts przypisuje etykiety do właściwości systemu Android, aby kontrolować, jakie procesy mogą je ustawiać. Ta konfiguracja jest odczytywana przez proces init podczas uruchamiania.
  • service_contexts przypisuje etykiety do usług spinacza systemu Android, aby kontrolować, jakie procesy mogą dodawać (rejestrować) i znajdować (wyszukiwać) odwołanie do spinacza dla usługi. Ta konfiguracja jest odczytywana przez proces servicemanager podczas uruchamiania.
  • seapp_contexts przypisuje etykiety do procesów aplikacji i katalogów /data/data . Ta konfiguracja jest odczytywana przez proces zygote przy każdym uruchomieniu aplikacji i installd podczas uruchamiania.
  • mac_permissions.xml przypisuje tag seinfo do aplikacji na podstawie ich podpisu i opcjonalnie nazwy pakietu. Znacznik seinfo może być następnie użyty jako klucz w pliku seapp_contexts do 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 zapewniał przestrzenie nazw oparte na UID/AID. Keystore 2.0 dodatkowo wymusza sepolitykę przestrzeni nazw. 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 /device/ manufacturer / device-name /BoardConfig.mk makefile, aby odwoływał się do podkatalogu sepolicy i każdego nowego pliku zasad. Aby uzyskać więcej informacji na temat zmiennych BOARD_SEPOLICY , zobacz plik system/sepolicy/README .

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

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Po przebudowie twoje urządzenie jest włączone z SELinux. Możesz teraz albo dostosować swoje zasady SELinux, aby dostosować je do własnych dodatków do systemu operacyjnego Android, jak opisano w Dostosowywanie , lub zweryfikować istniejącą konfigurację, jak opisano w Walidacji .

Po wprowadzeniu nowych plików strategii i aktualizacji BoardConfig.mk nowe ustawienia strategii są automatycznie wbudowane w końcowy plik strategii jądra. Aby uzyskać więcej informacji na temat tworzenia zasad sepolitycznych na urządzeniu, zobacz Tworzenie zasad sepolitycznych .

Realizacja

Aby rozpocząć pracę z SELinux:

  1. Włącz SELinux w jądrze: CONFIG_SECURITY_SELINUX=y
  2. Zmień parametr kernel_cmdline lub bootconfig w taki sposób, aby:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    lub
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Służy tylko do początkowego opracowywania zasad dla urządzenia. Po ustaleniu początkowej zasady ładowania początkowego usuń ten parametr, aby urządzenie wymuszało lub nie powiodło się CTS.
  3. Uruchom system w trybie permisywnym i zobacz, jakie odmowy występują podczas rozruchu:
    W Ubuntu 14.04 lub nowszym:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    W Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Oceń dane wyjściowe 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, które wymagają etykietowania.
  6. Użyj istniejących lub nowych etykiet dla swoich obiektów. Spójrz na pliki *_contexts , aby zobaczyć, jak rzeczy były wcześniej oznaczane etykietami i użyj znajomości znaczenia etykiet, aby przypisać nowe. Najlepiej byłoby, gdyby była to istniejąca etykieta, która będzie pasować do polityki, ale czasami będzie potrzebna nowa etykieta i potrzebne będą zasady dostępu do tej etykiety. Dodaj swoje 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 zupełnie nową politykę. Na przykład wszystkie usługi zrodzone z init powinny mieć swoje własne. Poniższe polecenia pomagają odkryć te, które nadal działają (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ć wszelkie domeny, które nie mają typu domeny. Daj im domenę na wczesnym etapie procesu tworzenia, aby uniknąć dodawania reguł do init lub w inny sposób pomylić dostęp init z tymi, które są w ich własnych zasadach.
  9. Skonfiguruj BOARD_CONFIG.mk , aby używał zmiennych BOARD_SEPOLICY_* . Zobacz README w system/sepolicy aby uzyskać szczegółowe informacje na temat tego ustawienia.
  10. Zbadaj init. device .rc i fstab. device i upewnij się, że każde użycie mount odpowiada prawidłowo oznaczonemu systemowi plików lub że podano opcję context= mount .
  11. Przejrzyj każdą odmowę i stwórz politykę SELinux, aby prawidłowo obsłużyć każdą z nich. Zobacz przykłady w sekcji Dostosowywanie .

Powinieneś zacząć od zasad w AOSP, a następnie budować na nich własne dostosowania. 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 polityk SELinux:

Dowiązania symboliczne — ponieważ dowiązania symboliczne są wyświetlane jako pliki, 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 aby być nadmiernie otwartymi.

Atakujący mogą następnie zastąpić te pliki dowiązaniami symbolicznymi do kodu, który kontroluje, umożliwiając atakującemu nadpisanie dowolnych plików. Ale jeśli wiesz, że Twoja aplikacja nigdy nie będzie przechodzić przez dowiązanie symboliczne, możesz temu zabronić w SELinuksie.

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. Więc jeśli netd zostanie skompromitowany, może narazić te pliki i potencjalnie sam serwer systemowy.

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ł naruszony, nie może przełączyć domeny na domenę serwera systemowego i uzyskać dostęp do tych plików systemowych, chociaż działa jako root.

Dane aplikacji — innym przykładem jest klasa funkcji, które muszą działać jako root, ale nie powinny uzyskiwać dostępu do danych aplikacji. Jest to niezwykle przydatne, ponieważ można dokonywać zakrojonych na szeroką skalę twierdzeń, takich jak 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 przeprowadzać setattr . Wszystko poza tym może być zabronione przed tymi zmianami, nawet przez rootowanie. Tak więc aplikacja może uruchomić chmod i chown względem tych oznaczonych app_data_files ale nie shell_data_files lub system_data_files .