SELinux-Richtlinie erstellen

Auf dieser Seite wird beschrieben, wie SELinux-Richtlinien erstellt werden. Die SELinux-Richtlinie wird aus der Kombination aus der AOSP-Kernrichtlinie (Plattform) und der gerätespezifischen Richtlinie (Anbieter) erstellt. Beim SELinux-Richtlinien-Build-Ablauf für Android 4.4 bis Android 7.0 wurden alle sepolicy-Fragmente zusammengeführt und dann monolithische Dateien im Stammverzeichnis generiert. Das bedeutete, dass SoC-Anbieter und ODM-Hersteller boot.img (für Nicht-A/B-Geräte) oder system.img (für A/B-Geräte) jedes Mal ändern mussten, wenn die Richtlinie geändert wurde.

Unter Android 8.0 und höher werden Plattform- und Anbieterrichtlinien separat erstellt. SOCs und OEMs können ihre Teile der Richtlinie aktualisieren, ihre Images (z. B. vendor.img und boot.img) erstellen und diese Images dann unabhängig von Plattformupdates aktualisieren.

Da die modularisierten SELinux-Richtliniendateien jedoch auf /vendor-Partitionen gespeichert sind, muss der init-Prozess die System- und Anbieterpartitionen früher einbinden, damit er SELinux-Dateien aus diesen Partitionen lesen und mit den SELinux-Kerndateien im Systemverzeichnis zusammenführen kann, bevor er sie in den Kernel lädt.

Quelldateien

Die Logik zum Erstellen von SELinux befindet sich in diesen Dateien:

  • external/selinux: Externes SELinux-Projekt, das zum Erstellen von HOST-Befehlszeilenprogrammen zum Kompilieren von SELinux-Richtlinien und -Labels verwendet wird.
    • external/selinux/libselinux: Android verwendet nur eine Teilmenge des externen libselinux-Projekts sowie einige Android-spezifische Anpassungen. Weitere Informationen finden Sie unter external/selinux/README.android.
    • external/selinux/libsepol:
      • chkcon: Ermittelt, ob ein Sicherheitskontext für eine bestimmte binäre Richtlinie (Host-Executable) gültig ist.
      • libsepol: SELinux-Bibliothek zum Bearbeiten binärer Sicherheitsrichtlinien (statische/gemeinsam genutzte Hostbibliothek, statische Zielbibliothek).
    • external/selinux/checkpolicy: SELinux-Richtliniencompiler (Host-Ausführungsdateien: checkpolicy, checkmodule, und dispol). Hängt von libsepol ab.
  • system/sepolicy: Core-Android-SELinux-Richtlinienkonfigurationen, einschließlich Kontexten und Richtliniendateien. Die Hauptlogik für die Erstellung von sepolicy befindet sich ebenfalls hier (system/sepolicy/Android.mk).

Weitere Informationen zu den Dateien in system/sepolicy finden Sie unter SELinux implementieren.

Android 7.x und niedriger

In diesem Abschnitt wird beschrieben, wie SELinux-Richtlinien in Android 7.x und niedriger erstellt werden.

Build-Prozess für Android 7.x und niedriger

Die SELinux-Richtlinie wird durch Kombinieren der AOSP-Kernrichtlinie mit gerätespezifischen Anpassungen erstellt. Die kombinierte Richtlinie wird dann an den Richtlinien-Compiler und verschiedene Prüfungen übergeben. Die gerätespezifische Anpassung erfolgt über die Variable BOARD_SEPOLICY_DIRS, die in der gerätespezifischen Datei Boardconfig.mk definiert ist. Diese globale Build-Variable enthält eine Liste von Verzeichnissen, die die Reihenfolge angeben, in der nach zusätzlichen Richtliniendateien gesucht werden soll.

Beispielsweise können ein SoC-Anbieter und ein ODM jeweils ein Verzeichnis hinzufügen, eines für die SoC-spezifischen Einstellungen und eines für die gerätespezifischen Einstellungen, um die endgültigen SELinux-Konfigurationen für ein bestimmtes Gerät zu generieren:

  • BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

Der Inhalt der file_contexts-Dateien in system/sepolicy und BOARD_SEPOLICY_DIRS wird verkettet, um die file_contexts.bin auf dem Gerät zu generieren:

Dieses Bild zeigt die SELinux-Build-Logik für Android 7.x.

