Zgodność zasad

W tym artykule opisano, jak Android radzi sobie z problemami zgodności zasad z platformami OTA, gdzie ustawienia SELinux nowej platformy mogą różnić się od ustawień SELinux starego dostawcy.

Projekt polityki SELinux oparty na Treble uwzględnia binarne rozróżnienie pomiędzy polityką platformy i dostawcy ; schemat staje się bardziej skomplikowany, jeśli partycje dostawców generują zależności, takie jak platform < vendor < oem .

W systemie Android 8.0 i nowszych, globalna polityka SELinux jest podzielona na komponenty prywatne i publiczne. Komponenty publiczne składają się z polityki i powiązanej infrastruktury, które z pewnością będą dostępne dla wersji platformy. Ta zasada zostanie udostępniona autorom zasad dostawcy, aby umożliwić dostawcom utworzenie pliku zasad dostawcy, który w połączeniu z zasadami dostarczonymi przez platformę daje w wyniku w pełni funkcjonalną politykę dla urządzenia.

  • W przypadku wersjonowania wyeksportowana polityka publiczna platformy zostanie zapisana jako atrybuty .
  • Aby ułatwić pisanie zasad, wyeksportowane typy zostaną przekształcone w atrybuty wersjonowane w ramach procesu tworzenia zasad. Typy publiczne mogą być również używane bezpośrednio w decyzjach dotyczących etykietowania dostarczanych przez pliki kontekstu dostawcy.

Android utrzymuje mapowanie pomiędzy wyeksportowanymi konkretnymi typami w zasadach platformy i odpowiadającymi im atrybutami wersji dla każdej wersji platformy . Gwarantuje to, że gdy obiekty zostaną oznaczone etykietą typu, nie zerwie to zachowania gwarantowanego przez politykę publiczną platformy w poprzedniej wersji. To mapowanie jest utrzymywane poprzez aktualizowanie pliku mapowania dla każdej wersji platformy , w którym przechowywane są informacje o członkostwie atrybutów dla każdego typu wyeksportowane w zasadach publicznych.

Własność obiektu i etykietowanie

Podczas dostosowywania zasad w systemie Android 8.0 i nowszych wersjach należy jasno określić własność każdego obiektu, aby zachować odrębność zasad platformy i dostawcy. Na przykład, jeśli dostawca oznaczy etykietą /dev/foo a platforma następnie oznaczy etykietą /dev/foo w kolejnym OTA, zachowanie będzie niezdefiniowane. W przypadku SELinux objawia się to kolizją etykiet. Węzeł urządzenia może mieć tylko jedną etykietę, która odpowiada tej, która zostanie zastosowana jako ostatnia. W rezultacie:

  • Procesy wymagające dostępu do etykiety, która została nieudana, utracą dostęp do zasobu.
  • Procesy uzyskujące dostęp do pliku mogą zostać przerwane, ponieważ utworzono niewłaściwy węzeł urządzenia.

Właściwości systemu mogą również powodować kolizje nazw, które mogą skutkować niezdefiniowanym zachowaniem w systemie (jak również etykietowaniem SELinux). Kolizje między etykietami platformy i dostawcy mogą wystąpić w przypadku dowolnego obiektu posiadającego etykietę SELinux, w tym właściwości, usług, procesów, plików i gniazd. Aby uniknąć tych problemów, należy jasno określić własność tych obiektów.

Oprócz kolizji etykiet, nazwy typów/atrybutów SELinux mogą również kolidować. Kolizja nazwy typu/atrybutu zawsze spowoduje błąd kompilatora strategii.

Przestrzeń nazw typu/atrybutu

SELinux nie pozwala na wielokrotne deklaracje tego samego typu/atrybutu. Polisa ze zduplikowanymi deklaracjami nie zostanie skompilowana. Aby uniknąć kolizji nazw typów i atrybutów, wszystkie deklaracje dostawców powinny mieć przestrzeń nazw zaczynającą się od np_ .

type foo, domain; → type np_foo, domain;

Własność właściwości systemu i etykietowanie procesów

Unikanie kolizji etykiet najlepiej rozwiązać za pomocą przestrzeni nazw właściwości. Aby łatwo zidentyfikować właściwości platformy i uniknąć konfliktów nazw podczas zmiany nazwy lub dodawania właściwości wyeksportowanej platformy, upewnij się, że wszystkie właściwości dostawcy mają własne przedrostki:

Typ nieruchomości Dopuszczalne przedrostki
właściwości kontrolne ctl.vendor.
ctl.start$vendor.
ctl.stop$vendor.
init.svc.vendor.
do odczytu i zapisu vendor.
tylko czytać ro.vendor.
ro.boot.
ro.hardware.
uporczywy persist.vendor.

Dostawcy mogą nadal używać ro.boot.* (pochodzącego z wiersza poleceń jądra) i ro.hardware.* (oczywista właściwość związana ze sprzętem).

Wszystkie usługi dostawcy w plikach init rc powinny mieć vendor. dla usług w plikach init rc partycji niesystemowych. Podobne zasady obowiązują w przypadku etykiet SELinux dla właściwości dostawcy ( vendor_ dla właściwości dostawcy).

