Das Android Open Source Project (AOSP) bietet eine solide Grundlage für die Apps und Dienste, die auf allen Android-Geräten üblich sind. Die Mitwirkenden am AOSP überarbeiten diese Richtlinie regelmäßig. Die Kernrichtlinie wird voraussichtlich etwa 90–95% der endgültigen Richtlinie auf dem Gerät ausmachen, die restlichen 5–10 % sind gerätespezifische Anpassungen. Dieser Artikel konzentriert sich auf diese gerätespezifischen Anpassungen, das Erstellen gerätespezifischer Richtlinien und einige der Schwierigkeiten, die Sie vermeiden sollten.
Geräteeinrichtung
Beachten Sie beim Erstellen einer gerätespezifischen Richtlinie die folgenden Schritte.
Im permissiven Modus ausführen
Wenn sich ein Gerät im permissiven Modus befindet, werden Ablehnungen zwar protokolliert, aber nicht erzwungen. Der permissive Modus ist aus zwei Gründen wichtig:
- Der Modus „Moderat“ sorgt dafür, dass die Richtlinienerstellung andere Aufgaben zu Beginn der Gerätebereitstellung nicht verzögert.
- Eine erzwungene Ablehnung kann andere Ablehnungen verdecken. Der Dateizugriff umfasst beispielsweise in der Regel eine Verzeichnissuche, das Öffnen der Datei und das Lesen der Datei. Im Erzwingungsmodus würde nur die Verzeichnissuche abgelehnt. Im permissiven Modus werden alle Ablehnungen angezeigt.
Die einfachste Möglichkeit, ein Gerät in den mäßigen Modus zu versetzen, ist die Verwendung der Kernel-Befehlszeile. Dieser kann der Datei BoardConfig.mk
des Geräts hinzugefügt werden:
platform/device/<vendor>/<target>/BoardConfig.mk
.
Nachdem Sie die Befehlszeile geändert haben, führen Sie make clean
und dann make bootimage
aus und flashen Sie das neue Boot-Image.
Bestätigen Sie dann den permissiven Modus mit:
adb shell getenforce
Zwei Wochen sind ein angemessener Zeitraum für den globalen permissiven Modus. Nachdem Sie die meisten Ablehnungen behoben haben, kehren Sie zum Erzwingungsmodus zurück und beheben Sie auftretende Fehler. Domains, die weiterhin Abweisungen verursachen, oder Dienste, die sich noch in der Entwicklungsphase befinden, können vorübergehend in den permissiven Modus versetzt werden. Sie sollten sie jedoch so bald wie möglich wieder in den Erzwingungsmodus versetzen.
Frühzeitig erzwingen
Im Erzwingungsmodus werden Ablehnungen sowohl protokolliert als auch erzwungen. Es wird empfohlen, das Gerät so früh wie möglich in den Erzwingungsmodus zu versetzen. Wenn Sie warten, bis Sie gerätespezifische Richtlinien erstellen und erzwingen, führt dies oft zu einem fehlerhaften Produkt und einer schlechten Nutzererfahrung. Beginnen Sie früh genug, um am Dogfooding teilzunehmen und die Funktionen in der Praxis vollständig zu testen. Wenn Sie früh beginnen, können Sicherheitsbedenken in Designentscheidungen einfließen. Umgekehrt ist es nicht sicher, Berechtigungen nur auf der Grundlage beobachteter Ablehnungen zu gewähren. Nutzen Sie diese Zeit, um eine Sicherheitsprüfung des Geräts durchzuführen und Fehler in Bezug auf Verhaltensweisen zu melden, die nicht zulässig sind.
Vorhandene Richtlinie entfernen oder löschen
Es gibt eine Reihe von guten Gründen, eine gerätespezifische Richtlinie von Grund auf auf einem neuen Gerät zu erstellen. Dazu gehören:
- Sicherheitsprüfung
- Zu moderate Richtlinie
- Verringerung der Richtliniengröße
- Richtlinie zu Inhalten, die einen Todeseintritt zeigen
Ablehnungen von Hauptdiensten angehen
Von Kerndiensten generierte Ablehnungen werden in der Regel durch Dateilabel behoben. Beispiel:
avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0” dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1 avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
wird durch die korrekte Kennzeichnung von /dev/kgsl-3d0
vollständig behoben. In diesem Beispiel ist tcontext
device
. Dies stellt einen Standardkontext dar, in dem alles in /dev
das Label
Gerät erhält, sofern kein spezifischeres Label zugewiesen ist. Wenn Sie die Ausgabe von audit2allow einfach akzeptieren, würde dies zu einer falschen und zu toleranten Regel führen.
Um diese Art von Problem zu lösen, geben Sie der Datei ein genaueres Label, in diesem Fall gpu_device. Es sind keine weiteren Berechtigungen erforderlich, da der Mediaserver bereits die erforderlichen Berechtigungen in der Kernrichtlinie für den Zugriff auf das GPU-Gerät hat.
Andere gerätespezifische Dateien, die mit den in der Kernrichtlinie vordefinierten Typen gekennzeichnet werden sollten:
- blockieren
- Audiogeräte
- Videogeräte
- Sensoren
- nfc
- GPS-Gerät
- Dateien in /sys
- Dateien in /proc
Im Allgemeinen ist es nicht sinnvoll, Standardlabels Berechtigungen zu gewähren. Viele dieser Berechtigungen sind durch neverallow-Regeln nicht zulässig. Auch wenn sie nicht ausdrücklich nicht zulässig sind, empfiehlt es sich, ein bestimmtes Label anzugeben.
Neue Dienste kennzeichnen und Ablehnungen bearbeiten
Von Init gestartete Dienste müssen in ihren eigenen SELinux-Domains ausgeführt werden. Im folgenden Beispiel wird der Dienst "foo" in seiner eigenen SELinux-Domain platziert und ihm werden Berechtigungen gewährt.
Der Dienst wird in der init.device.rc
-Datei des Geräts so gestartet:
service foo /system/bin/foo class core
- Neue Domain „foo“ erstellen
Erstellen Sie die Datei
device/manufacturer/device-name/sepolicy/foo.te
mit folgendem Inhalt:# foo service type foo, domain; type foo_exec, exec_type, file_type; init_daemon_domain(foo)
Dies ist die ursprüngliche Vorlage für die SELinux-Domain „foo“, der Sie Regeln hinzufügen können, die auf den spezifischen Vorgängen basieren, die von dieser ausführbaren Datei ausgeführt werden.
- Label
/system/bin/foo
Fügen Sie
device/manufacturer/device-name/sepolicy/file_contexts
Folgendes hinzu:/system/bin/foo u:object_r:foo_exec:s0
Dadurch wird sichergestellt, dass die ausführbare Datei richtig gekennzeichnet ist, damit SELinux den Dienst in der richtigen Domain ausführt.
- Erstellen und flashen Sie die Boot- und System-Images.
- Passen Sie die SELinux-Regeln für die Domain an.
Anhand von Ablehnungen können Sie die erforderlichen Berechtigungen ermitteln. Das Tool audit2allow bietet gute Richtlinien. Verwenden Sie es jedoch nur als Orientierungshilfe beim Erstellen von Richtlinien. Kopieren Sie nicht nur die Ausgabe.
Zurück zum Erzwingungsmodus wechseln
Die Fehlerbehebung im moderaten Modus ist problemlos möglich. Wechseln Sie jedoch so früh wie möglich in den erzwungenen Modus und versuchen Sie, dort zu bleiben.
Häufige Fehler
Hier finden Sie einige Lösungen für häufige Fehler beim Erstellen gerätespezifischer Richtlinien.
Übermäßige Verwendung von Verneinungen
Die folgende Beispielregel ist mit dem Verriegeln der Haustür, aber dem Offenlassen der Fenster vergleichbar:
allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms
Die Absicht ist klar: Alle außer Drittanbieter-Apps dürfen Zugriff auf das Debuggerät haben.
Die Regel ist in mehrfacher Hinsicht fehlerhaft. Der Ausschluss von untrusted_app
lässt sich ganz einfach umgehen, da alle Apps optional Dienste in der Domain isolated_app
ausführen können. Wenn dem AOSP neue Domains für Drittanbieter-Apps hinzugefügt werden, haben diese ebenfalls Zugriff auf scary_debug_device
.
Die Regel ist zu großzügig. Bei den meisten Domains ist der Zugriff auf dieses Debugging-Tool nicht erforderlich. Die Regel sollte so geschrieben sein, dass nur die Domains zugelassen werden, für die Zugriff erforderlich ist.
Debug-Funktionen in der Produktionsumgebung
Debug-Funktionen sollten in Produktionsbuilds nicht vorhanden sein, ebenso wenig wie ihre Richtlinie.
Die einfachste Alternative besteht darin, die Debug-Funktion nur zuzulassen, wenn SELinux in eng/userdebug-Builds wie adb root
und adb shell setenforce 0
deaktiviert ist.
Eine weitere sichere Alternative besteht darin, Debugberechtigungen in einer userdebug_or_eng-Anweisung einzufügen.
Explosion der Richtliniengröße
In Characterizing SEAndroid Policies in the Wild wird ein besorgniserregender Trend bei der Zunahme von Anpassungen von Geräterichtlinien beschrieben. Gerätespezifische Richtlinien sollten 5–10% der Gesamtrichtlinien ausmachen, die auf einem Gerät ausgeführt werden. Anpassungen mit einem Wert von über 20%enthalten mit hoher Wahrscheinlichkeit zu viele berechtigte Domains und eine inaktive Richtlinie.
Unnötig große Richtlinie:
- Erhöht den Arbeitsspeicherbedarf, da die Richtlinie sich im RAM-Laufwerk befindet und auch in den Kernel-Speicher geladen wird.
- Es wird mehr Speicherplatz benötigt, da ein größeres Boot-Image erforderlich ist.
- Wirkt sich auf die Suchzeiten für Laufzeitrichtlinien aus.
Das folgende Beispiel zeigt zwei Geräte, bei denen die herstellerspezifische Richtlinie 50% und 40% der On-Device-Richtlinie ausmachte. Eine Überarbeitung der Richtlinie führte zu erheblichen Sicherheitsverbesserungen ohne Funktionsverlust, wie unten dargestellt. (Die AOSP-Geräte Shamu und Flounder sind zum Vergleich enthalten.)
In beiden Fällen wurde die Richtlinie sowohl in Bezug auf die Größe als auch auf die Anzahl der Berechtigungen drastisch reduziert. Die Verkleinerung der Richtlinie ist fast vollständig auf das Entfernen unnötiger Berechtigungen zurückzuführen. Viele davon waren wahrscheinlich von audit2allow
generierte Regeln, die der Richtlinie wahllos hinzugefügt wurden. Tot-Domains waren ebenfalls ein Problem für beide Geräte.
Die Berechtigung „dac_override“ gewähren
Eine dac_override
-Denial bedeutet, dass der betreffende Prozess versucht, mit den falschen Unix-Berechtigungen für Nutzer/Gruppe/Alle auf eine Datei zuzugreifen.
Die richtige Lösung besteht fast nie darin, die Berechtigung dac_override
zu gewähren.
Stattdessen
ändern Sie die Unix-Berechtigungen für die Datei oder den Prozess. Einige Domains wie init
, vold
und installd
benötigen tatsächlich die Möglichkeit, Unix-Dateiberechtigungen zu überschreiben, um auf die Dateien anderer Prozesse zuzugreifen.
Eine ausführlichere Erklärung finden Sie im Blog von Dan Walsh.