Inicjacja dostawcy

Proces init ma niemal nieograniczone uprawnienia i używa skryptów wejściowych z partycji systemowej i partycji dostawcy, aby zainicjować system podczas procesu uruchamiania. Ten dostęp powoduje ogromną lukę w podziale systemu/dostawcy w Treble, ponieważ skrypty dostawcy mogą instruować proces init, aby uzyskiwał dostęp do plików, właściwości itp., które nie są częścią stabilnego interfejsu ABI aplikacji systemowej i dostawcy.

Vendor init ma na celu załatanie tej luki przez użycie oddzielnej domeny SELinux vendor_init, aby uruchamiać polecenia znajdujące się w /vendor z uprawnieniami specyficznymi dla dostawcy.

Mechanizm

Vendor init rozwidla podproces init na wczesnym etapie procesu uruchamiania z kontekstem SELinux u:r:vendor_init:s0. Ten kontekst SELinux ma znacznie mniej uprawnień niż domyślny kontekst init, a jego dostęp jest ograniczony do plików, właściwości itp., które są specyficzne dla dostawcy lub stanowią część stabilnego interfejsu ABI systemu i dostawcy.

Proces init sprawdza każdy wczytywany skrypt, aby sprawdzić, czy jego ścieżka zaczyna się od /vendor. Jeśli tak, oznacza go informacją, że jego polecenia muszą być uruchamiane w kontekście vendor init. Każda wbudowana funkcja init jest opatrzona wartością logiczną, która określa, czy polecenie musi być uruchamiane w podprocesie vendor init:

  • Większość poleceń, które uzyskują dostęp do systemu plików, jest oznaczona jako uruchamiane w podprocesie vendor init, a zatem podlegają zasadom SEPolicy vendor init.
  • Większość poleceń, które wpływają na wewnętrzny stan init (np. uruchamianie i zatrzymywanie usług), jest uruchamiana w normalnym procesie init. Te polecenia są informowane że wywołuje je skrypt dostawcy, aby wykonywać własną obsługę uprawnień innych niż SELinux

Główna pętla przetwarzania init zawiera sprawdzenie, czy polecenie jest oznaczone jako uruchamiane w podprocesie dostawcy i pochodzi ze skryptu dostawcy. Jeśli tak, polecenie jest wysyłane za pomocą komunikacji międzyprocesowej (IPC) do podprocesu vendor init, który uruchamia polecenie i odsyła wynik do procesu init.

Używanie vendor init

Vendor init jest domyślnie włączony, a jego ograniczenia dotyczą wszystkich skryptów init znajdujących się w partycji /vendor. Vendor init powinien być niewidoczny dla dostawców, których skrypty nie uzyskują już dostępu do plików, właściwości itp. tylko w systemie.

Jeśli jednak polecenia w danym skrypcie dostawcy naruszają ograniczenia vendor init, polecenia nie działają. Nieudane polecenia mają w logu jądra (widocznym za pomocą dmesg) wiersz z procesu init wskazujący na błąd. Każdemu nieudanemu poleceniu, które nie powiodło się z powodu zasad SELinux, towarzyszy audyt SELinux. Przykład błędu, w tym audytu SELinux:

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

Jeśli polecenie nie działa, masz 2 opcje:

  • Jeśli polecenie nie działa z powodu zamierzonego ograniczenia (np. jeśli polecenie uzyskuje dostęp do pliku lub właściwości systemowej), należy je ponownie zaimplementować w sposób zgodny z Treble, korzystając tylko ze stabilnych interfejsów. Reguły neverallow uniemożliwiają dodawanie uprawnień do uzyskiwania dostępu do plików systemowych, które nie są częścią stabilnego interfejsu ABI systemu i dostawcy.
  • Jeśli etykieta SELinux jest nowa i nie ma jeszcze przyznanych uprawnień w systemowym pliku vendor_init.te ani wykluczonych uprawnień za pomocą reguł neverallow, nowa etykieta może otrzymać uprawnienia w pliku vendor_init.te specyficznym dla urządzenia.

W przypadku urządzeń wprowadzanych na rynek przed Androidem 9 reguły neverallow można obejść, dodając atrybut typu data_between_core_and_vendor_violators do pliku vendor_init.te specyficznego dla urządzenia.

Lokalizacje kodu

Większość logiki IPC vendor init znajduje się w system/core/init/subcontext.cpp.

Tabela poleceń znajduje się w klasie BuiltinFunctionMap w system/core/init/builtins.cpp i zawiera adnotacje wskazujące, czy polecenie musi być uruchamiane w podprocesie vendor init.

Zasady SEPolicy dla vendor init są podzielone na katalogi prywatny (system/sepolicy/private/vendor_init.te) i publiczny (system/sepolicy/public/vendor_init.te) w system/sepolicy.