Własność pliku

Zapobieganie kolizjom plików jest trudne, ponieważ zasady platformy i dostawcy zwykle zapewniają etykiety dla wszystkich systemów plików. W przeciwieństwie do nazewnictwa typów, przestrzenie nazw plików nie są praktyczne, ponieważ wiele z nich jest tworzonych przez jądro. Aby zapobiec takim kolizjom, postępuj zgodnie ze wskazówkami dotyczącymi nazewnictwa systemów plików zawartymi w tej sekcji. W przypadku Androida 8.0 są to zalecenia bez wymagań technicznych. W przyszłości zalecenia te będą egzekwowane przez pakiet Vendor Test Suite (VTS).

System (/system)

Tylko obraz systemu musi zawierać etykiety dla komponentów /system poprzez file_contexts , service_contexts itp. Jeśli etykiety dla komponentów /system zostaną dodane w zasadach /vendor , aktualizacja OTA wyłącznie dla platformy może nie być możliwa.

Sprzedawca (/sprzedawca)

Polityka AOSP SELinux oznacza już części partycji vendor , z którymi platforma współdziała, co umożliwia pisanie reguł SELinux dla procesów platformy, aby mogły komunikować się i/lub uzyskiwać dostęp do części partycji vendor . Przykłady:

/vendor Etykieta dostarczana przez platformę Procesy platformy w zależności od etykiety
/vendor(/. * )? vendor_file Wszyscy klienci HAL w frameworku, ueventd itp.
/vendor/framework(/. * )? vendor_framework_file dex2oat , appdomain itp.
/vendor/app(/. * )? vendor_app_file dex2oat , installd , idmap itp.
/vendor/overlay(/. * ) vendor_overlay_file system_server , zygote , idmap itp.

W rezultacie należy przestrzegać określonych zasad (wymuszanych przez neverallows ) podczas etykietowania dodatkowych plików na partycji vendor :

  • vendor_file musi być domyślną etykietą dla wszystkich plików w partycji vendor . Zasady platformy wymagają tego, aby uzyskać dostęp do implementacji warstwy HAL z przekazywaniem.
  • Wszystkie nowe exec_types dodane do partycji vendor za pośrednictwem SEPolicy dostawcy muszą mieć atrybut vendor_file_type . Jest to egzekwowane poprzez Neverallows.
  • Aby uniknąć konfliktów z przyszłymi aktualizacjami platformy/frameworka, unikaj etykietowania plików innych niż exec_types na partycji vendor .
  • Wszystkie zależności bibliotek dla warstw HAL tego samego procesu zidentyfikowanych przez AOSP muszą być oznaczone etykietą ten same_process_hal_file.

Procfs (/proc)

Pliki w /proc mogą być oznaczone wyłącznie etykietą genfscon . W systemie Android 7.0 zarówno platforma , jak i zasady dostawcy używały genfscon do oznaczania plików w procfs .

Zalecenie: tylko etykiety zasad platformy /proc . Jeśli procesy vendor potrzebują dostępu do plików w /proc , które są obecnie oznaczone domyślną etykietą ( proc ), zasady dostawcy nie powinny jawnie ich oznaczać i zamiast tego powinny używać ogólnego typu proc w celu dodania reguł dla domen dostawców. Dzięki temu aktualizacje platformy będą uwzględniać przyszłe interfejsy jądra udostępniane przez procfs i oznaczać je w razie potrzeby jawnie.

Debugfs (/sys/kernel/debug)

Debugfs można oznaczyć zarówno w file_contexts , jak i genfscon . W Androidzie 7.0 do Androida 10 debugfs zarówno platformy, jak i etykiety dostawcy.

W systemie Android 11 nie można uzyskać dostępu debugfs ani ich montować na urządzeniach produkcyjnych. Producenci urządzeń powinni usunąć debugfs .

Tracefs (/sys/kernel/debug/tracing)

Tracefs można oznaczyć zarówno w file_contexts , jak i genfscon . W systemie Android 7.0 tylko platforma etykietuje tracefs .

Zalecenie: Tylko platforma może oznaczać tagi tracefs .

Sysfs (/sys)

Pliki w /sys mogą być oznaczone zarówno przy użyciu file_contexts , jak i genfscon . W systemie Android 7.0 zarówno platforma, jak i dostawca używają file_contexts i genfscon do oznaczania plików w sysfs .

Zalecenie: platforma może oznaczać węzły sysfs etykietami, które nie są specyficzne dla urządzenia. W przeciwnym razie tylko sprzedawca może oznaczać pliki.

tmpfs (/dev)

Pliki w /dev mogą być oznaczone w file_contexts . W systemie Android 7.0 znajdują się tutaj pliki etykiet platformy i dostawcy.

Zalecenie: Sprzedawca może oznaczać tylko pliki w /dev/vendor (np. /dev/vendor/foo , /dev/vendor/socket/bar ).

Rootfs (/)

Pliki w / mogą być oznaczone etykietą file_contexts . W systemie Android 7.0 znajdują się tutaj pliki etykiet platformy i dostawcy.

