SELinux implementieren

SELinux ist so konfiguriert, dass standardmäßig alle Zugriffe abgelehnt werden. Das bedeutet, dass jeder einzelne Zugriff, für den es einen Hook im Kernel gibt, explizit durch die Richtlinie zugelassen werden muss. Das bedeutet, dass eine Richtliniendatei eine große Menge an Informationen zu Regeln, Typen, Klassen, Berechtigungen usw. enthält. Eine vollständige Betrachtung von SELinux fällt nicht in den Rahmen dieses Dokuments. Das Wissen, wie Richtlinienregeln geschrieben werden, ist jedoch bei der Einrichtung neuer Android-Geräte unerlässlich. Es gibt bereits viele Informationen zu SELinux. Unter Unterstützende Dokumentation finden Sie Vorschläge für Ressourcen.

Schlüsseldateien

Wenn Sie SELinux aktivieren möchten, integrieren Sie den aktuellen Android-Kernel und fügen Sie dann die Dateien aus dem Verzeichnis system/sepolicy ein. Nach der Kompilierung enthalten diese Dateien die SELinux-Kernelsicherheitsrichtlinie und decken das Upstream-Android-Betriebssystem ab.

Im Allgemeinen sollten Sie die system/sepolicy-Dateien nicht direkt ändern. Fügen Sie stattdessen Ihre eigenen gerätespezifischen Richtliniendateien im Verzeichnis /device/manufacturer/device-name/sepolicy hinzu oder bearbeiten Sie sie. Unter Android 8.0 und höher sollten sich die Änderungen, die Sie an diesen Dateien vornehmen, nur auf die Richtlinie in Ihrem Anbieterverzeichnis auswirken. Weitere Informationen zur Trennung der öffentlichen SEPolicy in Android 8.0 und höher finden Sie unter SEPolicy in Android 8.0 und höher anpassen. Unabhängig von der Android-Version ändern Sie weiterhin die folgenden Dateien:

Richtliniendateien

Dateien, die auf *.te enden, sind SELinux-Richtlinienquellendateien, in denen Domains und ihre Labels definiert werden. Möglicherweise müssen Sie neue Richtliniendateien in /device/manufacturer/device-name/sepolicy erstellen. Versuchen Sie jedoch nach Möglichkeit, vorhandene Dateien zu aktualisieren.

Kontextdateien

In Kontextdateien geben Sie Labels für Ihre Objekte an.

  • file_contexts weist Dateien Labels zu und wird von verschiedenen Userspace-Komponenten verwendet. Wenn Sie neue Richtlinien erstellen, erstellen oder aktualisieren Sie diese Datei, um Dateien neue Labels zuzuweisen. Wenn Sie eine neue file_contexts anwenden möchten, erstellen Sie das Dateisystem-Image neu oder führen Sie restorecon auf der Datei aus, die neu beschriftet werden soll. Bei Upgrades werden Änderungen an file_contexts automatisch auf die System- und Nutzerdatenpartitionen angewendet. Änderungen können auch automatisch beim Upgrade auf andere Partitionen angewendet werden, indem Sie der Datei „init.board.rc“ restorecon_recursive-Aufrufe hinzufügen, nachdem die Partition schreibgeschützt bereitgestellt wurde.
  • genfs_contexts weist Dateisystemen wie proc oder vfat Labels zu, die keine erweiterten Attribute unterstützen. Diese Konfiguration wird als Teil der Kernelrichtlinie geladen, aber Änderungen werden möglicherweise nicht für In-Core-Inodes wirksam. Es ist dann ein Neustart oder das Trennen und erneute Bereitstellen des Dateisystems erforderlich, damit die Änderung vollständig angewendet wird. Bestimmte Labels können auch bestimmten Bereitstellungen zugewiesen werden, z. B. vfat mit der Option context=mount.
  • property_contexts ordnet Android-Systemeigenschaften Labels zu, um zu steuern, welche Prozesse sie festlegen können. Diese Konfiguration wird beim Starten vom Prozess init gelesen.
  • service_contexts ordnet Android-Binderdiensten Labels zu, um zu steuern, welche Prozesse eine Binderreferenz für den Dienst hinzufügen (registrieren) und finden (abrufen) können. Diese Konfiguration wird beim Starten vom Prozess servicemanager gelesen.
  • seapp_contexts weist App-Prozessen und /data/data-Verzeichnissen Labels zu. Diese Konfiguration wird vom zygote-Prozess bei jedem App-Start und von installd beim Start gelesen.
  • mac_permissions.xml weist Apps basierend auf ihrer Signatur und optional ihrem Paketnamen ein seinfo-Tag zu. Das seinfo-Tag kann dann als Schlüssel in der seapp_contexts-Datei verwendet werden, um allen Apps mit diesem seinfo-Tag ein bestimmtes Label zuzuweisen. Diese Konfiguration wird beim Starten von system_server gelesen.
  • keystore2_key_contexts weist Keystore 2.0-Namespaces Labels zu. Diese Namespaces werden vom keystore2-Daemon erzwungen. Der Schlüsselspeicher hat immer UID-/AID-basierte Namespaces bereitgestellt. Keystore 2.0 erzwingt zusätzlich Namespaces, die in der SEPolicy definiert sind. Eine detaillierte Beschreibung des Formats und der Konventionen dieser Datei finden Sie hier.

