Inicjacja dostawcy

Proces init ma niemal nieograniczone uprawnienia i używa skryptów wejściowych z partycji systemowej i partycji dostawcy do inicjowania systemu podczas procesu uruchamiania. Ten dostęp powoduje dużą lukę w podziale systemu i 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 dostawcy.

Vendor init ma na celu załatanie tej luki poprzez użycie oddzielnej domeny vendor_init systemu Linux z ulepszonymi zabezpieczeniami (SELinux) do uruchamiania poleceń znajdujących się w /vendor z uprawnieniami specyficznymi dla dostawcy.

Mechanizm

Proces init dostawcy 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.

Skrypt init sprawdza każdy wczytywany skrypt, aby ustalić, czy jego ścieżka zaczyna się od znaku /vendor. Jeśli tak, oznacza go jako skrypt, którego polecenia muszą być uruchamiane w kontekście init dostawcy. Każda wbudowana funkcja init jest opatrzona adnotacją w postaci wartości logicznej, która określa, czy polecenie musi być uruchomione w podprocesie init dostawcy:

  • Większość poleceń, które uzyskują dostęp do systemu plików, jest oznaczona adnotacjami, aby były uruchamiane w podprocesie init dostawcy, a tym samym podlegały zasadom SEPolicy init dostawcy.
  • Większość poleceń, które wpływają na wewnętrzny stan inicjowania (np. uruchamianie i zatrzymywanie usług), jest wykonywana w ramach normalnego procesu inicjowania. Te polecenia są informowane, że skrypt dostawcy wywołuje je w celu obsługi uprawnień innych niż SELinux.

Główna pętla przetwarzania procesu init zawiera sprawdzenie, czy polecenie jest oznaczone adnotacją wskazującą, że ma być uruchomione w podprocesie dostawcy, i czy pochodzi ze skryptu dostawcy. Jeśli tak, polecenie jest wysyłane za pomocą komunikacji międzyprocesowej (IPC) do podprocesu init dostawcy, który uruchamia polecenie i wysyła wynik z powrotem do procesu init.

Użyj inicjowania przez dostawcę

Inicjowanie przez dostawcę jest domyślnie włączone, a jego ograniczenia dotyczą wszystkich skryptów inicjujących znajdujących się w partycji /vendor. Inicjowanie dostawcy powinno być przejrzyste dla dostawców, których skrypty nie mają już dostępu do plików, właściwości itp. dostępnych tylko w systemie.

Jeśli jednak polecenia w skrypcie dostawcy naruszają ograniczenia dotyczące inicjowania dostawcy, nie zostaną wykonane. Nieudane polecenia mają w logu jądra (widocznym za pomocą polecenia dmesg) wiersz z procesu init wskazujący na błąd. W przypadku każdego polecenia, które nie zostało wykonane z powodu zasad SELinux, dołączany jest audyt SELinux. Przykład błędu obejmującego kontrolę 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 powiedzie się, masz 2 możliwości:

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

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

Lokalizacje kodu

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

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

Plik SEPolicy dla procesu init dostawcy jest podzielony na katalogi prywatny (system/sepolicy/private/vendor_init.te) i publiczny (system/sepolicy/public/vendor_init.te) w katalogu system/sepolicy.