Zalecenie: Tylko system może oznaczać pliki w / .

Dane (/dane)

Dane są oznaczane za pomocą kombinacji file_contexts i seapp_contexts .

Zalecenie: Nie zezwalaj na etykietowanie dostawców poza /data/vendor . Tylko platforma może oznaczać inne części /data .

Atrybuty zgodności

Polityka SELinux to interakcja pomiędzy typami źródłowymi i docelowymi dla określonych klas obiektów i uprawnień. Każdy obiekt (procesy, pliki itp.), na który wpływa polityka SELinux, może mieć tylko jeden typ, ale typ ten może mieć wiele atrybutów.

Polityka jest pisana głównie w kategoriach istniejących typów:

allow source_type target_type:target_class permission(s);

To działa, ponieważ polityka została napisana z wiedzą wszelkiego rodzaju. Jeśli jednak zasady dostawcy i zasady platformy korzystają z określonych typów, a etykieta określonego obiektu zmieni się tylko w jednej z tych zasad, druga może zawierać zasady, do których wcześniej uzyskano lub utracono dostęp. Na przykład:

File_contexts:
/sys/A   u:object_r:sysfs:s0
Platform: allow p_domain sysfs:class perm;
Vendor: allow v_domain sysfs:class perm;

Można zmienić na:

File_contexts:
/sys/A   u:object_r:sysfs_A:s0

Chociaż zasady dostawcy pozostałyby takie same, domena v_domain utraciłaby dostęp z powodu braku zasad dla nowego typu sysfs_A .

Definiując politykę w kategoriach atrybutów, możemy nadać obiektowi bazowemu typ, który ma atrybut odpowiadający polityce zarówno dla platformy, jak i kodu dostawcy. Można to zrobić dla wszystkich typów, aby skutecznie utworzyć politykę atrybutów , w której konkretne typy nigdy nie są używane. W praktyce jest to wymagane tylko w przypadku tych części zasad, które nakładają się na platformę i dostawcę, które są zdefiniowane i udostępniane jako zasady publiczne platformy , które są budowane jako część zasad dostawcy.

Zdefiniowanie polityki publicznej jako atrybutów wersjonowanych spełnia dwa cele w zakresie zgodności zasad:

  • Upewnij się, że kod dostawcy nadal działa po aktualizacji platformy . Osiągnięto to poprzez dodanie atrybutów do konkretnych typów obiektów odpowiadających tym, na których opierał się kod dostawcy, zachowując dostęp.
  • Możliwość wycofania zasad . Osiąga się to poprzez jasne określenie zestawów polityk na atrybuty, które można usunąć, gdy tylko wersja, której odpowiadają, nie jest już obsługiwana. Rozwój platformy może być kontynuowany, wiedząc, że stare zasady są nadal obecne w zasadach dostawcy i zostaną automatycznie usunięte po aktualizacji.

Możliwość pisania polityki

Aby osiągnąć cel, jakim jest niewymaganie wiedzy o konkretnych zmianach wersji do opracowywania zasad, system Android 8.0 zawiera mapowanie między typami zasad publicznych platformy i ich atrybutami. Typ foo jest mapowany na atrybut foo_v N , gdzie N to docelowa wersja. vN odpowiada zmiennej kompilacji PLATFORM_SEPOLICY_VERSION i ma postać MM.NN , gdzie MM odpowiada numerowi zestawu SDK platformy, a NN to wersja specyficzna dla platformy.

Atrybuty w zasadach publicznych nie są wersjonowane, ale raczej istnieją jako interfejs API, na którym można zbudować zasady platformy i dostawcy, aby zapewnić stabilność interfejsu między dwiema partycjami. Zarówno twórcy zasad platformy, jak i dostawców mogą nadal tworzyć zasady w obecnej formie.

Polityka publiczna platformy wyeksportowana jako allow source_foo target_bar: class perm ; jest częścią polityki dostawcy. Podczas kompilacji (która obejmuje odpowiednią wersję) jest ona przekształcana w politykę, która trafi do części urządzenia dostarczonej przez dostawcę (przedstawiona w przekształconym języku Common Intermediate Language (CIL)):

 (allow source_foo_vN target_bar_vN (class (perm)))

Ponieważ zasady dostawców nigdy nie wyprzedzają platformy, nie powinny dotyczyć wcześniejszych wersji. Jednakże zasady platformy będą musiały wiedzieć, jak daleko sięgają zasady dostawcy, uwzględniać atrybuty dla ich typów i ustawiać zasady odpowiadające atrybutom wersjonowanym.

Różnice w zasadach

Automatyczne tworzenie atrybutów przez dodanie _v N na końcu każdego typu nic nie robi bez mapowania atrybutów na typy w różnych wersjach. Android utrzymuje mapowanie między wersjami atrybutów i mapowanie typów na te atrybuty. Odbywa się to w wyżej wymienionych plikach mapowania z instrukcjami takimi jak (CIL):

(typeattributeset foo_vN (foo))

Ulepszenia platformy

