Tworzenie zasad SELinux

Na tej stronie dowiesz się, jak tworzone są zasady SELinux. Zasady SELinux są tworzone na podstawie połączenia podstawowych zasad AOSP (platformy) i zasad dotyczących konkretnego urządzenia (dostawcy). Proces tworzenia zasad SELinux w przypadku Androida 4.4–7.0 polegał na scalaniu wszystkich fragmentów sepolicy, a następnie generowaniu monolitycznych plików w katalogu głównym. Oznaczało to, że dostawcy układów SoC i producenci ODM modyfikowali boot.img (w przypadku urządzeń innych niż A/B) lub system.img (w przypadku urządzeń A/B) za każdym razem, gdy zmieniano zasady.

W Androidzie 8.0 i nowszym zasady platformy i dostawcy są tworzone oddzielnie. Producenci układów SoC i OEM mogą aktualizować swoje części zasad, tworzyć obrazy (np. vendor.imgboot.img), a następnie aktualizować te obrazy niezależnie od aktualizacji platformy.

Jednak ponieważ modułowe pliki zasad SELinux są przechowywane na partycjach /vendor, proces init musi wcześniej zamontować partycje system i vendor, aby móc odczytać z nich pliki SELinux i połączyć je z głównymi plikami SELinux w katalogu system (przed załadowaniem ich do jądra).

Pliki źródłowe

Logika tworzenia SELinux znajduje się w tych plikach:

  • external/selinux: zewnętrzny projekt SELinux, używany do tworzenia narzędzi wiersza poleceń HOST do kompilowania zasad i etykiet SELinux.
    • external/selinux/libselinux: Android używa tylko podzbioru zewnętrznego projektu libselinux wraz z pewnymi dostosowaniami specyficznymi dla Androida. Więcej informacji znajdziesz w sekcji external/selinux/README.android.
    • external/selinux/libsepol:
      • chkcon: określa, czy kontekst zabezpieczeń jest prawidłowy w przypadku danej zasady binarnej (wykonywalny plik hosta).
      • libsepol: biblioteka SELinux do manipulowania binarnymi zasadami bezpieczeństwa (biblioteka statyczna/współdzielona hosta, biblioteka statyczna docelowa).
    • external/selinux/checkpolicy: kompilator zasad SELinux (pliki wykonywalne hosta: checkpolicy, checkmoduledispol). Zależy od libsepol.
  • system/sepolicy: podstawowe konfiguracje zasad SELinux w Androidzie, w tym konteksty i pliki zasad. Znajduje się tu też główna logika kompilacji sepolicy (system/sepolicy/Android.mk).

Więcej informacji o plikach w system/sepolicy znajdziesz w artykule Pliki kluczy.

Android 7.x i starsze

W tej sekcji opisujemy, jak tworzone są zasady SELinux w Androidzie 7.x i starszych wersjach.

Proces kompilacji w przypadku Androida 7.x i starszych wersji

Zasady SELinux są tworzone przez połączenie podstawowych zasad AOSP z dostosowaniami specyficznymi dla urządzenia. Połączone zasady są następnie przekazywane do kompilatora zasad i różnych narzędzi sprawdzających. Dostosowywanie do konkretnego urządzenia odbywa się za pomocą zmiennej BOARD_SEPOLICY_DIRS zdefiniowanej w pliku BOARD_SEPOLICY_DIRS dotyczącym konkretnego urządzenia.Boardconfig.mk Ta globalna zmienna kompilacji zawiera listę katalogów, które określają kolejność wyszukiwania dodatkowych plików zasad.

Na przykład dostawca układu SoC i producent ODM mogą dodać po jednym katalogu – jeden z ustawieniami specyficznymi dla układu SoC, a drugi z ustawieniami specyficznymi dla urządzenia – aby wygenerować końcowe konfiguracje SELinux dla danego urządzenia:

  • BOARD_SEPOLICY_DIRS += device/SoC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

