Zgodność z zasadami

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

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

Projekt polityki SELinux oparty na wysokich tonach uwzględnia binarne rozróżnienie między polityką platformy i 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 globalna polityka SELinux jest podzielona na komponenty prywatne i publiczne. Komponenty publiczne składają się z polityki i powiązanej infrastruktury, które mają gwarancję dostępności dla wersji platformy. Ta zasada zostanie udostępniona twórcom zasad dostawcy, aby umożliwić dostawcom tworzenie pliku zasad dostawcy, który w połączeniu z zasadami dostarczanymi przez platformę daje w rezultacie w pełni funkcjonalne zasady 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 budowania zasad. Typy publiczne mogą być również używane bezpośrednio w decyzjach dotyczących etykietowania dostarczanych przez pliki kontekstów dostawców.

Android utrzymuje mapowanie między wyeksportowanymi konkretnymi typami w zasadach platformy i odpowiednimi atrybutami wersjonowanymi dla każdej wersji platformy . Gwarantuje to, że gdy obiekty są oznaczone typem, nie zakłóca to zachowania gwarantowanego przez zasady platformy-public w poprzedniej wersji. To mapowanie jest utrzymywane przez aktualizowanie pliku mapowania dla każdej wersji platformy , który przechowuje informacje o członkostwie atrybutów dla każdego typu eksportowanego w ramach polityki publicznej.

Własność obiektu i etykietowanie

Podczas dostosowywania zasad w systemie Android 8.0 i nowszych należy jasno zdefiniować własność dla każdego obiektu, aby oddzielić zasady dotyczące platformy i dostawcy. Na przykład, jeśli dostawca oznaczy /dev/foo i platformę, a następnie oznaczy /dev/foo w kolejnej OTA, wystąpi niezdefiniowane zachowanie. W przypadku SELinux objawia się to kolizją etykietowania. Węzeł urządzenia może mieć tylko jedną etykietę, która odpowiada ostatniej nałożonej etykiecie. W rezultacie:

  • Procesy, które potrzebują dostępu do nieskutecznie zastosowanej etykiety, utracą dostęp do zasobu.
  • Procesy, które uzyskują 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 systemu (jak również etykietowaniem SELinux). 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, jasno określ własność tych obiektów.

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

Przestrzeń nazw typów/atrybutów

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 od np_ .

type foo, domain; → type np_foo, domain;

Własność systemu i własność etykietowania 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 eksportowanej 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 do zapisu vendor.
tylko czytać ro.vendor.
ro.boot.
ro.hardware.
trwały persist.vendor.

Sprzedawcy mogą nadal używać ro.boot.* (który pochodzi z cmdline jądra) i ro.hardware.* (oczywista właściwość związana ze sprzętem).

Wszystkie usługi dostawcy w inicjalnych plikach rc powinny mieć vendor. dla usług w plikach rc init partycji niesystemowych. Podobne reguły 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 często 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 tym kolizjom, postępuj zgodnie ze wskazówkami dotyczącymi nazewnictwa dla systemów plików w tej sekcji. W przypadku systemu Android 8.0 są to zalecenia bez wymuszania technicznego. W przyszłości zalecenia te będą egzekwowane przez Vendor Test Suite (VTS).

System (/system)

Tylko obraz systemu musi zawierać etykiety dla /system components za pośrednictwem file_contexts , service_contexts itp. Jeśli etykiety dla /system components zostaną dodane w zasadach /vendor , aktualizacja OTA tylko w ramach struktury może nie być możliwa.

Dostawca (/dostawca)

Polityka AOSP SELinux już określa części partycji vendor , z którymi platforma współpracuje, co umożliwia pisanie reguł SELinux dla procesów platformy, aby móc rozmawiać i/lub uzyskiwać dostęp do części partycji vendor . Przykłady:

/vendor Etykieta dostarczona 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 , idmap installd itp.
/vendor/overlay(/. * ) vendor_overlay_file system_server , zygote , idmap , itp.

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

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

