Implementierung von SELinux

SELinux ist auf „Default-Deny“ eingestellt, was bedeutet, dass jeder einzelne Zugriff, für den es einen Hook im Kernel hat, durch die Richtlinie explizit zugelassen werden muss. Das bedeutet, dass eine Richtliniendatei eine große Menge an Informationen zu Regeln, Typen, Klassen, Berechtigungen und mehr enthält. 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. Empfohlene Ressourcen finden Sie in der Begleitdokumentation .

Schlüsseldateien

Um SELinux zu aktivieren, integrieren Sie den neuesten Android-Kernel und dann die im Verzeichnis system/sepolicy gefundenen Dateien. Beim Kompilieren umfassen diese Dateien die SELinux-Kernel-Sicherheitsrichtlinie 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. In Android 8.0 und höher sollten sich die Änderungen, die Sie an diesen Dateien vornehmen, nur auf die Richtlinien 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 mit *.te enden, sind SELinux-Richtlinienquelldateien, die Domänen und ihre Bezeichnungen definieren. Möglicherweise müssen Sie neue Richtliniendateien in /device/ manufacturer / device-name /sepolicy erstellen, Sie sollten jedoch versuchen, vorhandene Dateien nach Möglichkeit zu aktualisieren.

Kontextdateien

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

  • file_contexts weist Dateien Beschriftungen zu und wird von verschiedenen Userspace-Komponenten verwendet. Wenn Sie neue Richtlinien erstellen, erstellen oder aktualisieren Sie diese Datei, um den Dateien neue Bezeichnungen zuzuweisen. Um neue file_contexts anzuwenden, erstellen Sie das Dateisystem-Image neu oder führen Sie restorecon für die Datei aus, die neu beschriftet werden soll. Bei Upgrades werden Änderungen an file_contexts im Rahmen des Upgrades automatisch auf die System- und Benutzerdatenpartitionen angewendet. Änderungen können auch automatisch beim Upgrade auf andere Partitionen angewendet werden, indem Sie restorecon_recursive -Aufrufe zu Ihrer Init-Instanz hinzufügen. board .rc-Datei, nachdem die Partition mit Lese-/Schreibzugriff gemountet wurde.
  • genfs_contexts weist Dateisystemen Labels zu, z. B. proc oder vfat , 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, sodass ein Neustart oder ein Unmounten und erneutes Mounten des Dateisystems erforderlich ist, um die Änderung vollständig anzuwenden. Bestimmten Mounts können auch bestimmte Labels zugewiesen werden, z. B. vfat mithilfe der Option context=mount .
  • property_contexts weist Android-Systemeigenschaften Beschriftungen zu, um zu steuern, welche Prozesse sie festlegen können. Diese Konfiguration wird beim Start vom init Prozess gelesen.
  • service_contexts weist Android-Binder-Diensten Beschriftungen zu, um zu steuern, welche Prozesse eine Binder-Referenz für den Dienst hinzufügen (registrieren) und suchen (suchen) können. Diese Konfiguration wird beim Start vom servicemanager Prozess gelesen.
  • seapp_contexts weist App-Prozessen und /data/data Verzeichnissen Beschriftungen zu. Diese Konfiguration wird vom zygote Prozess bei jedem App-Start gelesen und von installd beim Start.
  • 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 eine bestimmte Bezeichnung zuzuweisen. Diese Konfiguration wird beim Start von system_server gelesen.
  • keystore2_key_contexts weist Keystore 2.0-Namespaces Beschriftungen zu. Dieser Namespace wird vom keystore2-Daemon erzwungen. Keystore stellt seit jeher UID/AID-basierte Namespaces bereit. Keystore 2.0 erzwingt zusätzlich durch 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 dem Neuaufbau ist Ihr Gerät mit SELinux aktiviert. Sie können jetzt entweder Ihre SELinux-Richtlinien anpassen, um Ihre eigenen Ergänzungen zum Android-Betriebssystem zu berücksichtigen, wie unter „Anpassung“ beschrieben, oder Ihr bestehendes Setup überprüfen, wie unter „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