Abbildung 1: SELinux-Build-Logik.

Die Datei sepolicy besteht aus mehreren Quelldateien:

  • Der Nur-Text policy.conf wird durch Verketten der Dateien security_classes, initial_sids, *.te, genfs_contexts und port_contexts in dieser Reihenfolge generiert.
  • Der Inhalt jeder Datei (z. B. security_classes) ist die Verkettung der Dateien mit demselben Namen unter system/sepolicy/ und BOARDS_SEPOLICY_DIRS.
  • Die policy.conf wird zur Syntaxprüfung an den SELinux-Compiler gesendet und auf dem Gerät als sepolicy in ein Binärformat kompiliert.
    Dieses Bild zeigt die Dateien, mit denen die SELinux-Richtliniendatei für Android 7.x generiert wird.

    Abbildung 2: SELinux-Richtliniendatei.

SELinux-Dateien

Nach der Kompilierung enthalten Android-Geräte mit Version 7.x und früher in der Regel die folgenden SELinux-bezogenen Dateien:

  • selinux_version
  • sepolicy: Binäre Ausgabe nach dem Kombinieren von Richtliniendateien (z. B. security_classes, initial_sids und *.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

Weitere Informationen finden Sie unter SELinux implementieren.

SELinux-Initialisierung

Beim Hochfahren des Systems befindet sich SELinux im permissiven Modus (und nicht im Erzwingungsmodus). Der Init-Prozess führt die folgenden Aufgaben aus:

  • Lädt sepolicy-Dateien über /sys/fs/selinux/load aus der RAM-Disk in den Kernel.
  • Wechselt SELinux in den Erzwingungsmodus.
  • Führt re-exec() aus, um die SELinux-Domainregel auf sich selbst anzuwenden.

Um die Bootzeit zu verkürzen, führen Sie die re-exec() für den init-Prozess so schnell wie möglich aus.

Android 8.0 oder höher

In Android 8.0 wird die SELinux-Richtlinie in Plattform- und Anbieterkomponenten aufgeteilt, um unabhängige Plattform-/Anbieterrichtlinien-Updates zu ermöglichen und gleichzeitig die Kompatibilität aufrechtzuerhalten.

Die Plattform-SELinux-Richtlinie ist in private und öffentliche Teile unterteilt, um bestimmte Typen und Attribute für Anbieterrichtlinien-Autoren zu exportieren. Die öffentlichen Typen/Attribute der Plattform werden für eine bestimmte Plattformversion garantiert als stabile APIs beibehalten. Die Kompatibilität mit früheren öffentlichen Typen/Attributen der Plattform kann für mehrere Versionen mithilfe von Plattformzuordnungsdateien garantiert werden.

Build-Prozess für Android 8.0

Die SELinux-Richtlinie in Android 8.0 wird durch Kombinieren von Teilen aus /system und /vendor erstellt. Die Logik für die entsprechende Einrichtung befindet sich in /platform/system/sepolicy/Android.mk.

Die Richtlinie ist an den folgenden Stellen verfügbar:

Standort Enthält
system/sepolicy/public Die sepolicy-API der Plattform
system/sepolicy/private Details zur Plattformimplementierung (für Anbieter nicht relevant)
system/sepolicy/vendor Richtlinien- und Kontextdateien, die Anbieter verwenden können (Anbieter können sie bei Bedarf ignorieren)
BOARD_SEPOLICY_DIRS Anbieter-sepolicy
BOARD_ODM_SEPOLICY_DIRS (Android 9 und höher) Odm sepolicy
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 und höher) System_ext-SEPolicy-API
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 und höher) Implementierungsdetails für „system_ext“ (können von Anbietern ignoriert werden)
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 und höher) sepolicy API des Produkts
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 und höher) Details zur Produktimplementierung (können von Anbietern ignoriert werden)