BoardConfig.mk-Makefile

Nachdem Sie Richtlinien- und Kontextdateien bearbeitet oder hinzugefügt haben, aktualisieren Sie das /device/manufacturer/device-name/BoardConfig.mk-Makefile, damit es auf das Unterverzeichnis sepolicy und jede neue Richtliniendatei verweist. Weitere Informationen zu den BOARD_SEPOLICY-Variablen finden Sie in der system/sepolicy/README-Datei.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Nach dem Neuaufbau ist SELinux auf Ihrem Gerät aktiviert. Sie können Ihre SELinux-Richtlinien jetzt entweder so anpassen, dass sie Ihre eigenen Ergänzungen zum Android-Betriebssystem berücksichtigen, wie unter Anpassen beschrieben, oder Ihre vorhandene Konfiguration wie unter Validierung beschrieben überprüfen.

Wenn die neuen Richtliniendateien und die BoardConfig.mk-Updates vorhanden sind, werden die neuen Richtlinieneinstellungen automatisch in die endgültige Kernel-Richtliniendatei eingefügt. Weitere Informationen dazu, wie sepolicy auf dem Gerät erstellt wird, finden Sie unter sepolicy erstellen.

Implementierung

So starten Sie mit SELinux:

  1. Aktivieren Sie SELinux im Kernel: CONFIG_SECURITY_SELINUX=y
  2. Ändern Sie den Parameter „kernel_cmdline“ oder „bootconfig“ so, dass:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    oder
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Dieser Schritt dient nur der Erstentwicklung der Richtlinie für das Gerät. Nachdem Sie eine erste Bootstrap-Richtlinie festgelegt haben, entfernen Sie diesen Parameter, damit Ihr Gerät die Richtlinie erzwingt oder den CTS-Test nicht besteht.
  3. Starten Sie das System im permissive-Modus und sehen Sie nach, welche Zugriffsverweigerungen beim Start auftreten:
    Unter Ubuntu 14.04 oder höher:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    Unter Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Prüfen Sie die Ausgabe auf Warnungen, die init: Warning! Service name needs a SELinux domain defined; please fix! ähneln. Unter Validierung finden Sie eine Anleitung und Tools.
  5. Geräte und andere neue Dateien identifizieren, die gekennzeichnet werden müssen
  6. Verwenden Sie vorhandene oder neue Labels für Ihre Objekte. Sehen Sie sich die *_contexts-Dateien an, um zu sehen, wie die Elemente zuvor gekennzeichnet waren, und weisen Sie anhand der Bedeutungen der Labels ein neues zu. Idealerweise ist dies ein vorhandenes Label, das den Richtlinien entspricht. Manchmal ist jedoch ein neues Label und Regeln für den Zugriff auf dieses Label erforderlich. Fügen Sie die Labels den entsprechenden Kontextdateien hinzu.
  7. Domains/Prozesse identifizieren, die eigene Sicherheitsbereiche haben sollten Wahrscheinlich müssen Sie für jede eine völlig neue Richtlinie verfassen. Alle Dienste, die von init stammen, sollten beispielsweise eigene haben. Mit den folgenden Befehlen können Sie herausfinden, welche Dienste noch ausgeführt werden. ALLE Dienste müssen jedoch so behandelt werden:
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Prüfen Sie init.device.rc, um Domains zu finden, die keinen Domaintyp haben. Weisen Sie ihnen frühzeitig im Entwicklungsprozess eine Domain zu, um zu vermeiden, dass Sie init Regeln hinzufügen oder init-Zugriffe anderweitig mit denen in ihrer eigenen Richtlinie verwechseln.
  9. Richten Sie BOARD_CONFIG.mk so ein, dass BOARD_SEPOLICY_*-Variablen verwendet werden. Weitere Informationen zur Einrichtung finden Sie in der README-Datei in system/sepolicy.
  10. Prüfen Sie die Dateien „init.device.rc“ und „fstab.device“ und achten Sie darauf, dass jede Verwendung von mount einem korrekt beschrifteten Dateisystem entspricht oder dass eine context= mount-Option angegeben ist.
  11. Sehen Sie sich jede Ablehnung an und erstellen Sie eine SELinux-Richtlinie, um sie richtig zu verarbeiten. Sehen Sie sich die Beispiele unter Anpassung an.