Zawartość plików file_contexts w system/sepolicyBOARD_SEPOLICY_DIRS jest łączona w celu wygenerowania file_contexts.bin na urządzeniu:

Logika kompilacji SELinux w Androidzie 7.x

Rysunek 1. Logika kompilacji SELinux.

Plik sepolicy składa się z kilku plików źródłowych:

  • Zwykły tekst policy.conf jest generowany przez połączenie plików security_classes, initial_sids, *.te, genfs_contextsport_contexts w tej kolejności.
  • W przypadku każdego pliku (np. security_classes) jego zawartość jest konkatenacją plików o tej samej nazwie w katalogach system/sepolicy/ i BOARDS_SEPOLICY_DIRS.
  • policy.conf jest wysyłany do kompilatora SELinux w celu sprawdzenia składni i kompilowany do formatu binarnego jako sepolicy na urządzeniu.

    Pliki, które generują plik zasad SELinux
      dla Androida 7.x
    Rysunek 2. plik zasad SELinux,

Pliki SELinux

Po skompilowaniu urządzenia z Androidem 7.x i starszym zwykle zawierają te pliki związane z SELinux:

  • selinux_version
  • sepolicy: dane binarne po połączeniu plików zasad (np. security_classes, initial_sids*.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

Więcej informacji znajdziesz w artykule Implementowanie SELinux.

Inicjalizacja SELinux

Po uruchomieniu systemu SELinux działa w trybie zezwalającym (a nie w trybie egzekwowania). Proces init wykonuje te zadania:

  • Wczytuje sepolicy plików z dysku RAM do jądra za pomocą /sys/fs/selinux/load.
  • Przełącza SELinux w tryb egzekwowania.
  • Uruchamia re-exec(), aby zastosować do siebie regułę domeny SELinux.

Aby skrócić czas rozruchu, jak najszybciej wykonaj proces re-exec() na urządzeniuinit.

Android 8.0 lub nowszy

W Androidzie 8.0 zasady SELinux są podzielone na komponenty platformy i dostawcy, co umożliwia niezależne aktualizowanie zasad platformy i dostawcy przy zachowaniu zgodności.

Zasady platformy są dodatkowo dzielone na części prywatną i publiczną, aby eksportować określone typy i atrybuty do twórców zasad dostawców. Gwarantujemy, że publiczne typy i atrybuty platformy będą stabilnymi interfejsami API w przypadku danej wersji platformy. Zgodność z poprzednimi typami/atrybutami publicznymi platformy można zagwarantować w przypadku kilku wersji za pomocą plików mapowania platformy.

Proces kompilacji w Androidzie 8.0

Zasady SELinux w Androidzie 8.0 powstają przez połączenie fragmentów z /system/vendor. Logika prawidłowego konfigurowania tego ustawienia znajduje się w  /platform/system/sepolicy/Android.bp.

Zasady te obowiązują w tych lokalizacjach:

Lokalizacja Zawiera
system/sepolicy/public Platform sepolicy API
system/sepolicy/private Szczegóły wdrożenia na platformie (dostawcy mogą je zignorować)
system/sepolicy/vendor Pliki zasad i kontekstu, których dostawcy mogą używać (dostawcy mogą je zignorować)
BOARD_SEPOLICY_DIRS Vendor sepolicy
BOARD_ODM_SEPOLICY_DIRS (Android 9 lub nowszy) ODM sepolicy
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 lub nowszy) system_ext sepolicy API
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 lub nowszy) system_ext szczegóły implementacji (dostawcy mogą je zignorować);
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 lub nowszy) Product sepolicy API
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 lub nowszy) Szczegóły implementacji usługi (dostawcy mogą je zignorować)