Procs (/proc)

Pliki w /proc mogą być oznaczone tylko 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 etykietą domyślną ( proc ), zasady dostawcy nie powinny ich jawnie etykietować i zamiast tego powinny używać ogólnego typu proc , aby dodać reguły dla domen dostawców. Pozwala to aktualizacjom platformy na uwzględnienie przyszłych interfejsów jądra ujawnionych przez procfs i wyraźne oznaczenie ich zgodnie z potrzebami.

Debugfs (/sys/kernel/debug)

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

W systemie Android 11 debugfs nie można uzyskać dostępu ani zamontować 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 iw genfscon . W Androidzie 7.0 tylko platforma oznacza tracefs .

Zalecenie: tylko platforma może oznaczać znaczniki tracefs .

Sysfs (/sys)

Pliki w /sys mogą być etykietowane przy użyciu zarówno 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 , które nie są specyficzne dla urządzenia. W przeciwnym razie tylko dostawca może oznaczać pliki.

tmpfs (/dev)

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

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

Korzenie (/)

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

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

Dane (/dane)

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

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

Atrybuty zgodności

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

Polityka jest napisana głównie pod kątem istniejących typów:

allow source_type target_type:target_class permission(s);

To działa, ponieważ polityka została napisana ze znajomością wszystkich typów. Jeśli jednak zasady dostawcy i zasady platformy korzystają z określonych typów, a etykieta określonego obiektu zmienia się tylko w jednej z tych zasad, druga może zawierać zasady, do których dostęp był wcześniej zależny. 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 pozostaną takie same, v_domain utraciłaby dostęp z powodu braku zasad dla nowego typu sysfs_A .

Definiując politykę pod względem atrybutów, możemy nadać bazowemu obiektowi 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 dostarczane jako zasady publiczne platformy, które są tworzone jako część zasad dostawcy.

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

  • Upewnij się, że kod dostawcy nadal działa po aktualizacji platformy . Osiągany przez 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ść deprecjonowania polityki . Osiąga się to dzięki jasnemu określeniu zestawów zasad w atrybuty, które można usunąć, gdy tylko wersja, której odpowiadają, przestanie być obsługiwana. Rozwój może być kontynuowany na platformie, wiedząc, że stara polityka jest nadal obecna w polityce dostawcy i zostanie automatycznie usunięta po aktualizacji.

Zapisywalność polityki

Aby osiągnąć cel polegający na niewymaganiu znajomości konkretnych zmian wersji na potrzeby 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 jest wersją docelową. vN odpowiada zmiennej budowania PLATFORM_SEPOLICY_VERSION i ma postać MM.NN , gdzie MM odpowiada numerowi platformy SDK, a NN jest wersją specyficzną dla sepolityki platformy.

Atrybuty w zasadach publicznych nie są wersjonowane, ale raczej istnieją jako interfejs API, na którym można budować zasady platformy i dostawcy, aby utrzymać stabilny interfejs między dwiema partycjami. Zarówno twórcy zasad platformy, jak i dostawcy mogą nadal pisać zasady tak, jak są napisane dzisiaj.

Zasady publiczne platformy wyeksportowane jako allow source_foo target_bar: class perm ; jest częścią polityki dostawcy. Podczas kompilacji (która obejmuje odpowiednią wersję) jest przekształcana w politykę, która zostanie przekazana do części dostawcy urządzenia (pokazanej w przekształconym języku Common Intermediate Language (CIL)):

 (allow source_foo_vN target_bar_vN (class (perm)))

Ponieważ polityka dostawcy nigdy nie wyprzedza platformy, nie powinna dotyczyć wcześniejszych wersji. Jednak zasady platformy będą musiały wiedzieć, jak daleko wstecz są zasady dostawcy, uwzględniać atrybuty w ich typach i ustawiać zasady odpowiadające atrybutom wersjonowanym.

Różnice w polityce

