Z tego artykułu dowiesz się, jak Android obsługuje problemy ze zgodnością zasad w przypadku aktualizacji OTA platformy, w których nowe ustawienia SELinux platformy mogą się różnić od starych ustawień SELinux dostawcy.
Projektowanie zasad SELinux na podstawie Treble uwzględnia binarne rozróżnienie między zasadami platformy a dostawcy. Schemat staje się bardziej skomplikowany, jeśli partycje dostawcy generują zależności, takie jak platform
< vendor
< oem
.
W Androidzie 8.0 i nowszych polityka globalna SELinux jest podzielona na komponenty prywatne i publiczne. Komponenty publiczne to zasady i powiązana z nimi infrastruktura, które są dostępne w przypadku danej wersji platformy. Ta zasada będzie dostępna dla autorów zasad dostawców, aby umożliwić im tworzenie pliku zasad dostawcy, który w połączeniu z zasadami udostępnionymi przez platformę zapewni pełną funkcjonalność zasad na urządzeniu.
- W przypadku wersji wyeksportowane zasady publiczne platformy zostaną zapisane jako atrybuty.
- Aby ułatwić tworzenie zasad, w ramach procesu tworzenia zasad typy eksportowane zostaną przekształcone w atrybuty z wersją. Publiczne typy mogą być też używane bezpośrednio w decyzjach dotyczących etykietowania w plikach kontekstów dostawcy.
Android utrzymuje mapowanie między eksportowanymi typami konkretnych danych w zasadach dotyczących platformy a odpowiednimi atrybutami z wersją dla każdej wersji platformy. Dzięki temu, gdy obiekty są oznaczone typem, nie naruszają one zasad obowiązujących w danej platformie w poprzedniej wersji. Mapowanie jest aktualizowane przez utrzymywanie aktualnego pliku mapowania dla każdej wersji platformy, który zawiera informacje o przynależności atrybutu do każdego typu wyeksportowanego w zasadach publicznych.
Własność obiektu i oznaczanie
Podczas dostosowywania zasad w Androidzie w wersji 8.0 lub nowszej należy wyraźnie określić własność każdego obiektu, aby oddzielić zasady platformy od zasad dostawcy. Jeśli na przykład dostawca oznaczy element jako /dev/foo
, a platforma oznaczy go jako /dev/foo
w kolejnych aktualizacjach OTA, zachowanie będzie nieokreślone. W przypadku SELinux powoduje to kolizję etykiet. Węzeł urządzenia może mieć tylko jedną etykietę, która jest rozwiązywana do ostatniej zastosowanej etykiety. W rezultacie:
- Procesy, które potrzebują dostępu do etykiety zastosowanej bez powodzenia, stracą dostęp do zasobu.
- Procesy, które uzyskają dostęp do pliku, mogą się nie uruchomić, ponieważ utworzono niewłaściwy węzeł urządzenia.
Właściwości systemowe mogą też powodować kolizje nazw, które mogą skutkować nieokreślonym działaniem systemu (a także etykietowaniem SELinux). Kolizje między etykietami platformy i usługodawcy mogą wystąpić w przypadku dowolnego obiektu z etykietą SELinux, w tym usług, procesów, plików i gniazd. Aby uniknąć tych problemów, jasno określ własność tych obiektów.
Oprócz kolizji etykiet mogą też występować kolizje nazw typów/atrybutów SELinux. Kolizja nazw typu lub atrybutu zawsze powoduje błąd kompilatora zasad.
Nazewnictwo typów i atrybutów
SELinux nie zezwala na wielokrotne deklaracje tego samego typu/atrybutu. Kompilacja zasad z powtarzającymi się deklaracjami zakończy się niepowodzeniem. Aby uniknąć kolizji nazw typów i atrybutów, wszystkie deklaracje dostawców powinny być umieszczane w przestrzeni nazw zaczynającej się od vendor_
.
type foo, domain; → type vendor_foo, domain;
Własność etykietowania właściwości systemowych i procesów
Aby uniknąć kolizji etykiet, najlepiej użyć przestrzeni nazw właściwości. Aby łatwo identyfikować właściwości platformy i unikać konfliktów nazw podczas ich zmiany lub dodawania na platformach wyeksportowanych, upewnij się, że wszystkie właściwości dostawcy mają własne prefiksy:
Typ obiektu | Dopuszczalne prefiksy |
---|---|
właściwości kontrolne | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor.
|
odczyt i zapis | vendor. |
tylko do odczytu | ro.vendor. ro.boot. ro.hardware.
|
trwałe | persist.vendor. |
Dostawcy mogą nadal używać ro.boot.*
(który pochodzi z jądra cmdline) i ro.hardware.*
(czyli właściwości związanej z sprzętem).
Wszystkie usługi dostawcy w plikach init rc powinny mieć vendor.
w przypadku usług w plikach init rc w partycjach niesystemowych. Podobne reguły są stosowane do etykiet SELinux w usługach dostawców (vendor_
).
Własność pliku
Zapobieganie kolizjom plików jest trudne, ponieważ zarówno platformy, jak i dostawcy często udostępniają etykiety dla wszystkich systemów plików. W przeciwieństwie do nazewnictwa typów stosowanie nazw przestrzeni nazw plików nie jest praktyczne, ponieważ wiele z nich jest tworzonych przez jądro. Aby uniknąć takich kolizji, postępuj zgodnie ze wskazówkami dotyczącymi nazewnictwa systemów plików podanymi w tej sekcji. W przypadku Androida 8.0 są to zalecenia bez technicznego egzekwowania. W przyszłości te rekomendacje będą egzekwowane przez pakiet testów dostawcy (VTS).
System (/system)
Etykiety dla komponentów /system
do file_contexts
, service_contexts
itd. musi zawierać tylko obraz systemu. Jeśli etykiety dla komponentów /system
zostaną dodane w zasadach /vendor
, aktualizacja OTA tylko dla frameworku może okazać się niemożliwa.
Dostawca (/vendor)
Zasady SELinux w AOSP już oznaczają części partycji vendor
, z którymi platforma wchodzi w interakcje. Umożliwia to tworzenie reguł SELinux dla procesów platformy, aby mogły one komunikować się z częściami partycji vendor
lub uzyskiwać do nich dostęp. Przykłady:
Ścieżka elementu „/vendor ” |
Etykieta udostępniona przez platformę | Procesy platformy w zależności od etykiety |
---|---|---|
/vendor(/.*)?
|
vendor_file
|
Wszyscy klienci HAL w ramach, ueventd itd.
|
/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 związku z tym podczas etykietowania dodatkowych plików w partycji vendor
należy przestrzegać określonych reguł (przestrzeganych za pomocą neverallows
):
vendor_file
musi być domyślną etykietą wszystkich plików na partycjivendor
. Zasady platformy wymagają tego, aby uzyskać dostęp do implementacji przepustki HAL.- Wszystkie nowe
exec_types
dodane w partycjivendor
za pomocą SEPolicy dostawcy muszą mieć atrybutvendor_file_type
. Ta zasada jest egzekwowana za pomocą reguły neverallows. - Aby uniknąć konfliktów z przyszłymi aktualizacjami platformy lub platformy, nie etykietuj plików innych niż
exec_types
w partycjivendor
. - Wszystkie zależności bibliotek dla identyfikowanych przez AOSP interfejsów HAL dla tego samego procesu muszą być oznaczone jako
same_process_hal_file.
procfs (/proc)
Pliki w /proc
mogą być oznaczane tylko etykietą genfscon
. W Androidzie 7.0 zarówno platforma, jak i dostawca używają zasad genfscon
do oznaczania plików w procfs
.
Zalecenie: tylko etykiety zasad platformy /proc
.
Jeśli procesy vendor
wymagają dostępu do plików w /proc
, które są obecnie oznaczone etykietą domyślną (proc
), polityka dostawcy nie powinna ich wyraźnie oznaczać. Zamiast tego należy użyć ogólnego typu proc
, aby dodać reguły dla domen dostawcy. Dzięki temu aktualizacje platformy mogą uwzględniać przyszłe interfejsy jądra udostępniane przez procfs
i w razie potrzeby wyraźnie je oznaczać.
Debugfs (/sys/kernel/debug)
Debugfs
może być oznaczony w przypadku zarówno file_contexts
, jak i genfscon
. W Androidzie 7.0–10 obie etykiety: platformy i producentadebugfs
.
W Androidzie 11 nie można uzyskać dostępu do debugfs
ani zamontować go na urządzeniach produkcyjnych. Producenci urządzeń powinni usunąć debugfs
.
Tracefs (/sys/kernel/debug/tracing)
Tracefs
może być oznaczony w przypadku zarówno file_contexts
, jak i genfscon
. W Androidzie 7.0 tylko etykiety platformy.tracefs
Rekomendacja: tylko platforma może oznaczać tracefs
.
Sysfs (/sys)
Pliki w /sys
mogą być oznaczone etykietami file_contexts
i genfscon
. W Androidzie 7.0 zarówno platforma, jak i producent używają etykiety genfscon
do oznaczania plików w folderze sysfs
.
Rekomendacja: platforma może oznaczać etykietą sysfs
węzły, które nie są powiązane z konkretnym urządzeniem. W przeciwnym razie tylko dostawca może etykietować pliki.
tmpfs (/dev)
Pliki w folderze /dev
mogą mieć etykiety w folderze file_contexts
. W Androidzie 7.0 pliki etykiet platformy i usługodawcy.
Zalecenie: dostawca może oznaczać etykietami tylko pliki w /dev/vendor
(np. /dev/vendor/foo
, /dev/vendor/socket/bar
).
rootfs (/)
Pliki w folderze /
mogą mieć etykiety w folderze file_contexts
. W Androidzie 7.0 pliki etykiet platformy i dostawcy.
Zalecenie: tylko system może oznaczać pliki w /
.
Data (/data)
Dane są oznaczane za pomocą kombinacji atrybutów file_contexts
i seapp_contexts
.
Rekomendacja: nie zezwalaj na etykietowanie przez dostawcę poza /data/vendor
. Tylko platforma może oznaczać inne części /data
.
Wersja etykiet Genfs
Od poziomu interfejsu API dostawcy 202504 nowsze etykiety SELinux przypisane za pomocą genfscon
w system/sepolicy/compat/plat_sepolicy_genfs_{ver}.cil
są opcjonalne w przypadku starszych partycji dostawcy. Umożliwia to starszym partycjom dostawcy zachowanie dotychczasowej implementacji SEPolicy. Jest ona kontrolowana przez zmienną Makefile BOARD_GENFS_LABELS_VERSION
, która jest przechowywana w pliku /vendor/etc/selinux/genfs_labels_version.txt
.
Przykład:
-
Na poziomie interfejsu API dostawcy 202404 węzeł
/sys/class/udc
jest domyślnie oznaczony jakosysfs
. -
Od poziomu interfejsu API dostawcy 202504
/sys/class/udc
ma etykietęsysfs_udc
.
Jednak /sys/class/udc
może być używane przez partycje dostawcy korzystające z poziomu interfejsu API 202404, z domyślną etykietą sysfs
lub etykietą specyficzną dla dostawcy. Bezwarunkowe oznaczenie /sys/class/udc
jako sysfs_udc
może spowodować utratę zgodności z tymi partycjami dostawcy. Jeśli zaznaczysz BOARD_GENFS_LABELS_VERSION
, platforma będzie nadal używać poprzednich etykiet i uprawnień w przypadku starszych partycji dostawcy.
Wartość BOARD_GENFS_LABELS_VERSION
może być równa lub większa niż poziom interfejsu API dostawcy. Na przykład partycje dostawcy korzystające z poziomu interfejsu API 202404 mogą ustawić wartość BOARD_GENFS_LABELS_VERSION
na 202504, aby zastosować nowe etykiety wprowadzone w wersji 202504. Zobacz listę
etykiet genfs dla wersji 202504.
Podczas etykietowania węzłów genfscon
platforma musi wziąć pod uwagę starsze partycje dostawcy i w razie potrzeby zastosować mechanizmy zastępcze w celu zapewnienia zgodności. Platforma może używać bibliotek przeznaczonych tylko dla tej platformy do zapytania o wersję etykiet genfs.
-
W przypadku elementów natywnych użyj właściwości
libgenfslabelsversion
. Plik nagłówkalibgenfslabelsversion
znajdziesz w plikugenfslabelsversion.h
. -
W Javie użyj:
android.os.SELinux.getGenfsLabelsVersion()
.
Atrybuty zgodności
Zasady SELinux to interakcja między typami źródła i docelownika w przypadku określonych klas obiektów i uprawnień. Każdy obiekt (procesy, pliki itp.), na który mają wpływ zasady SELinux, może mieć tylko jeden typ, ale ten typ może mieć wiele atrybutów.
Zasady są sformułowane głównie w ujęciu istniejących typów:
allow source_type target_type:target_class permission(s);
To działa, ponieważ zasady zostały opracowane z uwzględnieniem wszystkich typów. Jeśli jednak zasady dostawcy i zasady platformy używają określonych typów, a etykieta konkretnego obiektu zmienia się tylko w jednej z tych zasad, druga może zawierać zasady, które uzyskały lub utraciły dostęp, na których wcześniej się opierano. 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 je zmienić na:
File_contexts: /sys/A u:object_r:sysfs_A:s0
Chociaż zasady dostawcy pozostaną takie same, v_domain
utraci dostęp z powodu braku zasad dotyczących nowego typu sysfs_A
Definiując zasady w terminach atrybutów, możemy nadać obiektowi bazowemu typ, który ma atrybut odpowiadający zasadom zarówno dla platformy, jak i kodu dostawcy. Można to zrobić w przypadku wszystkich typów, aby skutecznie utworzyć zasady dotyczące atrybutów, w których konkretne typy nigdy nie są używane. W praktyce jest to wymagane tylko w przypadku części zasad, które pokrywają się w przypadku platformy i dostawcy. Są one zdefiniowane i udostępniane jako zasady publiczne platformy, które są tworzone w ramach zasad dostawcy.
Zdefiniowanie publicznych zasad jako atrybutów z wersją spełnia 2 cele dotyczące zgodności z zasadami:
- Upewnij się, że kod dostawcy nadal działa po aktualizacji platformy. Osiągane przez dodawanie atrybutów do konkretnych typów obiektów odpowiadających tym, na których oparty jest kod dostawcy, z zachowaniem dostępu.
- Możliwość wycofania zasady. Osiąga się to poprzez wyraźne wyodrębnienie zbiorów zasad w atrybuty, które można usunąć, gdy tylko wersja, do której one pasują, przestanie być obsługiwana. Rozwój może być kontynuowany na platformie, ponieważ wiadomo, że stara zasada jest nadal obecna w zasadach dostawcy i zostanie automatycznie usunięta, gdy nastąpi uaktualnienie.
Możliwość zapisu zasad
Aby spełnić cel polegający na tym, że tworzenie zasad nie wymaga znajomości zmian w konkretnej wersji, Android 8.0 zawiera mapowanie typów zasad publicznych na platformie i ich atrybutów. Typ foo
jest mapowany na atrybut foo_vN
, gdzie N
to wersja docelowa. vN
odpowiada zmiennej kompilacji PLATFORM_SEPOLICY_VERSION
i ma postać MM.NN
, gdzie MM
odpowiada numerowi pakietu SDK platformy, a NN
to wersja platformy do konkretnej polityki bezpieczeństwa.
Atrybuty w publicznych zasadach nie są powiązane z wersją, ale występują jako interfejs API, na którym można budować zasady platformy i usługodawcy, aby utrzymać stabilność interfejsu między tymi dwoma obszarami. Zarówno platformy, jak i dostawcy mogą nadal pisać zasady w taki sposób, w jaki są one obecnie sformułowane.
Zasady publiczne platformy wyeksportowane jako allow source_foo target_bar:class
perm;
są uwzględnione w zasadach dostawcy. Podczas kompilacji (która obejmuje odpowiednią wersję) jest przekształcana w zasady, które zostaną przekazane do części dostawcy urządzenia (wyświetlane w przekształconym wspólnym języku pośrednim):
(allow source_foo_vN target_bar_vN (class (perm)))
Zasady dostawcy nigdy nie wyprzedzają platformy, więc nie powinny dotyczyć wcześniejszych wersji. Jednak zasady platformy muszą uwzględniać, jak daleko wstecz sięga polityka dostawcy, jakie atrybuty i typy atrybutów są uwzględnione oraz jakie zasady odpowiadają atrybutom z wersją.
Różnice w zasadach
Automatyczne tworzenie atrybutów przez dodanie _vN
na końcu każdego typu nie ma żadnego znaczenia bez mapowania atrybutów na typy w ramach różnic między wersjami. Android utrzymuje mapowanie wersji atrybutów oraz mapowanie typów na te atrybuty. Jest to realizowane w wymienionych wyżej plikach mapowania za pomocą instrukcji takich jak (CIL):
(typeattributeset foo_vN (foo))
Aktualizacje platformy
W sekcji poniżej znajdziesz szczegółowe informacje o scenariuszach uaktualniania platformy.
Takie same typy
Ten scenariusz występuje, gdy obiekt nie zmienia etykiet w wersjach zasad.
Jest to takie samo w przypadku typów źródeł i docelowo. Można to zobaczyć w przypadku /dev/binder
, który jest oznaczony jako binder_device
we wszystkich wersjach. W przekształconej polityce jest on reprezentowany jako:
binder_device_v1 … binder_device_vN
W przypadku przejścia z poziomu v1
na v2
zasady platformy muszą 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 zasadach dostawcy w wersji 1 (CIL):
(typeattribute binder_device_v1) (allow binder_device_v1 …)
W zasadach dostawcy w wersji 2 (CIL):
(typeattribute binder_device_v2) (allow binder_device_v2 …)
Nowe typy
Ten scenariusz występuje, gdy platforma doda nowy typ, co może się zdarzyć podczas dodawania nowych funkcji lub wzmacniania zasad.
- Nowa funkcja. Jeśli typ oznacza obiekt, który wcześniej nie istniał (np. nowy proces usługi), kod dostawcy nie był wcześniej z nim bezpośrednio powiązany, więc nie ma odpowiednich zasad. Nowy atrybut odpowiadający temu typowi nie ma atrybutu w poprzedniej wersji, więc nie wymaga wpisu w pliku mapowania kierowanym na tę wersję.
- Wzmacnianie zasad. Gdy typ reprezentuje zaostrzenie zasad, nowy atrybut typu musi wskazywać na łańcuch atrybutów odpowiadających poprzedniemu (podobnie jak w poprzednim przykładzie, w którym wartość
/sys/A
została zmieniona zsysfs
nasysfs_A
). Kod dostawcy opiera się na regule umożliwiającej dostęp do atrybutusysfs
i musi zawierać tę regułę jako atrybut nowego typu.
W przypadku przejścia z poziomu v1
na v2
zasady platformy muszą 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 zasadach dostawcy w wersji 1 (CIL):
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
W zasadach dostawcy w wersji 2 (CIL):
(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)
Typy usunięte
Ten (rzadki) scenariusz występuje, gdy usuwany jest typ, co może się zdarzyć, gdy obiekt źródłowy:
- Pozostanie, ale otrzyma inną etykietę.
- został usunięty przez platformę;
Podczas łagodzenia zasad dany typ jest usuwany, a obiekt oznaczony tym typem otrzymuje inną, już istniejącą etykietę. Jest to przykład scalania mapowań atrybutów: kod dostawcy musi nadal mieć dostęp do obiektu podstawowego za pomocą atrybutu, który był używany wcześniej, ale reszta systemu musi teraz mieć dostęp do obiektu za pomocą nowego atrybutu.
Jeśli atrybut, na który została przełączona etykieta, jest nowy, zmiana etykiety przebiega tak samo jak w przypadku nowego typu, z tym że gdy używana jest istniejąca etykieta, dodanie nowego typu starego atrybutu spowoduje, że inne obiekty z tą etykietą również staną się dostępne. Platforma robi to właśnie w podstawie, co jest akceptowalną kompromisem w celu zachowania zgodności.
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
Przykład wersji 1: upatrywanie typów (usuwanie sysfs_A)
W przypadku przejścia z poziomu v1
na v2
zasady platformy muszą 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 zasadach dostawcy w wersji 1 (CIL):
(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)
W zasadach dostawcy w wersji 2 (CIL):
(typeattribute sysfs_v2) (allow … sysfs_v2 …)
Przykład wersji 2: usuwanie całkowicie (typ foo)
W przypadku przejścia z poziomu v1
na v2
zasady platformy muszą 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 zasadach dostawcy w wersji 1 (CIL):
(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)
W zasadach dostawcy w wersji 2 (CIL):
(typeattribute sysfs_v2) (allow sysfs_v2 …)
Nowe zajęcia lub uprawnienia
Ten scenariusz ma miejsce, gdy uaktualnienie platformy wprowadza nowe komponenty zasad, które nie występują w poprzednich wersjach. Gdy na przykład Android dodał menedżera obiektów servicemanager
, który utworzył uprawnienia do dodawania, wyszukiwania i wyświetlania, demony dostawców, które chcą się zarejestrować w servicemanager
, potrzebowały uprawnień, których nie było. W Androidzie 8.0 tylko zasady platformy mogą dodawać nowe klasy i uprawnienia.
Aby umożliwić wszystkim domenom, które mogły zostać utworzone lub rozszerzone przez zasady dostawcy, korzystanie z nowej klasy bez ograniczeń, zasada platformy musi zawierać regułę podobną do tej:
allow {domain -coredomain} *:new_class perm;
Może to wymagać zasady zezwalającej na dostęp dla wszystkich typów interfejsów (publiczna zasada), aby mieć pewność, że obraz dostawcy uzyska dostęp. Jeśli spowoduje to nieakceptowalną politykę zabezpieczeń (jak w przypadku zmian w servicemanager), może być konieczne wymuszenie aktualizacji przez dostawcę.
Usunięcie zajęć lub uprawnień
Ten scenariusz występuje, gdy usuwasz menedżera obiektu (np. menedżera obiektu ZygoteConnection
) i nie powinien powodować problemów. Klasa menedżera obiektów i uprawnienia mogą pozostać zdefiniowane w zasadach, dopóki wersja dostawcy nie przestanie ich używać. W tym celu należy dodać definicje do odpowiedniego pliku mapowania.
dostosowywanie przez dostawcę nowych lub zmienionych typów;
Nowe typy dostawców są podstawą tworzenia zasad dotyczących dostawców, ponieważ są potrzebne do opisywania nowych procesów, plików binarnych, urządzeń, podsystemów i przechowywanych danych. Dlatego konieczne jest zezwolenie na tworzenie typów zdefiniowanych przez dostawcę.
Ponieważ zasady dostawcy są zawsze najstarszymi na urządzeniu, nie ma potrzeby automatycznego konwertowania wszystkich typów dostawców na atrybuty w zasadach. Platforma nie korzysta z nic oznaczonego w zasadach dostawcy, ponieważ nie ma o nich żadnej wiedzy. Udostępnia jednak atrybuty i publiczne typy, których używa do interakcji z obiektmi oznaczonymi tymi typami (np. domain
, sysfs_type
itp.). Aby platforma mogła nadal prawidłowo współpracować z tymi obiektami, atrybuty i typy muszą być odpowiednio stosowane, a w przypadku domen z możliwością dostosowania (takich jak init
) może być konieczne dodanie określonych reguł.
Zmiany atrybutów w Androidzie 9
Urządzenia aktualizowane do Androida 9 mogą używać tych atrybutów, ale nie mogą ich używać urządzenia uruchamiane z Androidem 9.
Atrybuty naruszyciela
Android 9 zawiera te atrybuty związane z domeną:
data_between_core_and_vendor_violators
. Atrybut dla wszystkich domen, które naruszają wymóg nieudostępniania plików przez ścieżkę międzyvendor
icoredomains
. Procesy platformy i dostawców nie powinny używać plików na dysku do komunikacji (niestabilny ABI). Rekomendacja:- Kod dostawcy powinien zawierać
/data/vendor
. - System nie może używać
/data/vendor
.
- Kod dostawcy powinien zawierać
system_executes_vendor_violators
.Atrybut dla wszystkich domen systemowych (z wyjątkieminit
ishell domains
), które naruszają wymóg nieuruchamiania binarek dostawców. Wykonywanie binarnych plików dostawcy z niestabilnym interfejsem API. Platforma nie powinna bezpośrednio wykonywać plików binarnych dostawcy. Rekomendacja:- Takie zależności platformy od plików binarnych dostawcy muszą być zaimplementowane za pomocą interfejsów HIDL HAL.
LUB
coredomains
, które wymagają dostępu do plików binarnych dostawcy, powinny zostać przeniesione na partycję dostawcy, przez co przestaną byćcoredomain
.
- Takie zależności platformy od plików binarnych dostawcy muszą być zaimplementowane za pomocą interfejsów HIDL HAL.
Niegodne zaufania atrybuty
Niezaufane aplikacje, które zawierają dowolny kod, nie powinny mieć dostępu do usług HwBinder, z wyjątkiem tych, które są uznawane za wystarczająco bezpieczne (patrz niżej „Bezpieczne usługi”). Wynika to z 2 głównych powodów:
- Serwery HwBinder nie przeprowadzają uwierzytelniania klienta, ponieważ HIDL obecnie nie udostępnia informacji o UID dzwoniącego. Nawet jeśli HIDL udostępnia takie dane, wiele usług HwBinder działa na poziomie niższym niż aplikacje (np. HAL) lub nie może polegać na tożsamości aplikacji w celu autoryzacji. Dlatego, aby zachować bezpieczeństwo, domyślnie zakładamy, że każda usługa HwBinder traktuje wszystkich swoich klientów jako równych sobie w wykonaniu operacji oferowanych przez usługę.
- Serwery HAL (podzbiór usług HwBinder) zawierają kod, który ma większą częstotliwość występowania problemów z bezpieczeństwem niż komponenty
system/core
. Mają one dostęp do niższych warstw stosu (aż do sprzętu), co zwiększa możliwości obejścia modelu zabezpieczeń Androida.
Bezpieczne usługi
Bezpieczne usługi to m.in.:
same_process_hwservice
Te usługi (z definicji) działają w procesie klienta, więc mają ten sam dostęp co domena klienta, w której działa proces.coredomain_hwservice
. Te usługi nie stwarzają ryzyka związanego z przyczyną #2.hal_configstore_ISurfaceFlingerConfigs
. Ta usługa jest przeznaczona do użytku w dowolnej domenie.hal_graphics_allocator_hwservice
. Te operacje są też dostępne w usłudzesurfaceflinger
Binder, do której aplikacje mogą uzyskać dostęp.hal_omx_hwservice
. To wersja usługi Bindermediacodec
w ramach interfejsu HwBinder, do której aplikacje mogą uzyskać dostęp.hal_codec2_hwservice
. Jest to nowsza wersja programuhal_omx_hwservice
.
Atrybuty, które można wykorzystać
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 z Androidem 9 NIE MOGĄ używać atrybutu untrusted
.
Rekomendacja:
- Zamiast tego aplikacje o nieznanej reputacji powinny komunikować się z usługą systemową, która komunikuje się z interfejsem HIDL dostawcy. Aplikacje mogą na przykład komunikować się z
binderservicedomain
, a następnie zmediaserver
(który jestbinderservicedomain
), a ten z kolei zhal_graphics_allocator
.LUB
- Aplikacje, które wymagają bezpośredniego dostępu do
vendor
HAL, powinny mieć własną domenę sepolicy zdefiniowaną przez dostawcę.
Testy atrybutów pliku
Android 9 zawiera testy w czasie kompilacji, które sprawdzają, czy wszystkie pliki w określonych lokalizacjach mają odpowiednie atrybuty (np. czy wszystkie pliki w sysfs
mają wymagany atrybut sysfs_type
).
Zasady dotyczące platformy i publiczne
Zasady dotyczące platformy publicznej są podstawą zgodności z modelem architektury Androida 8.0, a nie tylko podtrzymaniem unionu zasad platformy z wersji 1 i 2. Dostawcy mają dostęp do podzbioru zasad platformy, który zawiera przydatne typy i atrybuty oraz reguły dotyczące tych typów i atrybutów. Zasady te stają się częścią zasad dostawcy (czyli vendor_sepolicy.cil
).
Typy i zasady są automatycznie tłumaczone w zasadach generowanych przez dostawcę na attribute_vN
, dzięki czemu wszystkie typy udostępniane przez platformę są atrybutami z wersją (chociaż atrybuty nie mają wersji). Platforma jest odpowiedzialna za mapowanie konkretnych typów na odpowiednie atrybuty, aby zapewnić, że zasady dostawcy będą nadal działać i że uwzględnione zostaną reguły określone dla danej wersji. Połączenie zasad dotyczących platformy i publicznych zasad dostawcy spełnia cel modelu architektury Androida 8.0, który umożliwia niezależne kompilacje platform i dostawców.
Mapowanie na łańcuchy atrybutów
Gdy używasz atrybutów do mapowania wersji zasad, typ jest mapowany na atrybut lub wiele atrybutów, co zapewnia, że obiekty opisane tym typem są dostępne za pomocą atrybutów odpowiadających ich poprzednim typom.
Utrzymywanie celu polegającego na ukrywaniu informacji o wersji przed autorem zasad oznacza automatyczne generowanie atrybutów z wersją i przypisywanie ich do odpowiednich typów. W przypadku typów statycznych jest to proste:type_foo
odpowiada type_foo_v1
.
W przypadku zmiany etykiety obiektu, np. sysfs
→ sysfs_A
lub mediaserver
→ audioserver
, utworzenie tego mapowania nie jest trywialne (i jest opisane w powyższych przykładach). Administratorzy zasad platformy muszą określić, jak tworzyć mapowanie w punktach przejścia dla obiektów. Wymaga to zrozumienia relacji między obiektami a przypisanymi do nich etykietami oraz określenia, kiedy to ma miejsce. Ze względu na zgodność z wcześniejszymi wersjami należy zarządzać tą złożonością po stronie platformy, która jest jedyną partycją, która może być aktualizowana.
Wersje wstecz
Dla ułatwienia platforma Android udostępnia wersję sepolicy, gdy tworzona jest nowa gałąź wersji. Jak opisano powyżej, numer wersji znajduje się w PLATFORM_SEPOLICY_VERSION
i ma postać MM.nn
, gdzie MM
odpowiada wartości pakietu SDK, a nn
to wartość prywatna przechowywana w /platform/system/sepolicy.
. Przykładowo: 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.
Przewidywania nie zawsze są liczbami całkowitymi. Jeśli na przykład przejście na nową wersję w ramach MR wymaga wprowadzenia niezgodnych zmian w system/sepolicy/public
, ale nie w interfejsie API, wersja sepolicy może być taka: vN.1
. Wersja w gałęzi rozwojowej jest wersją, która nigdy nie powinna być używana na urządzeniach produkcyjnych 10000.0
.
Android może wycofać najstarszą wersję podczas aktualizacji. Aby określić, kiedy wycofać wersję, Android może zbierać informacje o liczbie urządzeń z zasadami dostawcy, na których działa ta wersja Androida i które nadal otrzymują główne aktualizacje platformy. Jeśli liczba jest mniejsza od określonego progu, wersja jest wycofana.
Wpływ na skuteczność wielu atrybutów
Jak opisano na stronie https://github.com/SELinuxProject/cil/issues/9, duża liczba atrybutów przypisanych do typu powoduje problemy z wydajnością w przypadku braku pamięci podręcznej zasad.
Potwierdzono, że jest to problem z Androidem, więc wprowadziliśmy zmiany w Androidzie 8.0, aby usunąć atrybuty dodane do zasad przez kompilator zasad, a także nieużywane atrybuty. Te zmiany rozwiązały problemy z regresją wydajności.
system_ext public and product public policy
Od Androida 11 partycje system_ext
i product
mogą eksportować swoje wyznaczone typy publiczne do partycji dostawcy. Podobnie jak w przypadku publicznych zasad platformy, dostawca używa typów i reguł automatycznie przekształcanych w atrybuty z wersją, np. z type
na type_N
, gdzie N
to wersja platformy, na której zbudowano partycję dostawcy.
Gdy partycje system_ext
i product
są oparte na tej samej wersji platformy (N
), system kompilacji generuje pliki mapowania podstawowego do plików system_ext/etc/selinux/mapping/N.cil
i product/etc/selinux/mapping/N.cil
, które zawierają mapowania tożsamości z poziomu type
do type_N
. Dostawca może uzyskać dostęp do atrybutu type
za pomocą atrybutu z wersją type_N
.
Jeśli tylko partycje system_ext
i product
zostaną zaktualizowane, np. z N
na N+1
(lub nowszą), a dostawca pozostanie na wersji N
, może utracić dostęp do typów partycji system_ext
i product
. Aby zapobiec uszkodzeniom, partycje system_ext
i product
powinny zawierać pliki mapowania plików konkretnych typów na atrybuty type_N
. Każdy partner jest odpowiedzialny za utrzymywanie plików mapowania, jeśli zamierza obsługiwać dostawcę N
z wersją N+1
(lub nowszą) z partycjami system_ext
i product
.
Aby to osiągnąć, partnerzy muszą:
- Skopiuj wygenerowane pliki mapowania bazy z partycji
N
,system_ext
iproduct
do drzewa źródłowego. - W razie potrzeby zmodyfikuj pliki mapowania.
-
Zainstaluj pliki mapowania na partycjach
N+1
(lub nowszych)system_ext
iproduct
.
Załóżmy na przykład, że N
system_ext
ma jeden publiczny typ o nazwie foo_type
. W tym przypadku system_ext/etc/selinux/mapping/N.cil
na partycji N
system_ext
będzie wyglądać tak:
(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 bar_type
zostanie zmapowany na foo_type
dla dostawcy N
, N.cil
można zaktualizować z
(typeattributeset foo_type_N (foo_type))
to
(typeattributeset foo_type_N (foo_type bar_type))
a następnie zainstalowane na partycji N+1
system_ext.
Dostawca N
może nadal uzyskiwać dostęp do funkcji foo_type
system_extfoo_type
i bar_type
.N+1
Oznaczanie kontekstów SELinux
Aby umożliwić rozróżnianie polityki zabezpieczeń platformy i zabezpieczeń dostawcy, system tworzy pliki kontekstu SELinux w inny sposób, aby zachować ich odrębność.
konteksty plików,
W Androidzie 8.0 wprowadzono następujące zmiany dotyczące file_contexts
:
- Aby uniknąć dodatkowego obciążenia kompilacją na urządzeniu podczas uruchamiania,
file_contexts
przestają istnieć w postaci binarnej. Zamiast tego są to czytelne pliki tekstowe z wyrażeniami regularnymi, takie jak{property, service}_contexts
(jak w wersji 7.0 i wcześniejszych). file_contexts
są podzielone na 2 pliki:plat_file_contexts
- platforma Android
file_context
, która nie ma etykiet związanych z urządzeniem, z wyjątkiem etykiet części partycji/vendor
, które muszą być dokładnie opisane, aby zapewnić prawidłowe działanie plików sepolicy; - Musi znajdować się na partycji
system
na urządzeniu/system/etc/selinux/plat_file_contexts
i być wczytywany przezinit
na początku wraz z dostawcąfile_context
.
- platforma Android
vendor_file_contexts
file_context
dla danego urządzenia utworzone przez połączeniefile_contexts
z katalogów wskazywanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
na urządzeniu.- Musi być zainstalowany w miejscu
/vendor/etc/selinux/vendor_file_contexts
w partycjivendor
i wczytany przezinit
na początku razem z platformąfile_context
.
Konteksty obiektów
W Androidzie 8.0 property_contexts
jest podzielony na 2 pliki:
plat_property_contexts
- platforma Android
property_context
, która nie ma etykiet dla poszczególnych urządzeń; - Musi znajdować się w partycji
system
w/system/etc/selinux/plat_property_contexts
i być wczytywany przezinit
na początku razem z dostawcąproperty_contexts
.
- platforma Android
vendor_property_contexts
property_context
dla danego urządzenia utworzone przez połączenieproperty_contexts
z katalogów wskazywanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
na urządzeniu.- Musi znajdować się w partycji
vendor
w/vendor/etc/selinux/vendor_property_contexts
i być wczytywany przezinit
na początku wraz z platformąproperty_context
.
Konteksty usług
W Androidzie 8.0 service_contexts
jest podzielony na te pliki:
plat_service_contexts
service_context
na platformie Androida w przypadkuservicemanager
.service_context
nie ma etykiet związanych z urządzeniem.- Musi znajdować się w partycji
system
w/system/etc/selinux/plat_service_contexts
i być wczytywany przezservicemanager
na początku razem z dostawcąservice_contexts
.
vendor_service_contexts
service_context
dla danego urządzenia utworzone przez połączenieservice_contexts
z katalogów wskazywanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia.- Musi znajdować się w partycji
vendor
w czasie/vendor/etc/selinux/vendor_service_contexts
i być wczytywany przezservicemanager
na początku razem z platformąservice_contexts
. - Chociaż
servicemanager
szuka tego pliku podczas uruchamiania, w przypadku w pełni zgodnego urządzeniaTREBLE
plikvendor_service_contexts
NIE MOŻE istnieć. Dzieje się tak, ponieważ wszystkie interakcje między procesamivendor
isystem
muszą przechodzić przez procesyhwservicemanager
/hwbinder
.
plat_hwservice_contexts
- Platforma Android
hwservice_context
dlahwservicemanager
, która nie ma etykiet związanych z urządzeniem. - Musi znajdować się w partycji
system
w czasie/system/etc/selinux/plat_hwservice_contexts
i być wczytywana przezhwservicemanager
na początku razem zvendor_hwservice_contexts
.
- Platforma Android
vendor_hwservice_contexts
hwservice_context
dla danego urządzenia utworzone przez połączeniehwservice_contexts
z katalogów wskazywanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia.- Musi znajdować się w partycji
vendor
w/vendor/etc/selinux/vendor_hwservice_contexts
i być wczytywany przezhwservicemanager
na początku razem zplat_service_contexts
.
vndservice_contexts
service_context
dla urządzeniavndservicemanager
utworzone przez połączenievndservice_contexts
znajdujących się w katalogach wskazywanych przezBOARD_SEPOLICY_DIRS
wBoardconfig.mk
urządzenia.- Plik musi znajdować się na partycji
vendor
w miejscu/vendor/etc/selinux/vndservice_contexts
i na początku musi być wczytywany przezvndservicemanager
.
Konteksty Seapp
W Androidzie 8.0 seapp_contexts
jest podzielony na 2 pliki:
plat_seapp_contexts
- platforma Android
seapp_context
bez zmian specyficznych dla urządzenia. - Musi znajdować się w partycji
system
w czasie/system/etc/selinux/plat_seapp_contexts.
- platforma Android
vendor_seapp_contexts
- Rozszerzenie dla konkretnego urządzenia na platformie
seapp_context
utworzone przez połączenieseapp_contexts
znalezionego w katalogach wskazywanych przezBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi znajdować się na partycji
vendor
w czasie/vendor/etc/selinux/vendor_seapp_contexts
.
- Rozszerzenie dla konkretnego urządzenia na platformie
Uprawnienia MAC
W Androidzie 8.0 mac_permissions.xml
jest podzielony na 2 pliki:
- Platforma:
mac_permissions.xml
- platforma Android
mac_permissions.xml
bez zmian specyficznych dla urządzenia. - Musi znajdować się w partycji
system
w czasie/system/etc/selinux/.
- platforma Android
- Nie na platformie
mac_permissions.xml
- Rozszerzenie dla konkretnego urządzenia na platformie
mac_permissions.xml
utworzone na podstawie plikumac_permissions.xml
znajdującego się w katalogach wskazywanych przez elementBOARD_SEPOLICY_DIRS
w plikachBoardconfig.mk
urządzenia. - Musi znajdować się w partycji
vendor
w czasie/vendor/etc/selinux/.
- Rozszerzenie dla konkretnego urządzenia na platformie