Das Build-System verwendet diese Richtlinie und erstellt Richtlinienkomponenten für System, system_ext, Produkt, Anbieter und ODM auf der entsprechenden Partition. Erforderliche Schritte:

  1. Richtlinien in das SELinux Common Intermediate Language (CIL)-Format konvertieren, insbesondere:
    1. Richtlinie für öffentliche Plattformen (System + System_Ext + Produkt)
    2. Kombinierte private und öffentliche Richtlinie
    3. öffentlich + Anbieter und BOARD_SEPOLICY_DIRS-Richtlinie
  2. Die von der Öffentlichkeit bereitgestellte Richtlinie wird als Teil der Anbieterrichtlinie versioniert. Dazu wird die erstellte öffentliche CIL-Richtlinie verwendet, um die kombinierte öffentliche + Anbieter- + BOARD_SEPOLICY_DIRS-Richtlinie darüber zu informieren, welche Teile in Attribute umgewandelt werden müssen, die mit der Plattformrichtlinie verknüpft werden.
  3. Erstellen einer Zuordnungsdatei, in der die Plattform- und Anbieterteile verknüpft werden. Anfangs werden nur die Typen aus der öffentlichen Richtlinie mit den entsprechenden Attributen in der Anbieterrichtlinie verknüpft. Später wird auch die Grundlage für die Datei in zukünftigen Plattformversionen bereitgestellt, um die Kompatibilität mit der Anbieterrichtlinie für diese Plattformversion zu ermöglichen.
  4. Kombinieren von Richtliniendateien (sowohl On-Device- als auch vorkompilierte Lösungen beschreiben).
    1. Kombinieren Sie die Richtlinien für Mapping, Plattform und Anbieter.
    2. Kompilieren Sie die binäre Ausgabedatei für die Richtlinie.

Öffentliche SEPolicy der Plattform

Die öffentliche SELinux-Richtlinie der Plattform umfasst alles, was unter system/sepolicy/public definiert ist. Die Plattform kann davon ausgehen, dass die unter „Öffentliche Richtlinie“ definierten Typen und Attribute stabile APIs für eine bestimmte Plattformversion sind. Dies ist der Teil der sepolicy, der von der Plattform exportiert wird, auf der Entwickler von Vendor-Richtlinien (d. h. Geräte-) zusätzliche gerätespezifische Richtlinien schreiben können.

Die Typen werden entsprechend der Version der Richtlinie, für die Anbieterdateien geschrieben werden, versioniert. Diese Version wird durch die Build-Variable PLATFORM_SEPOLICY_VERSION definiert. Die versionierte öffentliche Richtlinie wird dann in die Händlerrichtlinie und (in ihrer ursprünglichen Form) in die Plattformrichtlinie aufgenommen. Die endgültige Richtlinie umfasst also die private Plattformrichtlinie, die öffentliche SELinux-Richtlinie der aktuellen Plattform, die gerätespezifische Richtlinie und die versionierte öffentliche Richtlinie, die der Plattformversion entspricht, für die die Geräterichtlinie geschrieben wurde.

Plattform-private SELinux-Richtlinie

Die private SELinux-Richtlinie der Plattform umfasst alles, was unter /system/sepolicy/private definiert ist. Dieser Teil der Richtlinie umfasst nur Typen, Berechtigungen und Attribute, die für die Plattformfunktionen erforderlich sind. Diese werden nicht an die vendor/device-Richtlinienautoren exportiert. Richtlinienautoren, die nicht zur Plattform gehören, dürfen ihre Richtlinienerweiterungen nicht auf Typen, Attributen oder Regeln basieren, die in der privaten SEPolicy der Plattform definiert sind. Außerdem können diese Regeln im Rahmen eines reinen Framework-Updates geändert werden oder verschwinden.

Private Zuordnung auf der Plattform

Die private Plattformzuordnung enthält Richtlinienanweisungen, die die Attribute, die in der öffentlichen Richtlinie der vorherigen Plattformversionen verfügbar gemacht wurden, den konkreten Typen zuordnen, die in der aktuellen öffentlichen Plattform-SELinux-Richtlinie verwendet werden. So wird sichergestellt, dass die Anbieterrichtlinie, die auf Grundlage der öffentlichen Plattformattribute aus der/den vorherigen öffentlichen SELinux-Version(en) der Plattform geschrieben wurde, weiterhin funktioniert. Die Versionsverwaltung basiert auf der Build-Variablen PLATFORM_SEPOLICY_VERSION, die in AOSP für eine bestimmte Plattformversion festgelegt ist. Für jede frühere Plattformversion, von der erwartet wird, dass diese Plattform die Richtlinie für Anbieter akzeptiert, ist eine separate Zuordnungsdatei vorhanden. Weitere Informationen finden Sie unter Kompatibilität.