Automatyczne tworzenie atrybutów przez dodanie _v N na końcu każdego typu nic nie daje bez mapowania atrybutów na typy w różnych wersjach. System Android obsługuje 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 opisano scenariusze uaktualnień platformy.

Te same typy

Ten scenariusz występuje, gdy obiekt nie zmienia etykiet w wersjach zasad. To samo dotyczy typów źródłowych i docelowych i można je zobaczyć za pomocą /dev/binder , który jest oznaczony jako binder_device we wszystkich wydaniach. Jest reprezentowany w przekształconej polityce jako:

binder_device_v1 … binder_device_vN

Podczas aktualizacji z wersji v1v2 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 polityce dostawcy v1 (CIL):

(typeattribute binder_device_v1)
(allow binder_device_v1 …)

W polityce dostawcy v2 (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 funkcja . Gdy typ oznacza obiekt, który wcześniej nie istniał (na przykład proces nowej usługi), kod dostawcy nie wchodził z nim w bezpośrednią interakcję, więc nie istnieje odpowiednia zasada. Nowy atrybut odpowiadający typowi nie ma atrybutu w poprzedniej wersji, a zatem nie wymaga wpisu w pliku odwzorowania dotyczącym tej wersji.
  • Zaostrzenie polityki . Gdy typ reprezentuje wzmocnienie strategii, nowy atrybut type musi być połączony z łańcuchem atrybutów odpowiadającym poprzedniemu (podobnie jak w poprzednim przykładzie zmieniającym /sys/A z sysfs na sysfs_A ). Kod dostawcy opiera się na regule umożliwiającej dostęp do sysfs i musi zawierać tę regułę jako atrybut nowego typu.

Podczas aktualizacji z wersji v1v2 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 polityce dostawcy v1 (CIL):

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

W polityce dostawcy v2 (CIL):

(typeattribute sysfs_A_v2)
(allow … sysfs_A_v2 …)
(typeattribute sysfs_v2)
(allow … sysfs_v2 …)
Usunięto 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 rozluźniania zasad typ jest usuwany, a obiekt oznaczony tym typem otrzymuje inną, już istniejącą etykietę. Reprezentuje to scalanie mapowań atrybutów: kod dostawcy musi nadal mieć dostęp do bazowego obiektu za pomocą atrybutu, który posiadał, ale reszta systemu musi teraz mieć dostęp do niego za pomocą nowego atrybutu.

Jeśli atrybut, na który został przełączony, jest nowy, to ponowne etykietowanie jest takie samo jak w przypadku nowego typu, z tym wyjątkiem, że gdy używana jest istniejąca etykieta, dodanie starego atrybutu nowy typ spowoduje, że inne obiekty również będą oznaczone tym typem być nowo dostępnym. Jest to zasadniczo to, co robi platforma i jest uważane za akceptowalny kompromis w celu utrzymania zgodności.

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Przykładowa wersja 1: typy zwijane (usuwanie sysfs_A)

Podczas aktualizacji z wersji v1v2 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 polityce dostawcy v1 (CIL):

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

W polityce dostawcy v2 (CIL):

(typeattribute sysfs_v2)
(allow … sysfs_v2 …)

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

Podczas aktualizacji z wersji v1v2 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 polityce dostawcy v1 (CIL):

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

W polityce dostawcy v2 (CIL):

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

Ten scenariusz ma miejsce, gdy uaktualnienie 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, znajdowania i wyświetlania listy, demony dostawcy, które chcą zarejestrować się w menedżerze servicemanager , potrzebowały uprawnień, które nie były dostępne. W systemie Android 8.0 tylko zasady platformy mogą dodawać nowe klasy i uprawnienia.

Aby umożliwić wszystkim domenom, które mogły zostać utworzone lub rozszerzone przez zasady dostawcy, korzystanie z nowej klasy bez przeszkód, zasady platformy muszą zawierać regułę podobną do:

allow {domain -coredomain} *:new_class perm;

Może to nawet wymagać zasad zezwalających na dostęp dla wszystkich typów interfejsów (polityka publiczna), aby mieć pewność, że obraz dostawcy uzyska dostęp. Jeśli spowoduje to nieakceptowalną politykę bezpieczeństwa (jak to może mieć w przypadku zmian w menedżerze usług), uaktualnienie dostawcy może być potencjalnie wymuszone.

Usunięto zajęcia/uprawnienia

Ten scenariusz ma miejsce, gdy menedżer obiektów zostanie usunięty (na przykład 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 przestanie ich używać. Odbywa się to poprzez dodanie definicji do odpowiedniego pliku mapowania.

Dostosowanie dostawcy do nowych/przemianowanych typów

Nowe typy dostawców są podstawą opracowywania polityki dostawców, ponieważ są potrzebne 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 oznaczonym w polityce dostawcy, ponieważ platforma nie ma o tym wiedzy; jednak 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 mogła nadal poprawnie współdziałać z tymi obiektami, atrybuty i typy muszą być odpowiednio zastosowane i może być konieczne dodanie określonych reguł do domen, które można dostosować (takich jak init ).

Zmiany atrybutów dla Androida 9

Urządzenia aktualizowane do systemu Android 9 mogą korzystać z następujących atrybutów, ale urządzenia uruchamiane z systemem Android 9 nie mogą.

Atrybuty naruszeń

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 między vendor a coredomains . Procesy platformy i dostawcy nie powinny używać plików na dysku do komunikacji (niestabilny ABI). Rekomendacje:
    • Kod dostawcy powinien używać /data/vendor .
    • System nie powinien używać /data/vendor .
  • system_executes_vendor_violators . Atrybut dla wszystkich domen systemowych (z wyjątkiem domen init i shell domains ), które naruszają wymóg niewykonania plików binarnych dostawcy. Wykonywanie plików binarnych dostawcy ma niestabilne 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 HAL HIDL.

      LUB

    • coredomains , które potrzebują dostępu do plików binarnych dostawcy, należy przenieść na partycję dostawcy, a tym samym przestać być coredomain .

Niezaufane 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 uzyskać dostęp z takich aplikacji (zobacz bezpieczne usługi poniżej). Dwa główne powody tego to:

  1. Serwery HwBinder nie przeprowadzają uwierzytelniania klienta, ponieważ HIDL obecnie nie ujawnia informacji UID wywołującego. Nawet jeśli HIDL ujawnił takie dane, wiele usług HwBinder działa na poziomie niższym niż poziom aplikacji (takich jak warstwy HAL) lub nie może polegać na tożsamości aplikacji w celu autoryzacji. Tym samym, dla bezpieczeństwa, domyślnym założeniem jest, że każda usługa HwBinder traktuje wszystkich swoich klientów jako równoprawnych do wykonywania operacji oferowanych przez usługę.
  2. Serwery HAL (podzbiór usług HwBinder) zawierają kod o wyższym wskaźniku występowania problemów z bezpieczeństwem niż komponenty system/core i mają dostęp do niższych warstw stosu (aż do sprzętu), co zwiększa możliwości obejś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, a zatem 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 #2.
  • hal_configstore_ISurfaceFlingerConfigs . Ta usługa jest specjalnie zaprojektowana do użytku przez dowolną domenę.
  • hal_graphics_allocator_hwservice . Te operacje są również oferowane przez usługę surfaceflinger Binder, do której aplikacje mają dostęp.
  • hal_omx_hwservice . Jest to wersja usługi mediacodec Binder firmy HwBinder, do której aplikacje mają dostęp.
  • hal_codec2_hwservice . To jest nowsza wersja hal_omx_hwservice .

Użyteczne atrybuty

Wszystkie hwservices 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 Androidem 9 NIE MOGĄ używać żadnego untrusted atrybutu.

Rekomendacje:

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

    LUB

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

Testy atrybutów plików

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

Platforma-polityka publiczna

Zasada platforma-public jest podstawą zgodności z modelem architektury Androida 8.0 bez po prostu utrzymywania unii zasad platformy z wersji v1 i v2. Dostawcy są narażeni na podzbiór zasad platformy, który zawiera użyteczne typy i atrybuty oraz reguły dotyczące tych typów i atrybutów, które następnie stają się częścią zasad dostawcy (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 dostarczane 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ć, że zasady dostawcy będą nadal działać i że uwzględnione są reguły przewidziane dla konkretnej wersji. Połączenie zasad dotyczących platform i dostawców spełnia cel modelu architektury systemu Android 8.0, jakim jest umożliwienie niezależnych kompilacji platform i dostawców.

Mapowanie do łańcuchów atrybutów

W przypadku używania atrybutów do mapowania na wersje zasad typ mapuje do atrybutu lub wielu atrybutów, zapewniając, że obiekty oznaczone typem są dostępne za pośrednictwem atrybutów odpowiadających ich poprzednim typom.

Utrzymanie celu, jakim jest ukrycie informacji o wersji przed autorem zasad, oznacza automatyczne generowanie wersjonowanych atrybutów i przypisywanie ich do odpowiednich typów. W typowym przypadku typów statycznych jest to proste: type_foo mapuje do type_foo_v1 .

W przypadku zmiany etykiety obiektu, takiej jak sysfssysfs_A lub audioservermediaserver , utworzenie tego mapowania nie jest trywialne (i zostało opisane w powyższych przykładach). Opiekunowie zasad platformy muszą określić, jak utworzyć mapowanie w punktach przejścia dla obiektów, co wymaga zrozumienia relacji między obiektami i przypisanymi im etykietami oraz określenia, kiedy to nastąpi. Aby zapewnić zgodność wsteczną, ta złożoność musi być zarządzana po stronie platformy, która jest jedyną partycją, która może ulec zmianie.

Wersja w górę

Dla uproszczenia platforma Android wydaje wersję sepolicy po wycięciu nowej gałęzi wydania. Jak opisano powyżej, numer wersji znajduje się 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. zawsze liczby całkowite. Na przykład, jeśli podbicie MR do wersji wymaga niezgodnej zmiany w system/sepolicy/public , ale nie podbicia API, wtedy ta wersja sepolicy może mieć postać: vN.1 . Wersja obecna w gałęzi deweloperskiej to 10000.0 , którego nigdy nie należy używać w urządzeniach wysyłkowych.

Android może wycofać najstarszą wersję podczas aktualizacji. Aby uzyskać dane wejściowe dotyczące tego, kiedy należy wycofać wersję, system Android może zbierać liczbę urządzeń z zasadami dostawcy, na których działa ta wersja systemu Android i nadal otrzymuje 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 braku pamięci podręcznej zasad.

Potwierdzono, że jest to problem w systemie Android, dlatego w systemie Android 8.0 wprowadzono zmiany w celu usunięcia atrybutów dodanych do zasad przez kompilator zasad, a także usunięcia nieużywanych atrybutów. Te zmiany rozwiązały regresję wydajności.

System_ext public i polityka publiczna produktu

Począwszy od systemu Android 11, partycje system_ext i produktu mogą eksportować wyznaczone typy publiczne do partycji dostawcy. Podobnie jak zasady publiczne platformy, dostawca używa typów i reguł automatycznie tłumaczonych na wersjonowane atrybuty, np. z type na type_ N , gdzie N jest wersją platformy, na 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 do system_ext/etc/selinux/mapping/ N .cil i product/etc/selinux/mapping/ N .cil , które zawierają tożsamość odwzorowania z type na type_ N . Dostawca może uzyskać dostęp do type za pomocą atrybutu wersjonowanego type_ N .

W przypadku, gdy aktualizowane są tylko partycje system_ext i produktu, powiedzmy od N do N+1 (lub później), podczas gdy dostawca pozostaje w N , dostawca może utracić dostęp do typów partycji system_ext i produktu. Aby zapobiec awariom, partycje system_ext i produktu powinny udostępniać pliki mapowania z konkretnych typów na atrybuty type_ N . Każdy partner jest odpowiedzialny za utrzymanie plików mapowania, jeśli ma wspierać dostawcę N z N+1 (lub nowszymi) partycjami system_ext i produktu.

W tym celu oczekuje się od partnerów:

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

Załóżmy na przykład, że N system_ext ma jeden typ publiczny o nazwie foo_type . Wtedy 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 jeśli bar_type powinien być zmapowany na foo_type dla dostawcy N , 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 bar_type .

Etykietowanie kontekstów SELinux

Aby wspierać rozróżnienie między platformą a polityką dostawcy, system buduje pliki kontekstowe SELinux w inny sposób, aby zachować ich odrębność.

Konteksty plików

Android 8.0 wprowadził następujące zmiany dla file_contexts :

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

Konteksty właściwości

W systemie Android 8.0 property_contexts jest podzielona na dwa pliki:

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

Konteksty usług

W systemie Android 8.0 service_contexts jest dzielony między następujące pliki:

  • plat_service_contexts
    • service_context specyficzny dla platformy Android dla menedżera servicemanager . service_context nie ma etykiet specyficznych dla urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/plat_service_contexts i być załadowany przez servicemanager na początku wraz z dostawcą service_contexts .
  • vendor_service_contexts
    • service_contexts service_context w katalogach wskazywanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się w partycji vendor w /vendor/etc/selinux/vendor_service_contexts i być załadowany przez servicemanager na początku wraz z platformą service_contexts .
    • Chociaż servicemanager szuka tego pliku podczas rozruchu, dla w pełni zgodnego urządzenia TREBLE , vendor_service_contexts NIE MOŻE istnieć. Dzieje się tak, ponieważ wszystkie interakcje między vendor a procesami system MUSZĄ przechodzić przez hwservicemanager / hwbinder .
  • plat_hwservice_contexts
    • Platforma Android hwservice_context dla hwservicemanager , która nie ma etykiet specyficznych dla urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/plat_hwservice_contexts i być załadowany przez hwservicemanager na początku wraz z vendor_hwservice_contexts .
  • vendor_hwservice_contexts
    • hwservice_context specyficzny dla urządzenia zbudowany przez połączenie hwservice_contexts znalezionych w katalogach wskazywanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się w partycji vendor w /vendor/etc/selinux/vendor_hwservice_contexts i być załadowany przez hwservicemanager na początku wraz z plat_service_contexts .
  • vndservice_contexts
    • service_context specyficzny dla urządzenia dla vndservicemanager zbudowany przez połączenie vndservice_contexts znalezionych w katalogach wskazywanych przez BOARD_SEPOLICY_DIRS w urządzeniu Boardconfig.mk .
    • Ten plik musi znajdować się na partycji vendor w /vendor/etc/selinux/vndservice_contexts i zostać załadowany przez vndservicemanager na początku.

Konteksty Seapp

W systemie Android 8.0 seapp_contexts jest podzielony na dwa pliki:

  • plat_seapp_contexts
    • seapp_context platformy Android, na której nie ma zmian dotyczących konkretnego urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • Rozszerzenie specyficzne dla urządzenia dla platformy seapp_context zbudowane przez połączenie seapp_contexts znalezionych w katalogach wskazywanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się na partycji vendor w /vendor/etc/selinux/vendor_seapp_contexts .

Uprawnienia MAC

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

  • Platforma mac_permissions.xml
    • Platforma Android mac_permissions.xml , która nie zawiera żadnych zmian dotyczących konkretnego urządzenia.
    • Musi znajdować się na partycji system w /system/etc/selinux/.
  • mac_permissions.xml
    • Specyficzne dla urządzenia rozszerzenie platformy mac_permissions.xml utworzone na podstawie mac_permissions.xml znajdującego się w katalogach wskazywanych przez BOARD_SEPOLICY_DIRS w plikach Boardconfig.mk urządzenia.
    • Musi znajdować się na partycji vendor w /vendor/etc/selinux/.