Sie sollten mit den Richtlinien im AOSP beginnen und dann darauf aufbauen, um Ihre eigenen Anpassungen vorzunehmen. Weitere Informationen zur Richtlinienstrategie und einen genaueren Blick auf einige dieser Schritte finden Sie unter SELinux-Richtlinie schreiben.

Anwendungsfälle

Im Folgenden finden Sie Beispiele für Exploits, die Sie bei der Erstellung Ihrer eigenen Software und der zugehörigen SELinux-Richtlinien berücksichtigen sollten:

Symlinks: Da Symlinks als Dateien angezeigt werden, werden sie oft auch als Dateien gelesen, was zu Exploits führen kann. Beispielsweise ändern einige privilegierte Komponenten wie init die Berechtigungen bestimmter Dateien, manchmal zu weitreichend.

Angreifer können diese Dateien dann durch Symlinks zu von ihnen kontrolliertem Code ersetzen, wodurch sie beliebige Dateien überschreiben können. Wenn Sie jedoch wissen, dass Ihre App niemals einen Symlink durchläuft, können Sie dies mit SELinux unterbinden.

Systemdateien: Die Klasse der Systemdateien, die nur vom Systemserver geändert werden sollte. Da netd, init und vold jedoch als Root ausgeführt werden, können sie auf diese Systemdateien zugreifen. Wenn netd also manipuliert wird, könnten diese Dateien und möglicherweise auch der Systemserver selbst manipuliert werden.

Mit SELinux können Sie diese Dateien als Systemserverdatendateien kennzeichnen. Daher hat nur der Systemserver Lese-/Schreibzugriff darauf. Selbst wenn netd manipuliert würde, könnte es nicht zur Systemserverdomain wechseln und auf diese Systemdateien zugreifen, obwohl es als Root ausgeführt wird.

App-Daten:Ein weiteres Beispiel ist die Klasse von Funktionen, die als Root ausgeführt werden müssen, aber keinen Zugriff auf App-Daten erhalten sollten. Das ist sehr nützlich, da weitreichende Behauptungen aufgestellt werden können, z. B. dass der Zugriff auf das Internet für bestimmte Domains, die nichts mit App-Daten zu tun haben, verboten ist.

setattr:Für Befehle wie chmod und chown können Sie die Dateien angeben, in denen die zugehörige Domain setattr ausführen kann. Alles andere kann von diesen Änderungen ausgeschlossen werden, auch durch Root. So kann eine App chmod und chown auf Elemente anwenden, die mit app_data_files gekennzeichnet sind, aber nicht auf shell_data_files oder system_data_files.