System kompilacji pobiera te zasady i tworzy komponenty zasad system, system_ext, product, vendorodm w odpowiedniej partycji. Kroki obejmują:

  1. Przekonwertuj zasady na format SELinux Common Intermediate Language (CIL), a w szczególności:
    • Zasady dotyczące platform publicznych (system, system_ext, product)
    • Połączona polityka prywatności i polityka publiczna
    • Zasady publiczne, zasady dostawcy i zasady BOARD_SEPOLICY_DIRS
  2. Wersja zasad udostępnionych publicznie w ramach zasad dostawcy. Wygenerowane publiczne zasady CIL posłużą do określenia, które części połączonych zasad publicznych, zasad dostawcy i zasad BOARD_SEPOLICY_DIRS muszą zostać przekształcone w atrybuty połączone z zasadami platformy.
  3. Utwórz plik mapowania łączący części platformy i sprzedawcy. Początkowo ta funkcja tylko łączy typy z zasad publicznych z odpowiednimi atrybutami w zasadach dostawcy. Później będzie też stanowić podstawę pliku utrzymywanego w przyszłych wersjach platformy, co umożliwi zgodność z zasadami dostawcy kierowanymi na tę wersję platformy.
  4. Połącz pliki zasad (opisz rozwiązania na urządzeniu i wstępnie skompilowane).
    1. Połącz zasady mapowania, platformy i dostawcy.
    2. Skompiluj wyjściowy plik binarny zasad.

Platform public sepolicy

Publiczna zasada SEPolicy platformy obejmuje wszystko, co jest zdefiniowane w sekcji system/sepolicy/public. Platforma może założyć, że typy i atrybuty zdefiniowane w zasadach publicznych są stabilnymi interfejsami API dla danej wersji platformy. Stanowi to część zasad bezpieczeństwa, która jest eksportowana przez platformę, na której deweloperzy zasad dostawcy (czyli urządzenia) mogą pisać dodatkowe zasady dotyczące konkretnego urządzenia.

Typy są wersjonowane zgodnie z wersją zasad, w odniesieniu do której pisane są pliki dostawcy, zdefiniowaną przez zmienną kompilacji PLATFORM_SEPOLICY_VERSION. Wersja zasad publicznych jest następnie dołączana do zasad dostawcy i (w oryginalnej formie) do zasad platformy. W związku z tym ostateczne zasady obejmują zasady platformy prywatnej, publiczne zasady bezpieczeństwa platformy bieżącej, zasady dotyczące urządzenia i wersjonowane zasady publiczne odpowiadające wersji platformy, na podstawie której zostały opracowane zasady dotyczące urządzenia.

Platform private sepolicy

Prywatne zasady bezpieczeństwa platformy obejmują wszystko, co zostało zdefiniowane w sekcji /system/sepolicy/private. Ta część zasad określa typy, uprawnienia i atrybuty wymagane do działania platformy. Nie są one eksportowane do dostawców ani autorów zasad dotyczących urządzeń. Osoby piszące zasady spoza platformy nie mogą tworzyć rozszerzeń zasad na podstawie typów, atrybutów i reguł zdefiniowanych w prywatnych zasadach bezpieczeństwa platformy. Ponadto te reguły można modyfikować lub mogą one zniknąć w ramach aktualizacji samego frameworka.

Prywatne mapowanie platformy

Prywatne mapowanie platformy obejmuje oświadczenia o zasadach, które mapują atrybuty udostępniane w publicznych zasadach platformy w poprzednich wersjach platformy na konkretne typy używane w bieżących publicznych zasadach platformy sepolicy. Dzięki temu zasady dostawcy, które zostały napisane na podstawie publicznych atrybutów platformy z poprzednich wersji publicznych zasad bezpieczeństwa platformy, nadal działają. Wersjonowanie opiera się na zmiennej kompilacji PLATFORM_SEPOLICY_VERSION ustawionej w AOSP dla danej wersji platformy. Dla każdej poprzedniej wersji platformy, z której ta platforma ma akceptować zasady dostawcy, istnieje osobny plik mapowania. Więcej informacji znajdziesz w artykule Zgodność zasad.

