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 dostawców, aby umożliwić dostawcom utworzenie pliku zasad dostawcy, który w połączeniu z zasadami dostarczonymi przez platformę daje 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 są stosowane do 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 partycjivendor
. Zasady platformy wymagają tego, aby uzyskać dostęp do implementacji warstwy HAL z przekazywaniem. - Wszystkie nowe
exec_types
dodane do partycjivendor
za pośrednictwem SEPolicy dostawcy muszą mieć atrybutvendor_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 partycjivendor
. - 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 v1
→ v2
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
zsysfs
nasysfs_A
). Kod dostawcy opiera się na regule umożliwiającej dostęp dosysfs
i musi uwzględnić tę regułę jako atrybut nowego typu.
Podczas aktualizacji z v1
→ v2
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 v1
→ v2
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 v1
→ v2
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 Androidzie 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 nadal poprawnie współdziałała z tymi obiektami, atrybuty i typy muszą zostać odpowiednio zastosowane, a do konfigurowalnych 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ędzyvendor
acoredomains
. 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
.
- Kod dostawcy powinien używać
-
system_executes_vendor_violators
. Atrybut dla wszystkich domen systemowych (z wyjątkiem domeninit
ishell 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
.
- Takie zależności platformy od plików binarnych dostawcy muszą znajdować się za warstwami HIDL HAL.
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:
- 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ę.
- 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ługimediacodec
Binder, do której aplikacje mają dostęp. -
hal_codec2_hwservice
. To jest nowsza wersjahal_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ępniemediaserver
(który jestbinderservicedomain
) z kolei komunikuje się zhal_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 sysfs
→ sysfs_A
lub mediaserver
→ audioserver
, 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ę:
- Skopiuj wygenerowane podstawowe pliki mapowania z
N
partycji system_ext i partycji produktu do ich drzewa źródłowego. - W razie potrzeby zmień pliki mapowania.
- 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 kompilacji 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 przezinit
na początku wraz zfile_context
dostawcy.
-
-
vendor_file_contexts
-
file_context
specyficzny dla urządzenia zbudowany poprzez połączeniefile_contexts
znalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi być zainstalowany w
/vendor/etc/selinux/vendor_file_contexts
w partycjivendor
i ładowany przezinit
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 przezinit
na początku wraz z właściwością dostawcyproperty_contexts
.
-
-
vendor_property_contexts
-
property_context
specyficzny dla urządzenia zbudowany poprzez połączenieproperty_contexts
znalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi znajdować się w partycji
vendor
w/vendor/etc/selinux/vendor_property_contexts
i być ładowany przezinit
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 dlaservicemanager
.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 przezservicemanager
na początku wraz z usługą dostawcyservice_contexts
.
-
-
vendor_service_contexts
-
service_context
specyficzny dla urządzenia zbudowany poprzez połączenieservice_contexts
znalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi znajdować się w partycji
vendor
pod adresem/vendor/etc/selinux/vendor_service_contexts
i być ładowany przezservicemanager
na początku wraz z platformąservice_contexts
. - Chociaż
servicemanager
szuka tego pliku podczas uruchamiania, w przypadku w pełni zgodnego urządzeniaTREBLE
vendor_service_contexts
NIE MOŻE istnieć. Dzieje się tak dlatego, że wszelka interakcja pomiędzyvendor
a procesamisystem
MUSI przechodzić przezhwservicemanager
/hwbinder
.
-
-
plat_hwservice_contexts
- Platforma Android
hwservice_context
dlahwservicemanager
, 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 przezhwservicemanager
na początku wraz zvendor_hwservice_contexts
.
- Platforma Android
-
vendor_hwservice_contexts
-
hwservice_context
specyficzny dla urządzenia zbudowany poprzez połączeniehwservice_contexts
znalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi znajdować się na partycji
vendor
pod adresem/vendor/etc/selinux/vendor_hwservice_contexts
i być ładowany przezhwservicemanager
na początku wraz zplat_service_contexts
.
-
-
vndservice_contexts
-
service_context
specyficzny dla urządzenia dlavndservicemanager
zbudowany poprzez połączenievndservice_contexts
znalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRS
wBoardconfig.mk
urządzenia. - Plik ten musi znajdować się na partycji
vendor
w/vendor/etc/selinux/vndservice_contexts
i być ładowany przezvndservicemanager
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łączenieseapp_contexts
znalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi znajdować się na partycji
vendor
pod adresem/vendor/etc/selinux/vendor_seapp_contexts
.
- Specyficzne dla urządzenia rozszerzenie platformy
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/.
- Platforma Android
- Nieplatformowy plik
mac_permissions.xml
- Rozszerzenie specyficzne dla urządzenia dla platformy
mac_permissions.xml
zbudowane zmac_permissions.xml
znalezionego w katalogach wskazanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi znajdować się na partycji
vendor
w/vendor/etc/selinux/.
- Rozszerzenie specyficzne dla urządzenia dla platformy