Um mit SELinux zu beginnen:

  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 einer Richtlinie für das Gerät. Nachdem Sie eine erste Bootstrap-Richtlinie erstellt haben, entfernen Sie diesen Parameter, damit Ihr Gerät die Richtlinie durchsetzt, andernfalls wird CTS fehlschlagen.
  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. Überprüfen Sie die Ausgabe auf Warnungen, 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 eine Kennzeichnung benötigen.
  6. Nutzen Sie bestehende oder neue Beschriftungen für Ihre Objekte. Schauen Sie sich die *_contexts Dateien an, um zu sehen, wie Dinge zuvor beschriftet wurden, und nutzen Sie die Kenntnis der Beschriftungsbedeutungen, um eine neue zuzuweisen. Im Idealfall handelt es sich dabei um ein vorhandenes Label, das in die Richtlinie passt. Manchmal ist jedoch ein neues Label erforderlich, und es sind Regeln für den Zugriff auf dieses Label erforderlich. Fügen Sie Ihre Beschriftungen den entsprechenden Kontextdateien hinzu.
  7. Identifizieren Sie Domänen/Prozesse, die über eigene Sicherheitsdomänen verfügen sollten. Sie müssen wahrscheinlich für jeden eine völlig neue Richtlinie schreiben. Alle aus init hervorgegangenen Dienste sollten beispielsweise ihre eigenen haben. Die folgenden Befehle helfen dabei, 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üfen Sie init. device .rc , um alle Domänen zu identifizieren, die keinen Domänentyp haben. Geben Sie ihnen zu Beginn Ihres Entwicklungsprozesses eine Domäne, um zu vermeiden, dass Sie Regeln zu init hinzufügen oder auf andere Weise init Zugriffe mit denen verwechseln, die in ihrer eigenen Richtlinie enthalten sind.
  9. Richten Sie BOARD_CONFIG.mk für die Verwendung von BOARD_SEPOLICY_* Variablen ein. Weitere Informationen zum Einrichten finden Sie in der README-Datei unter system/sepolicy .
  10. Untersuchen Sie die Init. device .rc und fstab. device und stellen Sie sicher, dass jede Verwendung von mount einem ordnungsgemäß 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. Sehen Sie sich die Beispiele unter „Anpassung“ an.

Sie sollten mit den Richtlinien im AOSP beginnen und dann für Ihre eigenen Anpassungen darauf aufbauen. Weitere Informationen zur Richtlinienstrategie und einen genaueren Blick auf einige dieser Schritte finden Sie unter Schreiben einer SELinux-Richtlinie .

Anwendungsfälle

Hier sind konkrete Beispiele für Exploits, die Sie bei der Erstellung Ihrer eigenen Software und 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 init die Berechtigungen bestimmter Dateien, sodass sie manchmal übermäßig geöffnet sind.

Angreifer könnten diese Dateien dann durch symbolische Links zu Code ersetzen, den sie kontrollieren, wodurch der Angreifer beliebige Dateien überschreiben kann. Wenn Sie jedoch wissen, dass Ihre Anwendung niemals einen symbolischen Link passieren wird, können Sie ihr dies mit SELinux verbieten.

Systemdateien – Berücksichtigen Sie die Klasse der Systemdateien, die nur vom Systemserver geändert werden sollten. Da netd , init und vold jedoch als Root ausgeführt werden, können sie auf diese Systemdateien zugreifen. Wenn also netd kompromittiert würde, könnten diese Dateien und möglicherweise auch der Systemserver selbst gefährdet werden.

Mit SELinux können Sie diese Dateien als Systemserver-Datendateien identifizieren. Daher ist der Systemserver die einzige Domäne, die Lese-/Schreibzugriff darauf hat. Selbst wenn netd kompromittiert wurde, konnte es die Domänen nicht zur Systemserverdomäne 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 haben sollten. Dies ist äußerst nützlich, da weitreichende Aussagen getroffen werden können, beispielsweise dass bestimmten Domains, die nichts mit Anwendungsdaten zu tun haben, der Zugriff auf das Internet untersagt ist.

setattr – Für Befehle wie chmod und chown können Sie den Satz von Dateien identifizieren, in denen die zugehörige Domäne setattr ausführen kann. Alles andere könnte von diesen Änderungen ausgeschlossen werden, sogar durch Root. Daher kann eine Anwendung chmod und chown für diejenigen mit der Bezeichnung app_data_files ausführen, jedoch nicht für shell_data_files oder system_data_files .