Android 11 lub nowszy

W tej sekcji opisujemy, jak tworzone są zasady SELinux w Androidzie 11 i nowszym.

system_ext i zasady bezpieczeństwa produktu

W Androidzie 11 dodano zasady system_extproduct. Podobnie jak w przypadku zasad platformy, zasady system_ext i zasady product są podzielone na zasady publiczne i zasady prywatne.

Zasady publiczne są eksportowane do dostawcy. Typy i atrybuty stają się stabilnym interfejsem API, a zasady dostawcy mogą odwoływać się do typów i atrybutów w zasadach publicznych. Typy są wersjonowane zgodnie z PLATFORM_SEPOLICY_VERSION, a wersjonowane zasady są uwzględniane w zasadach dostawcy. Pierwotne zasady są uwzględnione w każdej z partycji system_extproduct.

Zasady ochrony prywatności zawierają typy, uprawnienia i atrybuty wymagane tylko w przypadku system_ext i tylko w przypadku product, które są niezbędne do działania funkcji podziału system_extproduct. Zasady prywatności są niewidoczne dla dostawcy, co oznacza, że te reguły są wewnętrzne i można je modyfikować.

mapowanie system_ext i product;

system_extproduct mogą eksportować wyznaczone typy publiczne do dostawcy. Każdy partner jest jednak odpowiedzialny za zachowanie zgodności. Aby zapewnić zgodność, partnerzy mogą udostępniać własne pliki mapowania, które mapują atrybuty z wersjami z poprzednich wersji na konkretne typy używane w bieżącej publicznej wersji sepolicy:

  • Aby zainstalować plik mapowania dla system_ext, umieść plik CIL zawierający odpowiednie informacje o mapowaniu w {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, a następnie dodaj system_ext_{ver}.cil do PRODUCT_PACKAGES.
  • Aby zainstalować plik mapowania dla product, umieść plik CIL zawierający odpowiednie informacje o mapowaniu w {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, a następnie dodaj product_{ver}.cil do PRODUCT_PACKAGES.

Zapoznaj się z przykładem, w którym dodano plik mapowania partycji product urządzenia Redbull.

Wstępnie skompilowane zasady SELinux

Zanim init włączy SELinux, init zbiera wszystkie pliki CIL z partycji (system, system_ext, product, vendorodm) i kompiluje je do postaci binarnej, którą można wczytać do jądra. Kompilacja zajmuje trochę czasu (zwykle 1–2 sekundy), dlatego pliki CIL są wstępnie kompilowane w czasie kompilacji i umieszczane w folderze /vendor/etc/selinux/precompiled_sepolicy lub /odm/etc/selinux/precompiled_sepolicy wraz z haszami sha256 wejściowych plików CIL. W czasie działania init sprawdza, czy któryś z plików zasad został zaktualizowany, porównując hasze. Jeśli nic się nie zmieniło, init wczytuje wstępnie skompilowane zasady. Jeśli nie, init kompiluje go na bieżąco i używa zamiast wstępnie skompilowanego.

W szczególności wstępnie skompilowane zasady są używane, jeśli spełnione są wszystkie te warunki: W tym przypadku {partition} oznacza partycję, w której znajduje się wstępnie skompilowana zasada: vendor lub odm.

  • Oba elementy /system/etc/selinux/plat_sepolicy_and_mapping.sha256 i /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 istnieją i są identyczne.
  • Nie istnieją zarówno /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256, jak i /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256. lub oba istnieją i są identyczne.
  • Nie istnieją zarówno /product/etc/selinux/product_sepolicy_and_mapping.sha256, jak i /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256. lub oba istnieją i są identyczne.

Jeśli któraś z nich się różni, init wraca do ścieżki kompilacji na urządzeniu. Więcej informacji znajdziesz w sekcji system/core/init/selinux.cpp.