Implementierung von SELinux

SELinux ist auf Default-Deny eingestellt, was bedeutet, dass jeder einzelne Zugriff, für den es einen Hook im Kernel hat, explizit per Policy zugelassen werden muss. Dies bedeutet, dass eine Richtliniendatei aus einer großen Menge an Informationen zu Regeln, Typen, Klassen, Berechtigungen und mehr besteht. Eine vollständige Betrachtung von SELinux würde den Rahmen dieses Dokuments sprengen, aber ein Verständnis dafür, wie Richtlinienregeln geschrieben werden, ist jetzt unerlässlich, wenn neue Android-Geräte eingeführt werden. Es gibt bereits viele Informationen zu SELinux. Siehe Unterstützende Dokumentation für empfohlene Ressourcen.

Schlüsseldateien

Um SELinux zu aktivieren, integrieren Sie den neuesten Android-Kernel und dann die Dateien aus dem Verzeichnis system/sepolicy . Nach dem Kompilieren umfassen diese Dateien die SELinux-Kernel-Sicherheitsrichtlinie und decken das vorgeschaltete 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. In 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 Einzelheiten zur Trennung der öffentlichen SEPolicy in Android 8.0 und höher finden Sie unter Anpassen von SEPolicy in Android 8.0+ . Unabhängig von der Android-Version ändern Sie immer noch diese Dateien:

Richtliniendateien

Dateien, die auf *.te sind SELinux-Richtlinienquelldateien, die Domänen und ihre Bezeichnungen definieren. Möglicherweise müssen Sie neue Richtliniendateien in /device/ manufacturer / device-name /sepolicy , aber Sie sollten versuchen, vorhandene Dateien nach Möglichkeit zu aktualisieren.

Kontextdateien

In Kontextdateien geben Sie Beschriftungen 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 Bezeichnungen zuzuweisen. Um neue file_contexts anzuwenden, erstellen Sie das Dateisystem-Image neu oder führen restorecon für die umzubenennende Datei aus. Bei Upgrades werden Änderungen an file_contexts als Teil des Upgrades automatisch auf die System- und Benutzerdatenpartitionen angewendet. Änderungen können auch automatisch beim Upgrade auf andere Partitionen angewendet werden, indem restorecon_recursive Aufrufe zu Ihrem init hinzufügen. board .rc-Datei, nachdem die Partition mit Lese-/Schreibzugriff gemountet wurde.
  • genfs_contexts weist Dateisystemen wie proc oder vfat Labels zu, die keine erweiterten Attribute unterstützen. Diese Konfiguration wird als Teil der Kernel-Richtlinie geladen, aber Änderungen werden möglicherweise nicht für In-Core-Inodes wirksam, was einen Neustart oder das Aushängen und erneute Einhängen des Dateisystems erfordert, um die Änderung vollständig anzuwenden. Bestimmte Bezeichnungen können auch bestimmten Mounts zugewiesen werden, wie z. B. vfat , indem die Option context=mount verwendet wird.
  • property_contexts weist Android-Systemeigenschaften Labels zu, um zu steuern, welche Prozesse sie festlegen können. Diese Konfiguration wird beim Start vom init Prozess gelesen.
  • service_contexts weist Android-Binderdiensten Bezeichnungen zu, um zu steuern, welche Prozesse eine Binderreferenz für den Dienst hinzufügen (registrieren) und finden (suchen) können. Diese Konfiguration wird während des Starts vom servicemanager Prozess 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 während des Starts 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 Datei seapp_contexts “ verwendet werden, um allen Apps mit diesem seinfo -Tag ein bestimmtes Label zuzuweisen. Diese Konfiguration wird während des Starts von system_server gelesen.
  • keystore2_key_contexts weist Keystore 2.0-Namespaces Labels zu. Diese Namespaces werden vom keystore2-Daemon durchgesetzt. Keystore hat immer UID/AID-basierte Namespaces bereitgestellt. Keystore 2.0 erzwingt zusätzlich sepolicy-definierte Namespaces. Eine detaillierte Beschreibung des Formats und der Konventionen dieser Datei finden Sie hier .

BoardConfig.mk-Makefile

Aktualisieren Sie nach dem Bearbeiten oder Hinzufügen von Richtlinien- und Kontextdateien Ihr Makefile /device/ manufacturer / device-name /BoardConfig.mk um auf das Unterverzeichnis sepolicy und jede neue Richtliniendatei zu verweisen. Weitere Informationen zu den BOARD_SEPOLICY Variablen finden Sie in der Datei system/sepolicy/README .

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

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Nach der Wiederherstellung ist Ihr Gerät mit SELinux aktiviert. Sie können jetzt entweder Ihre SELinux-Richtlinien anpassen, um Ihre eigenen Ergänzungen des Android-Betriebssystems zu berücksichtigen, wie in Anpassung beschrieben, oder Ihre vorhandene Einrichtung überprüfen, wie in Validierung beschrieben.

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

Implementierung