W poniższej sekcji szczegółowo opisano scenariusze uaktualnień platformy.

Te same typy

Ten scenariusz ma miejsce, gdy obiekt nie zmienia etykiet w wersjach zasad. To samo dotyczy typów źródłowych i docelowych i można je zobaczyć w przypadku /dev/binder , który we wszystkich wersjach jest oznaczony etykietą binder_device . W przekształconej polityce jest ona reprezentowana jako:

binder_device_v1 … binder_device_vN

Podczas aktualizacji z v1v2 polityka platformy musi zawierać:

type binder_device; -> (type binder_device) (in CIL)

W pliku mapowania v1 (CIL):

(typeattributeset binder_device_v1 (binder_device))

W pliku mapowania v2 (CIL):

(typeattributeset binder_device_v2 (binder_device))

W polityce dostawcy wersji 1 (CIL):

(typeattribute binder_device_v1)
(allow binder_device_v1 …)

W zasadach dostawcy wersji 2 (CIL):

(typeattribute binder_device_v2)
(allow binder_device_v2 …)
Nowe typy

Ten scenariusz ma miejsce, gdy platforma dodała nowy typ, co może się zdarzyć podczas dodawania nowych funkcji lub podczas wzmacniania zasad.

  • Nowa cecha . Gdy typ etykietuje obiekt, który wcześniej nie istniał (np. nowy proces serwisowy), kod dostawcy nie wchodził z nim wcześniej w bezpośrednią interakcję, więc nie istnieje odpowiednia polityka. Nowy atrybut odpowiadający typowi nie ma atrybutu w poprzedniej wersji, dlatego nie będzie potrzebny wpis w pliku mapowania dotyczącym tej wersji.
  • Zaostrzenie polityki . Gdy typ reprezentuje zaostrzanie polityki, nowy atrybut type musi łączyć się z łańcuchem atrybutów odpowiadającym poprzedniemu (podobnie jak w poprzednim przykładzie, w którym zmieniono /sys/A z sysfs na sysfs_A ). Kod dostawcy opiera się na regule umożliwiającej dostęp do sysfs i musi uwzględnić tę regułę jako atrybut nowego typu.

Podczas aktualizacji z v1v2 polityka platformy musi zawierać:

type sysfs_A; -> (type sysfs_A) (in CIL)
type sysfs; (type sysfs) (in CIL)

W pliku mapowania v1 (CIL):

(typeattributeset sysfs_v1 (sysfs sysfs_A))

W pliku mapowania v2 (CIL):

(typeattributeset sysfs_v2 (sysfs))
(typeattributeset sysfs_A_v2 (sysfs_A))

W polityce dostawcy wersji 1 (CIL):

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

W zasadach dostawcy wersji 2 (CIL):

(typeattribute sysfs_A_v2)
(allow … sysfs_A_v2 …)
(typeattribute sysfs_v2)
(allow … sysfs_v2 …)
Usunięte typy

Ten (rzadki) scenariusz ma miejsce, gdy typ zostanie usunięty, co może się zdarzyć, gdy obiekt bazowy:

  • Pozostaje, ale otrzymuje inną etykietę.
  • Jest usuwany przez platformę.

Podczas luzowania polityki typ jest usuwany, a obiekt oznaczony tym typem otrzymuje inną, już istniejącą etykietę. Oznacza to połączenie mapowań atrybutów: kod dostawcy musi nadal mieć dostęp do obiektu bazowego za pomocą atrybutu, który posiadał, ale reszta systemu musi teraz mieć dostęp do obiektu za pomocą nowego atrybutu.

Jeżeli atrybut, na który został przełączony, jest nowy, to ponowne etykietowanie przebiega tak samo, jak w przypadku nowego typu, z tą różnicą, że w przypadku użycia istniejącej etykiety, dodanie starego atrybutu nowego typu spowodowałoby, że inne obiekty również zostałyby oznaczone tym typem być nowo dostępnym. Zasadniczo jest to wykonywane przez platformę i uważa się, że jest to akceptowalny kompromis w celu utrzymania kompatybilności.

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Przykładowa wersja 1: Zwijanie typów (usuwanie sysfs_A)

Podczas aktualizacji z v1v2 polityka platformy musi zawierać:

type sysfs; (type sysfs) (in CIL)

W pliku mapowania v1 (CIL):

(typeattributeset sysfs_v1 (sysfs))
(type sysfs_A) # in case vendors used the sysfs_A label on objects
(typeattributeset sysfs_A_v1 (sysfs sysfs_A))

W pliku mapowania v2 (CIL):

(typeattributeset sysfs_v2 (sysfs))

W polityce dostawcy wersji 1 (CIL):