Android 11 oder höher

system_ext- und Produkt-SELinux-Richtlinien

In Android 11 werden die Richtlinien „system_ext“ und „product“ hinzugefügt. Wie die Plattform-SE-Richtlinie werden auch die System-Ext-Richtlinie und die Produktrichtlinie in öffentliche und private Richtlinien unterteilt.

Die öffentliche Richtlinie wird an den Anbieter exportiert. Typen und Attribute werden zu einer stabilen API und die Anbieterrichtlinie kann sich auf Typen und Attribute in der öffentlichen Richtlinie beziehen. Die Typen werden gemäß PLATFORM_SEPOLICY_VERSION versioniert und die versionierte Richtlinie wird in die Anbieterrichtlinie aufgenommen. Die ursprüngliche Richtlinie ist in jeder System- und Produktpartition enthalten.

Die private Richtlinie enthält Typen, Berechtigungen und Attribute, die nur für system_ext und nur für Produkte gelten und für die Funktionalität von system_ext- und Produktpartitionen erforderlich sind. Die private Richtlinie ist für den Anbieter nicht sichtbar. Das bedeutet, dass diese Regeln intern sind und geändert werden dürfen.

system_ext- und Produktzuordnung

system_ext und product dürfen ihre öffentlichen Typen für den Anbieter exportieren. Die Verantwortung für die Aufrechterhaltung der Kompatibilität liegt jedoch bei jedem Partner selbst. Zur Kompatibilität können Partner eigene Zuordnungsdateien bereitstellen, in denen die versionierten Attribute früherer Versionen konkreten Typen zugeordnet werden, die in der aktuellen öffentlichen SELinux-Richtlinie verwendet werden.

  • Wenn Sie eine Zuordnungsdatei für system_ext installieren möchten, legen Sie eine CIL-Datei mit den gewünschten Zuordnungsinformationen in {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil ab und fügen Sie dann system_ext_{ver}.cil zu PRODUCT_PACKAGES hinzu.
  • Wenn Sie eine Zuordnungsdatei für ein Produkt installieren möchten, legen Sie eine CIL-Datei mit den gewünschten Zuordnungsinformationen in {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil ab und fügen Sie dann product_{ver}.cil zu PRODUCT_PACKAGES hinzu.

Hier finden Sie ein Beispiel, in dem eine Zuordnungsdatei für die Produktunterteilung des Redbull-Geräts hinzugefügt wird.

Vorkompilierte SELinux-Richtlinie

Bevor init SELinux aktiviert, werden alle CIL-Dateien aus Partitionen (system, system_ext, product, vendor und odm) von init erfasst und in eine binäre Richtlinie kompiliert, die in den Kernel geladen werden kann. Da die Kompilierung Zeit in Anspruch nimmt (normalerweise 1–2 Sekunden), werden die CIL-Dateien zur Build-Zeit vorkompiliert und entweder unter /vendor/etc/selinux/precompiled_sepolicy oder /odm/etc/selinux/precompiled_sepolicy abgelegt, zusammen mit den SHA256-Hashes der CIL-Eingabedateien. Zur Laufzeit wird mit init geprüft, ob eine der Richtliniendateien aktualisiert wurde. Dazu werden die Hashes verglichen. Wenn sich nichts geändert hat, wird die vorkompilierte Richtlinie von init geladen. Andernfalls wird init spontan kompiliert und anstelle der vorkompilierten Version verwendet.

Genauer gesagt wird die vorkompilierte Richtlinie verwendet, wenn alle folgenden Bedingungen erfüllt sind. Dabei steht {partition} für die Partition, in der die vorkompilierte Richtlinie vorhanden ist: entweder vendor oder odm.

  • Sowohl /system/etc/selinux/plat_sepolicy_and_mapping.sha256 als auch /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 sind vorhanden und identisch.
  • Sowohl /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 als auch /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 sind nicht vorhanden. Oder beide sind vorhanden und identisch.
  • Sowohl /product/etc/selinux/product_sepolicy_and_mapping.sha256 als auch /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 sind nicht vorhanden. Oder beide sind vorhanden und identisch.

Wenn sich einer der Werte unterscheidet, greift init auf den Kompilierungspfad auf dem Gerät zurück. Weitere Informationen finden Sie unter system/core/init/selinux.cpp.