Na tej stronie opisujemy, jak Android radzi sobie z problemami ze zgodnością zasad podczas aktualizacji platformy OTA, gdy nowe ustawienia SELinux platformy mogą różnić się od starych ustawień SELinux dostawcy.
Własność obiektów i oznaczanie ich etykietami
Własność każdego obiektu musi być jasno określona, aby zachować rozdzielenie zasad platformy i zasad dostawcy. Jeśli na przykład w kolejnej aktualizacji OTA etykiety zasad dostawcy /dev/foo
i etykiety zasad platformy /dev/foo
są różne, wystąpi nieokreślone zachowanie, np. nieoczekiwane odrzucenie lub, co gorsza, błąd rozruchu. W przypadku SELinux objawia się to jako kolizja etykiet. Węzeł urządzenia może mieć tylko jedną etykietę, która jest ostatnią zastosowaną etykietą.
W rezultacie:
- Procesy, które potrzebują dostępu do etykiety, której nie udało się zastosować, tracą dostęp do zasobu.
- Procesy, które uzyskują dostęp do pliku, mogą ulec awarii, ponieważ utworzono nieprawidłowy węzeł urządzenia.
Kolizje między etykietami platformy i dostawcy mogą wystąpić w przypadku dowolnego obiektu, który ma etykietę SELinux, w tym właściwości, usług, procesów, plików i gniazd. Aby uniknąć tych problemów, wyraźnie określ, kto jest właścicielem tych obiektów.
Przestrzeń nazw typów i atrybutów
Oprócz kolizji etykiet mogą też wystąpić kolizje nazw typów i atrybutów SELinux. SELinux nie zezwala na wielokrotne deklaracje tych samych typów i atrybutów. Zasady z powtarzającymi się deklaracjami nie zostaną skompilowane. Aby uniknąć kolizji nazw typów i nazw atrybutów, zalecamy, aby wszystkie deklaracje dostawców zaczynały się od prefiksu vendor_. Na przykład sprzedawcy powinni używać znacznika type vendor_foo, domain; zamiast type foo, domain;.
Własność pliku
Zapobieganie kolizjom w przypadku 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 z wytycznymi dotyczącymi nazewnictwa systemów plików podanymi w tej sekcji. W przypadku Androida 8.0 są to zalecenia bez egzekwowania technicznego. W przyszłości te rekomendacje będą egzekwowane przez pakiet testów dostawcy (VTS).
System (/system)
Tylko obraz systemu musi zawierać etykiety komponentów /system, file_contexts, service_contexts itp. Jeśli etykiety komponentów /system zostaną dodane w zasadach dostawcy, aktualizacja OTA obejmująca tylko platformę może nie być możliwa.
Dostawca (/vendor)
Zasady SELinux w AOSP już oznaczają części partycji vendor, z którymi platforma wchodzi w interakcje, co umożliwia pisanie 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:
| /vendor path | Etykieta dostarczona przez platformę | Procesy platformy w zależności od etykiety |
|---|---|---|
/vendor(/.*)?
|
vendor_file
|
Wszyscy klienci HAL w platformie, 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 związku z tym podczas etykietowania dodatkowych plików w partycji vendor należy przestrzegać określonych reguł (egzekwowanych za pomocą neverallows):
vendor_filemusi być domyślną etykietą dla wszystkich plików wvendorpartycji. Zasady platformy wymagają tego, aby uzyskać dostęp do implementacji HAL przekazywania.- Wszystkie nowe
exec_typesdodane wvendorpartycji za pomocą zasad dostawcy muszą mieć atrybutvendor_file_type. Jest to egzekwowane za pomocą reguł neverallow. - Aby uniknąć konfliktów z przyszłymi aktualizacjami platformy lub struktury, nie oznaczaj plików innych niż
exec_typesw partycjivendor. - Wszystkie zależności biblioteki w przypadku zidentyfikowanych przez AOSP interfejsów HAL działających w tym samym procesie muszą być oznaczone jako
same_process_hal_file..
Procfs (/proc)
Pliki w /proc można oznaczać tylko etykietą genfscon. W Androidzie 7.0 zarówno zasady platformy, jak i zasady dostawcy używały genfscon do oznaczania plików w procfs.
Zalecenie: tylko etykiety zasad platformy /proc.
Jeśli procesy dostawcy wymagają dostępu do plików w /proc, które są obecnie oznaczone domyślną etykietą (proc), zasady dostawcy nie powinny ich wyraźnie oznaczać, ale zamiast tego powinny używać ogólnego typu proc do dodawania reguł dla domen dostawcy. Dzięki temu aktualizacje platformy będą uwzględniać przyszłe interfejsy jądra udostępniane przez procfs i w razie potrzeby będą je wyraźnie oznaczać.
Debugfs (/sys/kernel/debug)
Debugfs może być oznaczona w file_contexts i genfscon. W Androidzie 7.0–10 zarówno etykieta platformy, jak i etykieta dostawcy
debugfs.
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ć oznaczona w file_contexts i genfscon. W Androidzie 7.0 tylko etykiety platformytracefs.
Rekomendacja: tylko platforma może oznaczać tracefs.
Sysfs (/sys)
Pliki w /sys mogą być oznaczane etykietami za pomocą file_contexts i genfscon. W Androidzie 7.0 zarówno platforma, jak i dostawca używają genfscon do oznaczania plików w sysfs.
Rekomendacja: platforma może oznaczać sysfswęzły, które nie są specyficzne dla urządzenia. W przeciwnym razie tylko dostawca może oznaczać pliki.
tmpfs (/dev)
Pliki w folderze /dev mogą być oznaczone etykietami w folderze file_contexts. W Androidzie 7.0 zarówno platforma, jak i dostawca mają tutaj pliki etykiet.
Rekomendacja: dostawca może oznaczać tylko pliki w /dev/vendor (np. /dev/vendor/foo, /dev/vendor/socket/bar).
Rootfs (/)
Pliki w folderze / mogą być oznaczone etykietami w folderze file_contexts. W Androidzie 7.0 pliki etykiet platformy i dostawcy znajdują się tutaj.
Zalecenie: tylko system może oznaczać pliki w /.
Dane (/data)
Dane są oznaczane za pomocą kombinacji 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
Począwszy 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 vendor. Dzięki temu starszevendor partycje mogą zachować dotychczasową implementację SEPolicy.
Jest to kontrolowane przez zmienną pliku Makefile BOARD_GENFS_LABELS_VERSION, która jest przechowywana w /vendor/etc/selinux/genfs_labels_version.txt.
Przykład:
-
W przypadku interfejsu API dostawcy na poziomie 202404 węzeł
/sys/class/udcjest domyślnie oznaczony etykietąsysfs. -
Od poziomu interfejsu API dostawcy 202504 parametr
/sys/class/udcjest oznaczony jakosysfs_udc.
/sys/class/udc może być jednak używane przez vendor
partycje korzystające z interfejsu API na poziomie 202404, z domyślną sysfs
etykietą lub etykietą dostawcy. Bezwarunkowe oznaczanie /sys/class/udc jako sysfs_udc może spowodować utratę zgodności z tymi vendor partycjami. Jeśli zaznaczysz pole wyboru BOARD_GENFS_LABELS_VERSION, platforma będzie nadal używać poprzednich etykiet i uprawnień w przypadku starszych partycji vendor.
BOARD_GENFS_LABELS_VERSION może być równa poziomowi interfejsu API dostawcy lub od niego większa. Na przykład vendorpartycje korzystające z poziomu interfejsu API 202404 mogą ustawić wartość BOARD_GENFS_LABELS_VERSION na 202504, aby zastosować nowe etykiety wprowadzone w poziomie 202504. Zobacz listę
etykiet genfs dotyczących 202504.
Podczas etykietowania węzłów genfscon platforma musi uwzględniać starsze partycje vendor i w razie potrzeby wdrażać mechanizmy rezerwowe zapewniające zgodność. Platforma może używać bibliotek dostępnych tylko na platformie do wysyłania zapytań o wersję etykiet genfs.
-
W przypadku reklam natywnych używaj parametru
libgenfslabelsversion. Plik nagłówkowylibgenfslabelsversionznajdziesz wgenfslabelsversion.h. -
W przypadku Javy użyj
android.os.SELinux.getGenfsLabelsVersion().
Platforma – polityka publiczna
Polityka SELinux platformy jest podzielona na część prywatną i publiczną. Zasady publiczne platformy składają się z typów i atrybutów, które są zawsze dostępne na poziomie interfejsu API dostawcy, działając jako interfejs API między platformą a dostawcą. Ta zasada jest udostępniana autorom zasad dostawców, aby umożliwić im tworzenie plików zasad dostawców, które w połączeniu z zasadami prywatnymi platformy tworzą w pełni funkcjonalne zasady dotyczące urządzenia. Zasady platformy są zdefiniowane w system/sepolicy/public.
Na przykład typ vendor_init, który reprezentuje proces inicjowania w kontekście dostawcy, jest zdefiniowany w system/sepolicy/public/vendor_init.te:
type vendor_init, domain;
Dostawcy mogą użyć typu vendor_init, aby napisać niestandardowe reguły zasad:
# Allow vendor_init to set vendor_audio_prop in vendor's init scripts
set_prop(vendor_init, vendor_audio_prop)Atrybuty zgodności
Zasady SELinux to interakcja między typami źródłowymi i docelowymi w przypadku określonych klas obiektów i uprawnień. Każdy obiekt (np. procesy, pliki) objęty zasadami SELinux może mieć tylko 1 typ, ale ten typ może mieć wiele atrybutów.
Zasady są w większości sformułowane w odniesieniu do istniejących typów. W tym przypadku zarówno vendor_init, jak i debugfs są typami:
allow vendor_init debugfs:dir { mounton };
Działa to dlatego, że 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 zmieni się tylko w jednych z tych zasad, w drugich może wystąpić zasada, która wcześniej zyskała lub utraciła dostęp. Załóżmy na przykład, że etykiety zasad platformy oznaczają węzły sysfs jako sysfs:
/sys(/.*)? u:object_r:sysfs:s0
Zasady dostawcy zapewniają dostęp do /sys/usb oznaczonego jakosysfs:
allow vendor_init sysfs:chr_file rw_file_perms;
Jeśli zasady platformy zostaną zmienione tak, aby oznaczać /sys/usb jako sysfs_usb, zasady dostawcy pozostaną bez zmian, ale vendor_init utraci dostęp do /sys/usb z powodu braku zasad dotyczących nowego typu sysfs_usb:
/sys/usb u:object_r:sysfs_usb:s0
Aby rozwiązać ten problem, Android wprowadza koncepcję atrybutów z określoną wersją. Podczas kompilacji system kompilacji automatycznie tłumaczy publiczne typy platformy używane w zasadach dostawcy na te atrybuty z określoną wersją. To tłumaczenie jest możliwe dzięki plikom mapowania, które łączą atrybut z wersją z co najmniej 1 publicznym typem z platformy.
Załóżmy na przykład, że w zasadach platformy 202504 element /sys/usb jest oznaczony jako sysfs, a zasady dostawcy 202504 przyznają vendor_init dostęp do /sys/usb. W tej sytuacji:
-
Zasady dostawcy tworzą regułę
allow vendor_init sysfs:chr_file rw_file_perms;, ponieważ/sys/usbjest oznaczony jakosysfsw zasadach platformy 202504. Gdy system kompilacji skompiluje zasady dostawcy, automatycznie przetłumaczy regułę naallow vendor_init_202504 sysfs_202504:chr_file rw_file_perms;. Atrybutyvendor_init_202504isysfs_202504odpowiadają typomvendor_initisysfs, które są typami zdefiniowanymi przez platformę. -
System kompilacji generuje plik mapowania tożsamości
/system/etc/selinux/mapping/202504.cil. Ponieważ partycjesystemivendorkorzystają z tej samej wersji202504, plik mapowania zawiera mapowania tożsamości ztype_202504natype. Na przykład:vendor_init_202504jest mapowany navendor_init, asysfs_202504jest mapowany nasysfs:(typeattributeset sysfs_202504 (sysfs)) (typeattributeset vendor_init_202504 (vendor_init)) ...
Gdy wersja zostanie zmieniona z 202504 na 202604, w system/sepolicy/private/compat/202504/202504.cil zostanie utworzony nowy plik mapowania dla partycji 202504
vendor, który zostanie zainstalowany w /system/etc/selinux/mapping/202504.cil w przypadku partycji 202604
lub nowszych system. Początkowo ten plik mapowania zawiera mapowania tożsamości opisane wcześniej. Jeśli do zasad platformy 202604 zostanie dodana nowa etykieta sysfs_usb
dla /sys/usb, plik mapowania zostanie zaktualizowany, aby zmapować sysfs_202504 na sysfs_usb:
(typeattributeset sysfs_202504 (sysfs sysfs_usb)) (typeattributeset vendor_init_202504 (vendor_init)) ...
Ta aktualizacja umożliwia przekonwertowanej regule zasad dostawcy allow
vendor_init_202504 sysfs_202504:chr_file rw_file_perms; automatyczne przyznawanie dostępu vendor_init do nowego typu sysfs_usb.
Aby zachować zgodność ze starszymi partycjami vendor, za każdym razem, gdy dodawany jest nowy typ publiczny, musi on być mapowany na co najmniej jeden z atrybutów z określoną wersją w pliku mapowania system/sepolicy/private/compat/ver/ver.cil lub musi być wymieniony w sekcji system/sepolicy/private/compat/ver/ver.ignore.cil, aby wskazać, że w poprzednich wersjach dostawcy nie ma pasującego typu.
Połączenie zasad platformy, zasad dostawcy i pliku mapowania umożliwia aktualizację systemu bez aktualizowania zasad dostawcy. Konwersja na atrybuty z określoną wersją odbywa się automatycznie, więc zasady dostawcy nie muszą uwzględniać obsługi wersji i mogą nadal używać typów publicznych w niezmienionej postaci.
system_ext public and product public policy
Od Androida 11 partycje system_ext i product mogą eksportować wyznaczone typy publiczne do partycji vendor. Podobnie jak w przypadku zasad publicznych platformy, zasady dostawcy korzystają z typów i reguł automatycznie tłumaczonych na atrybuty z wersjami, np. z type na type_ver, gdzie ver to poziom interfejsu API dostawcy w vendor partycji.
Gdy partycje system_ext i product są oparte na tej samej wersji platformy ver, system kompilacji generuje podstawowe pliki mapowania do system_ext/etc/selinux/mapping/ver.cil i product/etc/selinux/mapping/ver.cil, które zawierają mapowania tożsamości z type na type_ver.
Zasady dostawcy mogą uzyskać dostęp do type za pomocą atrybutu z określoną wersją
type_ver.
Jeśli zaktualizowane zostaną tylko partycje system_ext i product, np. z ver na ver+1 (lub nowszą), a partycja vendor pozostanie na poziomie ver, zasady dostawcy mogą utracić dostęp do typów partycji system_ext i product. Aby zapobiec przerwaniu, partycje system_ext i product powinny udostępniać pliki mapowania z konkretnych typów na atrybuty type_ver. Każdy partner jest odpowiedzialny za utrzymywanie plików mapowania, jeśli obsługuje partycję ver vendor z ver+1 (lub nowszą) system_ext i partycje product.
Aby zainstalować pliki mapowania na partycjach system_ext i product, producenci urządzeń lub dostawcy powinni:
- Skopiuj wygenerowane podstawowe pliki mapowania z partycji ver
system_extiproductdo drzewa źródłowego. - W razie potrzeby zmień pliki mapowania.
-
Zainstaluj pliki mapowania na partycjach ver+1 (lub nowszych)
system_extiproduct.
Załóżmy na przykład, że partycja 202504 system_ext ma jeden typ publiczny o nazwie foo_type. W takim przypadku
system_ext/etc/selinux/mapping/202504.cil
partycja 202504 system_ext wygląda tak:
(typeattributeset foo_type_202504 (foo_type)) (expandtypeattribute foo_type_202504 true) (typeattribute foo_type_202504)
Jeśli do partycji 202604 system_ext zostanie dodany element bar_type, a element bar_type powinien być mapowany na element foo_type w przypadku partycji 202504 vendor, element 202504.cil można zaktualizować z wartości (typeattributeset foo_type_202504 (foo_type)) na (typeattributeset foo_type_202504 (foo_type bar_type))
i następnie zainstalować w partycji 202604 system_ext. Partycja 202504
vendor może nadal uzyskiwać dostęp do foo_type i bar_type partycji 202604
system_ext.
Zmiany atrybutów w Androidzie 9
Urządzenia, które zostaną zaktualizowane do Androida 9, mogą używać tych atrybutów, ale urządzenia z Androidem 9 nie mogą.
Atrybuty naruszającego
Android 9 zawiera te atrybuty związane z domeną:
data_between_core_and_vendor_violators. Atrybut wszystkich domen, które naruszają wymaganie dotyczące nieudostępniania plików według ścieżki międzyvendoracoredomains. Procesy platformy i dostawcy nie powinny używać plików na dysku do komunikacji (niestabilny interfejs ABI). Rekomendacja:- 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ątkieminitishell domains) naruszających wymaganie dotyczące niewykonywania plików binarnych dostawcy. Wykonywanie plików binarnych dostawcy ma niestabilny interfejs API. Platforma nie powinna bezpośrednio wykonywać plików binarnych dostawcy. Rekomendacja:- Takie zależności platformy od plików binarnych dostawcy muszą być ukryte za interfejsami HAL HIDL.
LUB
coredomains, które potrzebują dostępu do plików binarnych dostawcy, powinny zostać przeniesione do partycjivendori tym samym przestać byćcoredomain.
- Takie zależności platformy od plików binarnych dostawcy muszą być ukryte za interfejsami HAL HIDL.
Nieufne atrybuty
Niezaufane aplikacje, które hostują 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 z nich korzystać w takich aplikacjach (patrz bezpieczne usługi poniżej). Główne powody to:
- Serwery HwBinder nie przeprowadzają uwierzytelniania klienta, ponieważ HIDL nie udostępnia obecnie informacji o identyfikatorze UID wywołującego. Nawet jeśli HIDL udostępniałby 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 dla bezpieczeństwa domyślnym założeniem jest to, że każda usługa HwBinder traktuje wszystkich swoich klientów jako równie uprawnionych do wykonywania operacji oferowanych przez tę usługę.
- Serwery HAL (podzbiór usług HwBinder) zawierają kod, w którym występuje większa częstotliwość występowania problemów z bezpieczeństwem niż w komponentach
system/core. Mają też dostęp do niższych warstw stosu (aż do sprzętu), co zwiększa możliwości obejścia modelu zabezpieczeń Androida.
Usługi związane z sejfami
Bezpieczne usługi obejmują:
same_process_hwservice. Te usługi (z definicji) działają w procesie klienta, a tym samym mają taki sam dostęp jak domena klienta, w której działa proces.coredomain_hwservice. Te usługi nie stwarzają zagrożeń związanych z przyczyną nr 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łudzesurfaceflingerBinder, do której aplikacje mają dostęp.hal_omx_hwservice. Jest to wersja HwBinder usługi Bindermediacodec, do której aplikacje mają dostęp.hal_codec2_hwservice. To nowsza wersja usługihal_omx_hwservice.
Atrybuty, których można używać
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.
Zalecenia:
- Niezaufane aplikacje powinny komunikować się z usługą systemową, która komunikuje się z interfejsem HAL HIDL dostawcy. Na przykład aplikacje mogą komunikować się z
binderservicedomain, a potem zmediaserver(który jestbinderservicedomain), który z kolei komunikuje się zhal_graphics_allocator.LUB
- Aplikacje, które potrzebują bezpośredniego dostępu do interfejsów HAL
vendor, powinny mieć własną domenę sepolicy zdefiniowaną przez dostawcę.
Testy atrybutów plików
Android 9 zawiera testy czasu 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).
Oznaczanie kontekstów SELinux
Aby rozróżnić zasady SELinux platformy i dostawcy, system tworzy pliki kontekstu SELinux w inny sposób, aby je od siebie oddzielić.
Konteksty plików
W Androidzie 8.0 wprowadzono te zmiany dotyczące file_contexts:
- Aby uniknąć dodatkowych obciążeń związanych z kompilacją na urządzeniu podczas uruchamiania,
file_contextsnie będą one już istniały w formie binarnej. Zamiast tego są to czytelne pliki tekstowe z wyrażeniami regularnymi, takie jak{property, service}_contexts(jak przed wersją 7.0). file_contextssą podzielone na 2 pliki:plat_file_contexts- Platforma Android
file_context, która nie ma etykiet specyficznych dla urządzenia, z wyjątkiem etykietowania części partycji/vendor, które musi być precyzyjne, aby zapewnić prawidłowe działanie plików sepolicy. - Musi znajdować się w
systemna urządzeniu i być wczytywana przezinitna początku wraz zfile_contextdostawcy./system/etc/selinux/plat_file_contexts
- Platforma Android
vendor_file_contextsfile_context– tworzony przez połączeniefile_contextsznalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRSw plikachBoardconfig.mkurządzenia.- Musi być zainstalowany w
/vendor/etc/selinux/vendor_file_contextsna partycjivendori ładowany przezinitna początku wraz z platformąfile_context.
Konteksty usługi
W Androidzie 8.0 property_contexts jest podzielony na 2 pliki:
plat_property_contexts- platformy Android
property_context, która nie ma etykiet przypisanych do konkretnych urządzeń. - Musi znajdować się w
systempartycji w/system/etc/selinux/plat_property_contextsi być wczytywana przezinitna początku wraz zproperty_contexts.
- platformy Android
vendor_property_contextsproperty_context– tworzony przez połączenieproperty_contextsznalezionych w katalogach wskazanych przezBOARD_SEPOLICY_DIRSw plikachBoardconfig.mkurządzenia.- Musi znajdować się w partycji
vendorw/vendor/etc/selinux/vendor_property_contextsi być wczytywana przezinitna początku wraz z platformąproperty_context.
Konteksty usług
W Androidzie 8.0 service_contexts jest podzielony na te pliki:
plat_service_contextsservice_contextna platformę Androidservicemanager.service_contextnie ma etykiet przypisanych do urządzenia.- Musi znajdować się w
systempartycji w/system/etc/selinux/plat_service_contextsi być wczytywana przezservicemanagerna początku wraz zservice_contexts.
vendor_service_contextsservice_context– tworzone przez połączenieservice_contextsznalezionych w katalogach wskazywanych przezBOARD_SEPOLICY_DIRSw plikachBoardconfig.mkurządzenia.- Musi znajdować się w partycji
vendorpod adresem/vendor/etc/selinux/vendor_service_contextsi być wczytywany przezservicemanagerna początku wraz z platformąservice_contexts. - Chociaż
servicemanagerszuka tego pliku podczas uruchamiania, w przypadku w pełni zgodnego urządzeniaTREBLEplikvendor_service_contextsNIE MOŻE istnieć. Dzieje się tak, ponieważ wszystkie interakcje między procesamivendorisystemmuszą przechodzić przezhwservicemanager/hwbinder.
plat_hwservice_contexts- platformy Android
hwservice_context,hwservicemanagerktóra nie ma etykiet specyficznych dla urządzenia. - Musi znajdować się w partycji
systemw lokalizacji/system/etc/selinux/plat_hwservice_contextsi być wczytywany przezhwservicemanagerna początku razem zvendor_hwservice_contexts.
- platformy Android
vendor_hwservice_contextshwservice_context– tworzone przez połączeniehwservice_contextsznalezionych w katalogach wskazywanych przezBOARD_SEPOLICY_DIRSw plikachBoardconfig.mkurządzenia.- Musi znajdować się w partycji
vendorpod adresem/vendor/etc/selinux/vendor_hwservice_contextsi być wczytywany przezhwservicemanagerna początku wraz zplat_service_contexts.
vndservice_contextsservice_contextdla urządzeniavndservicemanagerutworzony przez połączenievndservice_contextsznalezionych w katalogach wskazywanych przezBOARD_SEPOLICY_DIRSwBoardconfig.mkurządzenia.- Ten plik musi znajdować się w partycji
vendorw lokalizacji/vendor/etc/selinux/vndservice_contextsi być wczytywany przezvndservicemanagerna początku.
Konteksty Seapp
W Androidzie 8.0 seapp_contexts jest podzielony na 2 pliki:
plat_seapp_contexts- platformy Android
seapp_context, która nie ma zmian specyficznych dla urządzenia. - Musi znajdować się w partycji
systemw/system/etc/selinux/plat_seapp_contexts.
- platformy Android
vendor_seapp_contexts- Rozszerzenie platformy
seapp_contextspecyficzne dla urządzenia, utworzone przez połączenieseapp_contextsznalezionych w katalogach wskazywanych przezBOARD_SEPOLICY_DIRSw plikachBoardconfig.mkurządzenia. - Musi znajdować się w partycji
vendorw/vendor/etc/selinux/vendor_seapp_contexts.
- Rozszerzenie platformy
Uprawnienia MAC
W Androidzie 8.0 mac_permissions.xml jest podzielony na 2 pliki:
- Peron
mac_permissions.xml- platformy Android
mac_permissions.xml, która nie ma zmian specyficznych dla urządzenia. - Musi znajdować się w partycji
systemw/system/etc/selinux/.
- platformy Android
- Poza platformą
mac_permissions.xml- Rozszerzenie specyficzne dla urządzenia do platformy
mac_permissions.xmlutworzone na podstawiemac_permissions.xmlznalezionych w katalogach wskazywanych przezBOARD_SEPOLICY_DIRSw plikachBoardconfig.mkurządzenia. - Musi znajdować się w partycji
vendorw/vendor/etc/selinux/.
- Rozszerzenie specyficzne dla urządzenia do platformy
Zmiany w pamięci współdzielonej w Androidzie 17
Począwszy od Androida 17, urządzenia z tymi właściwościami muszą włączyć funkcję zasad memfd_class i zaktualizować zasady dotyczące pamięci współdzielonej, aby obsługiwać obiekty klasy memfd_file:
- Interfejs API dostawcy na poziomie 202604 lub wyższym, aby umożliwić dostawcom i producentom OEM aktualizowanie zasad dostawcy w celu obsługi
memfd. Umożliwia też aktualizację istniejących urządzeń do wyższych wersji Androida bez konieczności aktualizowania partycji dostawcy. android16-6.12lub nowszy, ponieważ te jądra obsługują funkcjęmemfd_class, która jest wymagana do wdrożenia szczegółowych zasad dotyczącychmemfd.
Włączanie możliwości zasad memfd_class
Do niedawna system SELinux oznaczał memfd jako plik tego samego typu co jego system plików – tmpfs. Z punktu widzenia zasad nie można było odróżnić memfd od innego pliku na zamontowanym woluminie tmpfs. Teraz SELinux przypisuje memfd etykietę z kontekstem bezpieczeństwa procesu przydzielania, a memfds są traktowane jako obiekty klasy memfd_file. Ta funkcja jest chroniona przez możliwość memfd_class, aby zachować zgodność wsteczną ze starszymi środowiskami przestrzeni użytkownika.
Aby włączyć funkcję zasad memfd_class, utwórz plik policy_capabilities w folderze BOARD_VENDOR_SEPOLICY_DIRS. Plik powinien zawierać ten wpis:
# $BOARD_VENDOR_SEPOLICY_DIRS/*/policy_capabilities
policycap memfd_class;Następnie ponownie skompiluj obrazy i prześlij je na urządzenie, aby sprawdzić, czy funkcja jest włączona.
Sprawdzanie, czy funkcja zasad memfd_class jest włączona
Aby sprawdzić stan funkcji zasad memfd_class, użyj tego polecenia:
adb shell 'cat /sys/fs/selinux/policy_capabilities/memfd_class'
Jeśli wynikiem jest 1, funkcja zasady memfd_class jest włączona. W przeciwnym razie nie jest ona włączona.
Przenoszenie istniejącej zasady do memfd
Niektóre procesy używały w swoich zasadach makra tmpfs_domain(), aby uzyskać dostęp do memfds i przestrzeni nazw, na przykład:
# foo.te
tmpfs_domain(foo)Oznacza to:
# foo.te type_transition foo tmpfs:file foo_tmpfs; allow foo foo_tmpfs:file { read write getattr map };
i umożliwia procesowi bar dostęp do memfds procesu foo w ten sposób:
# bar.te allow bar foo_tmpfs:file { read write getattr map };
Po włączeniu funkcji zasad memfd_class makro tmpfs_domain() nie jest już potrzebne, ponieważ zasady platformy zostały zaktualizowane, aby umożliwić każdemu procesowi tworzenie i używanie własnego memfds, jak widać tutaj:
# system/sepolicy/private/domain.te allow domain self:memfd_file { create read write getattr map };
i memfds utworzone przez proces foo mogą być dostępne dla procesu bar w ten sposób:
# bar.te allow bar foo:memfd_file { read write getattr map };
Zasady platformy zostały zaktualizowane, aby uwzględnić dotychczasowe użycie symbolu memfd. Jednak zasady dotyczące dostawcy i urządzenia, które używają etykiet tmpfs, muszą zostać zaktualizowane, aby używać etykiet memfd_file. Jeśli zasady są wspólne dla układów SoC lub urządzeń, które nie mają interfejsu API dostawcy na poziomie 202604 lub wyższym, zalecamy zachowanie starszych zasad tmpfs wraz z nowymi zasadami memfd_file w celu zapewnienia zgodności.
Identyfikowanie odmów dostępu AVC związanych z memfd
Odmowy związane z Memfd można pobrać za pomocą tego polecenia:
adb shell logcat -d -b events | grep memfd
odmowy avc z tmpfs jako celem,
Poniższy przykład pokazuje odmowę avc, która wystąpiła w procesie, który próbował zapisać dane w memfd, do którego nie miał uprawnień do zapisu:
audit(0.0:539): avc: denied { write } for comm="binder:665_1" name="memfd:MessageQueue"
dev="tmpfs" ino=8324 scontext=u:r:mediacodec:s0 tcontext=u:object_r:tmpfs:s0 tclass=file
permissive=0
Gdy funkcja zasady memfd_class jest włączona, kontekstem docelowym elementu memfd jest kontekst zabezpieczeń procesu przydzielania, a nie tmpfs, a klasą docelową jest memfd_file, a nie file. Jeśli więc widzisz avc odrzucenia związane z memfd, gdzie memfd jest oznaczony jako plik tmpfs, oznacza to, że funkcja zasad memfd_class nie jest włączona.
odmowy avc z memfd_file jako klasą docelową,
Poniższy przykład pokazuje odmowę avc, która wystąpiła w procesie próbującym zapisać dane w memfd, do którego nie miał uprawnień do zapisu. Włączona była funkcja zasad memfd_class. Dodatkowo w tym samym momencie logd wyemitował wiersz po odmowie:
audit(0.0:86): avc: denied { read } for
path=2F6D656D66643A4D6564696142756666657247726F7570202864656C6574656429 ino=512 dev=""
scontext=u:r:mediaserver:s0 tcontext=u:object_r:mediaextractor:s0 tclass=memfd_file
auditd : Decoded path for audit(0.0:86): /memfd:MediaBufferGroup (deleted)
Pasująca sygnatura czasowa wskazuje, że Decoded path for … log jest powiązany z odmową avc z sygnaturą czasową 0.0.86. Ten log dekoduje ciąg szesnastkowy z wartości ścieżki w avc odmowie i podaje nazwę memfd regionu pamięci, co może być przydatne do zrozumienia, który bufor jest udostępniany. Kontekst źródłowy i kontekst docelowy pomagają zrozumieć, które procesy muszą współdzielić pamięć. Z powyższego przykładu jasno wynika, że proces mediaserver musi mieć dostęp do memfds procesu mediaextractor. Dlatego odpowiednie zasady to:
# mediaserver.te allow mediaserver mediaextractor:memfd_file { getattr read write map };
Aktualizacje domeny zabezpieczeń w Androidzie 17
Interfejs ASharedMemory_create() API w Androidzie 17 implementuje logikę warunkową, która umożliwia wybór między starszym sterownikiem ashmem a platformą ASharedMemory_create() do przydzielania pamięci współdzielonej.memfd
W przypadku urządzeń spełniających memfd wymagania (poziom interfejsu API dostawcy 202604 lub wyższy i jądro android16-6.12 lub nowsze) interfejs API ocenia targetSdkVersion aplikacji wywołującej. Jeśli docelowa wersja pakietu SDK to 37 lub nowsza, przydzielana jest wartość memfd. Dzięki temu deweloperzy mogą rozwiązywać problemy, które napotykają podczas uaktualniania docelowej wersji pakietu SDK.
Jeśli urządzenie nie spełnia memfd's wymagań wstępnych, ASharedMemory przełącza się na ashmem. Zapewnia to zgodność uaktualnionych urządzeń ze starszymi partycjami dostawcy lub jądrami.
Aby wymusić to przejście, zasady SELinux platformy blokują aplikacjom kierowanym na pakiet SDK w wersji 37 lub nowszej w domenach zabezpieczeń platform_app, priv_app i untrusted_app otwieranie /dev/ashmem i wywoływanie poleceń ashmem ioctl na memfd. Osiąga się to przez podzielenie domen aplikacji na podstawie docelowej wersji pakietu SDK. Wprowadzamy domeny zabezpieczeń platform_app_36, priv_app_36 i untrusted_app_34, które wraz z innymi domenami aplikacji zachowują uprawnienia do otwierania ashmem i możliwość wywoływania poleceń ioctl ashmem na memfds.
W przyszłej wersji Androida zestaw aplikacji, które zachowają uprawnienia do otwierania urządzenia ashmem i wywoływania poleceń ashmem ioctl na memfds, zostanie ograniczony do platform_app_36, priv_app_36 i untrusted_app_34 oraz niezaufanych domen aplikacji w przypadku starszych wersji pakietu SDK.
Niestandardowe zasady SELinux dostawcy lub producenta OEM dla aplikacji, które przypinają docelową wersję pakietu SDK, muszą zostać zaktualizowane, aby były zgodne z tymi zmianami w domenach, jak opisano w kolejnych sekcjach.
Aktualizacje domeny SELinux platform_app
Domena platform_app jest dzielona na podstawie targetSdkVersion aplikacji. Aplikacje platformy kierowane na pakiet SDK w wersji 37 lub nowszej mają przypisaną domenę platform_app, a aplikacje kierowane na pakiet SDK w wersji 36 lub starszej – domenę platform_app_36. Domena platform_app_36 zachowuje możliwość otwierania /dev/ashmem ze względu na zgodność wsteczną. Aby uprościć zarządzanie zasadami w obu domenach, użyj atrybutu platform_app_all.
Rozważmy sytuację, w której aplikacja platformy sample-plat-app musi odczytywać dane z /dev/foo_device i zapisywać je w /dev/foo_device. Obecna zasada SELinux dostawcy może wyglądać tak:
# This will only allow sample-plat-app to access the device if it # is placed in the platform_app domain (i.e. target SDK version is 37 or higher). allow platform_app foo_device:chr_file rw_file_perms;
Jeśli jednak sample-plat-app jest przypięty do docelowego pakietu SDK w wersji 36, jest umieszczany w domenie platform_app_36, a zasady SELinux z wcześniejszej wersji nie będą stosowane. W takim przypadku wystąpi następujące odrzucenie AVC:
auditd : type=1400 audit(0.0:11): avc: denied { read write } for comm="sample-plat-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:platform_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0
Aby to naprawić, można zaktualizować zasadę, ponieważ aplikacja powinna zawsze mieć dostęp do węzła urządzenia:
# This allows sample-plat-app to access the device independent of # target SDK version. allow platform_app_all foo_device:chr_file rw_file_perms;
W niektórych sytuacjach platform_app_all może nie działać. Jeśli na przykład makro hal_client_domain() jest używane z makrem platform_app_all, kompilacja zasady nie powiedzie się. Dzieje się tak, ponieważ platform_app_all jest atrybutem, a hal_client_domain() próbuje dołączyć do niego kolejny atrybut, co jest niemożliwe:
# platform_app.te
hal_client_domain(platform_app, hal_foo)
W takich przypadkach musisz użyć bezpośrednio typu platform_app_36, więc Twoje zasady będą zawierać te informacje:
# platform_app.te hal_client_domain(platform_app, hal_foo) # platform_app_36.te hal_client_domain(platform_app_36, hal_foo)
Aktualizacje domeny SELinux aplikacji uprzywilejowanych
Domena priv_app jest dzielona na podstawie targetSdkVersion aplikacji. Aplikacje uprzywilejowane kierowane na pakiet SDK w wersji 37 lub nowszej mają przypisaną domenę priv_app, a aplikacje kierowane na pakiet SDK w wersji 36 lub starszej korzystają z domeny priv_app_36. Domena priv_app_36 zachowuje możliwość otwierania /dev/ashmem ze względu na zgodność wsteczną. Aby uprościć zarządzanie zasadami w obu domenach, użyj atrybutu priv_app_all.
Rozważmy sytuację, w której aplikacja platformy sample-priv-app musi odczytywać dane z /dev/foo_device i zapisywać je w /dev/foo_device. Obecna zasada SELinux dostawcy może wyglądać tak:
# This will only allow sample-priv-app to access the device if it # is placed in the priv_app domain (i.e. target SDK version is 37 or higher). allow priv_app foo_device:chr_file rw_file_perms;
Jeśli jednak sample-priv-app jest przypięty do docelowego pakietu SDK w wersji 36, jest umieszczany w domenie priv_app_36, a zasady SELinux z wcześniejszej wersji nie będą stosowane. W takim przypadku wystąpi następujące odrzucenie AVC:
auditd : type=1400 audit(0.0:11): avc: denied { read write } for comm="sample-priv-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:priv_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0
Aby to naprawić, można zaktualizować zasadę, ponieważ aplikacja powinna zawsze mieć dostęp do węzła urządzenia:
# This allows sample-priv-app to access the device independent of # target SDK version. allow priv_app_all foo_device:chr_file rw_file_perms;
W niektórych sytuacjach priv_app_all może nie działać. Jeśli na przykład makro hal_client_domain() jest używane z makrem priv_app_all, kompilacja zasady nie powiedzie się. Dzieje się tak, ponieważ priv_app_all jest atrybutem, a hal_client_domain() próbuje dołączyć do niego kolejny atrybut, co jest niemożliwe:
# priv_app.te
hal_client_domain(priv_app, hal_foo)
W takich przypadkach musisz użyć bezpośrednio typu priv_app_36, więc pliki zasad będą wyglądać mniej więcej tak:
# priv_app.te hal_client_domain(priv_app, hal_foo) # priv_app_36.te hal_client_domain(priv_app_36, hal_foo)
Aktualizacje domeny SELinux untrusted_app
Domena untrusted_app jest dzielona na podstawie targetSdkVersion aplikacji. Niezaufane aplikacje kierowane na pakiet SDK w wersji 37 lub nowszej są przypisywane do domeny untrusted_app, a aplikacje kierowane na pakiet SDK w wersji 34–36 (włącznie) są przypisywane do nowej domeny untrusted_app_34. Domena untrusted_app_34 oraz domeny untrusted_app_X, gdzie „X” to starsza wersja docelowego pakietu SDK, zachowują możliwość otwierania `/dev/ashmem` ze względu na zgodność wsteczną.