(typeattribute sysfs_A_v1)
(allow … sysfs_A_v1 …)
(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

W zasadach dostawcy wersji 2 (CIL):

(typeattribute sysfs_v2)
(allow … sysfs_v2 …)

Przykładowa wersja 2: Całkowite usunięcie (typ foo)

Podczas aktualizacji z v1v2 polityka platformy musi zawierać:

# nothing - we got rid of the type

W pliku mapowania v1 (CIL):

(type foo) #needed in case vendors used the foo label on objects
(typeattributeset foo_v1 (foo))

W pliku mapowania v2 (CIL):

# nothing - get rid of it

W polityce dostawcy wersji 1 (CIL):

(typeattribute foo_v1)
(allow foo …)
(typeattribute sysfs_v1)
(allow sysfs_v1 …)

W zasadach dostawcy wersji 2 (CIL):

(typeattribute sysfs_v2)
(allow sysfs_v2 …)
Nowa klasa/uprawnienia

Ten scenariusz ma miejsce, gdy aktualizacja platformy wprowadza nowe składniki zasad, które nie istnieją w poprzednich wersjach. Na przykład, gdy system Android dodał menedżera obiektów servicemanager , który utworzył uprawnienia dodawania, wyszukiwania i wyświetlania listy, demony dostawców chcące zarejestrować się w servicemanager potrzebowały uprawnień, które nie były dostępne. W systemie Android 8.0 tylko zasady platformy mogą dodawać nowe klasy i uprawnienia.

Aby wszystkie domeny, które mogły zostać utworzone lub rozszerzone na podstawie zasad dostawcy, mogły bez przeszkód korzystać z nowej klasy, zasady platformy muszą zawierać regułę podobną do:

allow {domain -coredomain} *:new_class perm;

Może to nawet wymagać polityki zezwalającej na dostęp dla wszystkich typów interfejsów (polityki publicznej), aby mieć pewność, że obraz dostawcy uzyska dostęp. Jeśli skutkuje to nieakceptowalną polityką bezpieczeństwa (jak to może mieć miejsce w przypadku zmian w menedżerze usług), potencjalnie może zostać wymuszona aktualizacja dostawcy.

Usunięto klasę/uprawnienia

Ten scenariusz ma miejsce, gdy menedżer obiektów zostanie usunięty (taki jak menedżer obiektów ZygoteConnection ) i nie powinien powodować problemów. Klasa i uprawnienia menedżera obiektów mogą pozostać zdefiniowane w zasadach, dopóki wersja dostawcy nie będzie już ich używać. Odbywa się to poprzez dodanie definicji do odpowiedniego pliku mapowania.

Dostosowanie dostawcy do nowych/zmienionych typów

Nowe typy dostawców stanowią podstawę opracowywania zasad dostawców, ponieważ są potrzebni do opisywania nowych procesów, plików binarnych, urządzeń, podsystemów i przechowywanych danych. W związku z tym konieczne jest umożliwienie tworzenia typów zdefiniowanych przez dostawcę.

Ponieważ zasady dostawcy są zawsze najstarsze na urządzeniu, nie ma potrzeby automatycznego konwertowania wszystkich typów dostawców na atrybuty w zasadach. Platforma nie opiera się na niczym określonym w zasadach dostawcy, ponieważ nie ma o tym wiedzy; jednakże platforma zapewni atrybuty i typy publiczne, których używa do interakcji z obiektami oznaczonymi tymi typami (takimi jak domain , sysfs_type itp.). Aby platforma w dalszym ciągu poprawnie współdziałała z tymi obiektami, należy odpowiednio zastosować atrybuty i typy, a do dostosowywalnych domen konieczne może być dodanie określonych reguł (takich jak init ).

Zmiany atrybutów dla Androida 9

Urządzenia aktualizujące się do Androida 9 mogą korzystać z następujących atrybutów, ale urządzenia uruchamiane z Androidem 9 nie mogą.

Atrybuty naruszającego

Android 9 zawiera następujące atrybuty związane z domeną:

  • data_between_core_and_vendor_violators . Atrybut dla wszystkich domen, które naruszają wymóg nieudostępniania plików według ścieżki pomiędzy vendor a coredomains . Procesy platformy i dostawcy nie powinny używać plików na dysku do komunikacji (niestabilny ABI). Rekomendacje:
    • Kod dostawcy powinien używać /data/vendor .
    • System nie powinien używać /data/vendor .
  • system_executes_vendor_violators . Atrybut dla wszystkich domen systemowych (z wyjątkiem domen init i shell domains ), które naruszają wymóg niewykonywania plików binarnych dostawcy. Wykonywanie plików binarnych dostawcy ma niestabilny interfejs API. Platforma nie powinna bezpośrednio wykonywać plików binarnych dostawcy. Rekomendacje:
    • Takie zależności platformy od plików binarnych dostawcy muszą znajdować się za warstwami HIDL HAL.

      LUB

    • coredomains , które wymagają dostępu do plików binarnych dostawcy, powinny zostać przeniesione na partycję dostawcy i w ten sposób przestaną być coredomain .

Niezaufane atrybuty

Niezaufane aplikacje przechowujące dowolny kod nie powinny mieć dostępu do usług HwBinder, z wyjątkiem tych, które są uważane za wystarczająco bezpieczne, aby można było uzyskać do nich dostęp z poziomu takich aplikacji (patrz bezpieczne usługi poniżej). Dwa główne powody tego stanu rzeczy to:

  1. Serwery HwBinder nie przeprowadzają uwierzytelniania klienta, ponieważ HIDL obecnie nie ujawnia informacji UID osoby dzwoniącej. Nawet jeśli HIDL rzeczywiście ujawnił takie dane, wiele usług HwBinder albo działa na poziomie niższym niż aplikacje (takie jak HAL), albo nie może polegać na tożsamości aplikacji przy autoryzacji. Zatem dla bezpieczeństwa domyślnie przyjmuje się założenie, że każdy serwis HwBinder traktuje wszystkich swoich klientów jako jednakowo uprawnionych do wykonywania operacji oferowanych przez usługę.
  2. Serwery HAL (podzbiór usług HwBinder) zawierają kod, w przypadku którego występuje wyższy wskaźnik problemów związanych z bezpieczeństwem niż komponenty system/core i mają dostęp do niższych warstw stosu (aż do sprzętu), zwiększając w ten sposób możliwości ominięcia modelu bezpieczeństwa Androida .

Bezpieczne usługi

Bezpieczne usługi obejmują:

  • same_process_hwservice . Usługi te (z definicji) działają w procesie klienta i dlatego mają taki sam dostęp jak domena klienta, w której działa proces.
  • coredomain_hwservice . Usługi te nie stwarzają ryzyka związanego z powodem nr 2.
  • hal_configstore_ISurfaceFlingerConfigs . Ta usługa jest specjalnie zaprojektowana do użytku przez dowolną domenę.
  • hal_graphics_allocator_hwservice . Operacje te są również oferowane przez usługę surfaceflinger Binder, do której aplikacje mają dostęp.
  • hal_omx_hwservice . To jest wersja HwBinder usługi mediacodec Binder, do której aplikacje mają dostęp.
  • hal_codec2_hwservice . To jest nowsza wersja hal_omx_hwservice .

Użyteczne atrybuty

Wszystkie hwservices , które nie są uważane za bezpieczne, mają atrybut untrusted_app_visible_hwservice . Odpowiednie serwery HAL mają atrybut untrusted_app_visible_halserver . Urządzenia uruchamiane z systemem Android 9 NIE MOGĄ używać żadnego untrusted atrybutu.

Rekomendacje:

  • Zamiast tego niezaufane aplikacje powinny komunikować się z usługą systemową, która komunikuje się z dostawcą HIDL HAL. Na przykład aplikacje mogą komunikować się z binderservicedomain , następnie mediaserver (który jest binderservicedomain ) z kolei komunikuje się z hal_graphics_allocator .

    LUB

  • Aplikacje wymagające bezpośredniego dostępu do warstw HAL vendor powinny mieć własną domenę sepolicy zdefiniowaną przez dostawcę.

Testy atrybutów plików

Android 9 zawiera testy czasu kompilacji , które zapewniają, że wszystkie pliki w określonych lokalizacjach mają odpowiednie atrybuty (np. wszystkie pliki w sysfs mają wymagany atrybut sysfs_type ).

Platforma-polityka publiczna

Polityka publiczna platformy jest podstawą dostosowania się do modelu architektury Androida 8.0 bez prostego utrzymywania połączenia zasad platformy z wersji 1 i 2. Dostawcy są narażeni na podzbiór zasad platformy, który zawiera przydatne typy i atrybuty oraz reguły dotyczące tych typów i atrybutów, które następnie stają się częścią zasad dostawców (tj. vendor_sepolicy.cil ).

Typy i reguły są automatycznie tłumaczone w zasadach generowanych przez dostawcę na attribute_v N , tak że wszystkie typy dostarczone przez platformę są atrybutami wersjonowanymi (jednak atrybuty nie są wersjonowane). Platforma jest odpowiedzialna za mapowanie konkretnych typów, które udostępnia, na odpowiednie atrybuty, aby zapewnić dalsze działanie zasad dostawcy i uwzględnienie reguł przewidzianych dla konkretnej wersji. Połączenie zasad platformy i zasad dotyczących dostawców spełnia cel modelu architektury Androida 8.0, jakim jest umożliwienie tworzenia niezależnych platform i dostawców.

Mapowanie do łańcuchów atrybutów

W przypadku używania atrybutów do mapowania na wersje zasad typ jest odwzorowywany na atrybut lub wiele atrybutów, zapewniając dostępność obiektów oznaczonych danym typem za pośrednictwem atrybutów odpowiadających ich poprzednim typom.

Utrzymywanie celu polegającego na ukryciu informacji o wersji przed twórcą strategii oznacza automatyczne generowanie atrybutów wersjonowanych i przypisywanie ich do odpowiednich typów. W typowym przypadku typów statycznych jest to proste: type_foo odwzorowuje type_foo_v1 .

W przypadku zmiany etykiety obiektu, takiej jak sysfssysfs_A lub mediaserveraudioserver , utworzenie takiego mapowania nie jest trywialne (i zostało opisane w powyższych przykładach). Opiekunowie zasad platformy muszą określić, w jaki sposób utworzyć mapowanie w punktach przejścia obiektów, co wymaga zrozumienia relacji między obiektami i przypisanymi im etykietami oraz określenia, kiedy to nastąpi. Aby zapewnić kompatybilność wsteczną, tą złożonością należy zarządzać po stronie platformy, która jest jedyną partycją, która może zostać poprawiona.

Aktualizacja wersji

Dla uproszczenia platforma Android wydaje wersję sepolicy po wycięciu nowej gałęzi wydania. Jak opisano powyżej, numer wersji jest zawarty w PLATFORM_SEPOLICY_VERSION i ma postać MM.nn , gdzie MM odpowiada wartości SDK, a nn jest wartością prywatną utrzymywaną w /platform/system/sepolicy. Na przykład 19.0 dla KitKat, 21.0 dla Lollipop, 22.0 dla Lollipop-MR1 23.0 dla Marshmallow, 24.0 dla Nougat, 25.0 dla Nougat-MR1, 26.0 dla Oreo, 27.0 dla Oreo-MR1 i 28.0 dla Androida 9. Zwiększenia obrotów nie są zawsze liczby całkowite. Na przykład, jeśli zmiana MR na wersję wymaga niezgodnej zmiany w system/sepolicy/public , ale nie zmiany API, wówczas ta wersja sepolicy może być: vN.1 . Wersja dostępna w gałęzi rozwojowej to wersja, której nigdy nie należy używać w urządzeniach wysyłkowych 10000.0 .

Android może wycofać najstarszą wersję podczas aktualizacji. Aby uzyskać informacje na temat tego, kiedy wycofać wersję, system Android może zebrać liczbę urządzeń objętych zasadami dostawcy, na których działa ta wersja Androida i które nadal otrzymują główne aktualizacje platformy. Jeśli liczba jest mniejsza niż określony próg, ta wersja jest przestarzała.

Wpływ wielu atrybutów na wydajność

Jak opisano w https://github.com/SELinuxProject/cil/issues/9 , duża liczba atrybutów przypisanych do typu powoduje problemy z wydajnością w przypadku pominięcia pamięci podręcznej zasad.

Potwierdzono, że jest to problem w systemie Android, dlatego w systemie Android 8.0 wprowadzono zmiany , aby usunąć atrybuty dodane do zasad przez kompilator zasad, a także usunąć nieużywane atrybuty. Zmiany te rozwiązały problem regresji wydajności.

Polityka publiczna System_ext i polityka publiczna produktu

Począwszy od systemu Android 11, partycje system_ext i partycje produktów mogą eksportować wyznaczone typy publiczne do partycji dostawcy. Podobnie jak zasady publiczne platformy, dostawca używa typów i reguł automatycznie tłumaczonych na atrybuty wersjonowane, np. z type na type_ N , gdzie N jest wersją platformy, dla której zbudowana jest partycja dostawcy.

Gdy partycje system_ext i produktu są oparte na tej samej platformie w wersji N , system kompilacji generuje podstawowe pliki mapowania na system_ext/etc/selinux/mapping/ N .cil i product/etc/selinux/mapping/ N .cil , które zawierają tożsamość mapowania z type na type_ N . Dostawca może uzyskać dostęp do type za pomocą wersjonowanego atrybutu type_ N .

W przypadku, gdy zaktualizowane zostaną tylko partycje system_ext i partycje produktu, powiedzmy N do N+1 (lub później), podczas gdy sprzedawca pozostanie na N , sprzedawca może utracić dostęp do typów partycji system_ext i produktu. Aby zapobiec uszkodzeniom, partycje system_ext i partycje produktu powinny udostępniać pliki mapujące konkretne typy na atrybuty type_ N Każdy partner jest odpowiedzialny za utrzymanie plików mapowania, jeśli zamierza wspierać N dostawców z N+1 (lub nowszymi) partycjami system_ext i produktu.

W tym celu od partnerów oczekuje się:

  1. Skopiuj wygenerowane podstawowe pliki mapowania z N partycji system_ext i partycji produktu do ich drzewa źródłowego.
  2. W razie potrzeby zmień pliki mapowania.
  3. Zainstaluj pliki mapowania na partycjach N+1 (lub nowszych) system_ext i partycjach produktu.

Załóżmy na przykład, że N system_ext ma jeden typ publiczny o nazwie foo_type . Następnie system_ext/etc/selinux/mapping/ N .cil w N partycji system_ext będzie wyglądać następująco:

(typeattributeset foo_type_N (foo_type))
(expandtypeattribute foo_type_N true)
(typeattribute foo_type_N)

Jeśli bar_type zostanie dodany do N+1 system_ext i jeśli bar_type powinien zostać zmapowany na foo_type dla N dostawcy, N .cil można zaktualizować z

(typeattributeset foo_type_N (foo_type))

Do

(typeattributeset foo_type_N (foo_type bar_type))

a następnie zainstalowany na partycji N+1 system_ext. Dostawca N może nadal uzyskiwać dostęp do foo_type i bar_type N+1 system_ext.

SELinux kontekstuje etykietowanie

Aby ułatwić rozróżnienie między polityką platformy i dostawcy, system buduje pliki kontekstowe SELinux w różny sposób, aby zachować je oddzielnie.

Konteksty plików

W Androidzie 8.0 wprowadzono następujące zmiany dla file_contexts :

  • Aby uniknąć dodatkowego obciążenia związanego z kompilacją na urządzeniu podczas rozruchu, file_contexts przestaje istnieć w formie binarnej. Zamiast tego są czytelnymi plikami tekstowymi wyrażeń regularnych, takimi jak {property, service}_contexts (tak jak były przed wersją 7.0).
  • file_contexts jest podzielony pomiędzy dwa pliki:
    • plat_file_contexts
      • file_context platformy Android, który nie ma etykiet specyficznych dla urządzenia, z wyjątkiem etykietowania części partycji /vendor , które muszą być dokładnie oznaczone, aby zapewnić prawidłowe działanie plików sepolicy.
      • Musi znajdować się na partycji system w /system/etc/selinux/plat_file_contexts na urządzeniu i być ładowany przez init na początku wraz z file_context dostawcy.
    • vendor_file_contexts
      • file_context specyficzny dla urządzenia zbudowany poprzez połączenie file_contexts znalezionych w katalogach wskazanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
      • Musi być zainstalowany w /vendor/etc/selinux/vendor_file_contexts w partycji vendor i ładowany przez init na początku wraz z platformą file_context .

Konteksty własności

W systemie Android 8.0 property_contexts jest podzielona pomiędzy dwa pliki:

  • plat_property_contexts
    • property_context platformy Android, który nie ma etykiet specyficznych dla urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/plat_property_contexts i być ładowany przez init na początku wraz z właściwością dostawcy property_contexts .
  • vendor_property_contexts
    • property_context specyficzny dla urządzenia zbudowany poprzez połączenie property_contexts znalezionych w katalogach wskazanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się w partycji vendor w /vendor/etc/selinux/vendor_property_contexts i być ładowany przez init na początku wraz z platformą property_context

Konteksty usług

W Androidzie 8.0 service_contexts jest podzielony pomiędzy następujące pliki:

  • plat_service_contexts
    • service_context specyficzny dla platformy Android dla servicemanager . service_context nie ma etykiet specyficznych dla urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/plat_service_contexts i być ładowany przez servicemanager na początku wraz z usługą dostawcy service_contexts .
  • vendor_service_contexts
    • service_context specyficzny dla urządzenia zbudowany poprzez połączenie service_contexts znalezionych w katalogach wskazanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się w partycji vendor pod adresem /vendor/etc/selinux/vendor_service_contexts i być ładowany przez servicemanager na początku wraz z platformą service_contexts .
    • Chociaż servicemanager szuka tego pliku podczas uruchamiania, w przypadku w pełni zgodnego urządzenia TREBLE vendor_service_contexts NIE MOŻE istnieć. Dzieje się tak dlatego, że wszelka interakcja pomiędzy vendor a procesami system MUSI przechodzić przez hwservicemanager / hwbinder .
  • plat_hwservice_contexts
    • Platforma Android hwservice_context dla hwservicemanager , która nie ma etykiet specyficznych dla urządzenia.
    • Musi znajdować się na partycji system pod adresem /system/etc/selinux/plat_hwservice_contexts i być ładowany przez hwservicemanager na początku wraz z vendor_hwservice_contexts .
  • vendor_hwservice_contexts
    • hwservice_context specyficzny dla urządzenia zbudowany poprzez połączenie hwservice_contexts znalezionych w katalogach wskazanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się na partycji vendor pod adresem /vendor/etc/selinux/vendor_hwservice_contexts i być ładowany przez hwservicemanager na początku wraz z plat_service_contexts .
  • vndservice_contexts
    • service_context specyficzny dla urządzenia dla vndservicemanager zbudowany poprzez połączenie vndservice_contexts znalezionych w katalogach wskazanych przez BOARD_SEPOLICY_DIRS w Boardconfig.mk urządzenia.
    • Plik ten musi znajdować się na partycji vendor w /vendor/etc/selinux/vndservice_contexts i być ładowany przez vndservicemanager na początku.

Konteksty Seappa

W systemie Android 8.0 seapp_contexts jest podzielony pomiędzy dwa pliki:

  • plat_seapp_contexts
    • seapp_context platformy Android, która nie zawiera zmian specyficznych dla urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • Specyficzne dla urządzenia rozszerzenie platformy seapp_context zbudowane poprzez połączenie seapp_contexts znalezionych w katalogach wskazanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się na partycji vendor pod adresem /vendor/etc/selinux/vendor_seapp_contexts .

Uprawnienia MAC

W systemie Android 8.0 mac_permissions.xml jest podzielony na dwa pliki:

  • Platforma mac_permissions.xml
    • Platforma Android mac_permissions.xml , która nie zawiera zmian specyficznych dla urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/.
  • Nieplatformowy plik mac_permissions.xml
    • Rozszerzenie specyficzne dla urządzenia dla platformy mac_permissions.xml zbudowane z mac_permissions.xml znalezionego w katalogach wskazanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się na partycji vendor w /vendor/etc/selinux/.