Erste Schritte mit SELinux:

  1. Aktivieren Sie SELinux im Kernel: CONFIG_SECURITY_SELINUX=y
  2. Ändern Sie den Parameter kernel_cmdline oder bootconfig wie folgt:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    oder
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Dies dient nur der anfänglichen Entwicklung der Richtlinie für das Gerät. Nachdem Sie eine anfängliche Bootstrap-Richtlinie haben, entfernen Sie diesen Parameter, damit Ihr Gerät CTS erzwingt oder CTS fehlschlägt.
  3. Starten Sie das System permissiv und sehen Sie, welche Ablehnungen beim Booten auftreten:
    Unter Ubuntu 14.04 oder neuer:
    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. Werten Sie die Ausgabe auf Warnungen aus, die init: Warning! Service name needs a SELinux domain defined; please fix! Anweisungen und Tools finden Sie unter Validierung .
  5. Identifizieren Sie Geräte und andere neue Dateien, 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 Dinge zuvor beschriftet waren, und verwenden Sie das Wissen über die Bedeutung der Beschriftung, um eine neue zuzuweisen. Idealerweise ist dies ein vorhandenes Label, das in die Richtlinie passt, aber manchmal wird ein neues Label benötigt, und es werden Regeln für den Zugriff auf dieses Label benötigt. Fügen Sie Ihre Labels zu den entsprechenden Kontextdateien hinzu.
  7. Identifizieren Sie Domänen/Prozesse, die ihre eigenen Sicherheitsdomänen haben sollten. Sie müssen wahrscheinlich für jede eine völlig neue Richtlinie schreiben. Alle Dienste, die beispielsweise von init hervorgebracht werden, sollten ihre eigenen haben. Die folgenden Befehle helfen, diejenigen aufzudecken, die weiterhin ausgeführt werden (aber ALLE Dienste benötigen eine solche Behandlung):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Überprüfungsinit init. device .rc , um alle Domänen zu identifizieren, die keinen Domänentyp haben. Geben Sie ihnen früh in Ihrem Entwicklungsprozess eine Domäne, um zu vermeiden, dass Regeln zu init hinzugefügt werden oder anderweitig init Zugriffe mit denen verwechselt werden, die in ihrer eigenen Richtlinie enthalten sind.
  9. Richten Sie BOARD_CONFIG.mk ein, um BOARD_SEPOLICY_* Variablen zu verwenden. Einzelheiten zur Einrichtung finden Sie in der README -Datei in system/sepolicy .
  10. Untersuchen Sie die Initialisierung. device .rc und fstab. device -Datei und vergewissern Sie sich, dass jede Verwendung von mount einem richtig gekennzeichneten Dateisystem entspricht oder dass eine context= mount Option angegeben ist.
  11. Gehen Sie jede Ablehnung durch und erstellen Sie eine SELinux-Richtlinie, um jede ordnungsgemäß zu behandeln. Siehe die Beispiele in Anpassung .

Sie sollten mit den Richtlinien im AOSP beginnen und dann für Ihre eigenen Anpassungen darauf aufbauen. Weitere Informationen zur Richtlinienstrategie und eine genauere Betrachtung einiger dieser Schritte finden Sie unter Schreiben von SELinux-Richtlinien .

Anwendungsfälle

Hier sind spezifische Beispiele für Exploits, die Sie beim Erstellen Ihrer eigenen Software und der zugehörigen SELinux-Richtlinien berücksichtigen sollten:

Symlinks – Da Symlinks als Dateien erscheinen, werden sie oft als Dateien gelesen, was zu Exploits führen kann. Beispielsweise ändern einige privilegierte Komponenten, wie z. B. init , die Berechtigungen bestimmter Dateien, um sie manchmal übermäßig zu öffnen.

Angreifer können diese Dateien dann durch symbolische Links zu Code ersetzen, den sie kontrollieren, wodurch der Angreifer beliebige Dateien überschreiben kann. Aber wenn Sie wissen, dass Ihre Anwendung niemals einen Symlink durchlaufen wird, können Sie dies mit SELinux verbieten.

Systemdateien – Berücksichtigen Sie die Klasse von Systemdateien, die nur vom Systemserver geändert werden sollten. Da netd , init und vold als root ausgeführt werden, können sie auf diese Systemdateien zugreifen. Wenn also netd kompromittiert wird, könnte es diese Dateien und möglicherweise den Systemserver selbst kompromittieren.

Mit SELinux können Sie diese Dateien als Systemserver-Datendateien identifizieren. Daher ist die einzige Domäne, die Lese-/Schreibzugriff auf sie hat, der Systemserver. Selbst wenn netd kompromittiert wurde, konnte es die Domänen nicht auf die Systemserverdomäne umschalten 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 nicht auf App-Daten zugreifen dürfen. Dies ist unglaublich nützlich, da weitreichende Behauptungen aufgestellt werden können, z. B. dass bestimmten Domains, die nichts mit Anwendungsdaten zu tun haben, der Zugriff auf das Internet untersagt wird.

setattr – Für Befehle wie chmod und chown könnten Sie den Satz von Dateien identifizieren, in denen die zugeordnete Domäne setattr kann. Alles andere könnte von diesen Änderungen ausgeschlossen werden, sogar von root. Eine Anwendung kann also chmod und chown für diese gekennzeichneten app_data_files , aber nicht shell_data_files oder system_data_files .