Anbieter-Init

Der Init-Prozess hat nahezu uneingeschränkte Berechtigungen und verwendet Eingabeskripts sowohl von der System- als auch von der Anbieterpartition, um das System während des Bootvorgangs zu initialisieren. Dieser Zugriff verursacht eine große Lücke in der Trennung zwischen Treble-System und ‑Anbieter, da Anbieter-Scripts init anweisen können, auf Dateien, Eigenschaften usw. zuzugreifen, die nicht Teil des stabilen ABI (Application Binary Interface) zwischen System und Anbieter sind.

Vendor-Init wurde entwickelt, um diese Lücke zu schließen. Dazu wird eine separate Security-Enhanced Linux-Domain (SELinux) vendor_init verwendet, um Befehle auszuführen, die in /vendor mit anbieterspezifischen Berechtigungen gefunden werden.

Mechanismus

Vendor-Init forkt einen Unterprozess von Init früh im Bootvorgang mit dem SELinux-Kontext u:r:vendor_init:s0. Dieser SELinux-Kontext hat wesentlich weniger Berechtigungen als der Standard-Init-Kontext und sein Zugriff ist auf Dateien, Eigenschaften usw. beschränkt, die entweder anbieterspezifisch sind oder Teil des stabilen System-Vendor-ABI sind.

Init prüft jedes geladene Skript, ob sein Pfad mit /vendor beginnt. Wenn dies der Fall ist, wird es mit einem Hinweis versehen, dass seine Befehle im Vendor-Init-Kontext ausgeführt werden müssen. Jedes integrierte Init wird mit einem booleschen Wert annotiert, der angibt, ob der Befehl im Vendor-Init-Unterprozess ausgeführt werden muss:

  • Die meisten Befehle, die auf das Dateisystem zugreifen, sind so annotiert, dass sie im Vendor-Init-Unterprozess ausgeführt werden. Daher unterliegen sie der Vendor-Init-SEPolicy.
  • Die meisten Befehle, die sich auf den internen Initialisierungsstatus auswirken (z.B. das Starten und Beenden von Diensten), werden im normalen Initialisierungsprozess ausgeführt. Diese Befehle wissen, dass sie von einem Anbieterskript aufgerufen werden, um ihre eigene Berechtigungsverwaltung ohne SELinux durchzuführen.

Die Hauptverarbeitungsschleife von init enthält eine Prüfung, ob ein Befehl, der für die Ausführung im Vendor-Unterprozess vorgesehen ist und aus einem Vendor-Script stammt, über die Interprozesskommunikation (IPC) an den Vendor-init-Unterprozess gesendet wird. Dieser führt den Befehl aus und sendet das Ergebnis zurück an init.

Vendor-Init verwenden

Die Anbieterinitialisierung ist standardmäßig aktiviert und ihre Einschränkungen gelten für alle Initialisierungsskripts in der Partition /vendor. Die Initialisierung des Anbieters sollte für Anbieter transparent sein, deren Skripts bereits nicht auf reine Systemdateien, ‑properties usw. zugreifen.

Wenn Befehle in einem bestimmten Anbieterskript jedoch gegen die Einschränkungen für die Anbieterinitialisierung verstoßen, schlagen die Befehle fehl. Fehlerhafte Befehle haben eine Zeile im Kernel-Log (sichtbar mit dmesg) von init, die auf einen Fehler hinweist. Jeder Befehl, der aufgrund der SELinux-Richtlinie fehlgeschlagen ist, wird von einem SELinux-Audit begleitet. Beispiel für einen Fehler mit einem SELinux-Audit:

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

Wenn ein Befehl fehlschlägt, haben Sie zwei Möglichkeiten:

  • Wenn der Befehl aufgrund einer beabsichtigten Einschränkung fehlschlägt (z. B. wenn der Befehl auf eine Systemdatei oder ‑eigenschaft zugreift), muss er auf Treble-kompatible Weise neu implementiert werden und darf nur stabile Schnittstellen verwenden. „Neverallow“-Regeln verhindern, dass Berechtigungen für den Zugriff auf Systemdateien hinzugefügt werden, die nicht Teil des stabilen ABI für Systemanbieter sind.
  • Wenn das SELinux-Label neu ist und ihm im System vendor_init.te noch keine Berechtigungen gewährt wurden und es auch nicht durch die „neverallow“-Regeln ausgeschlossen wurde, können dem neuen Label Berechtigungen im gerätespezifischen vendor_init.te gewährt werden.

Bei Geräten, die vor Android 9 auf den Markt kommen, können die „neverallows“-Regeln umgangen werden, indem das Typattribut data_between_core_and_vendor_violators in die gerätespezifische Datei vendor_init.te eingefügt wird.

Codespeicherorte

Der Großteil der Logik für den IPC zur Initialisierung des Anbieters befindet sich in system/core/init/subcontext.cpp.

Die Tabelle der Befehle befindet sich in der Klasse BuiltinFunctionMap in system/core/init/builtins.cpp und enthält Anmerkungen, die angeben, ob der Befehl im Vendor-Init-Unterprozess ausgeführt werden muss.

Die SEPolicy für die Anbieterinitialisierung ist in den privaten (system/sepolicy/private/vendor_init.te) und öffentlichen (system/sepolicy/public/vendor_init.te) Verzeichnissen in system/sepolicy aufgeteilt.