Das Android Open Source Project (AOSP) bietet eine solide Basisrichtlinie für die Anwendungen und Dienste, die allen Android-Geräten gemeinsam sind. Mitwirkende an AOSP verfeinern diese Richtlinie regelmäßig. Es wird erwartet, dass die Kernrichtlinie etwa 90–95 % der endgültigen Richtlinie auf dem Gerät ausmacht, während gerätespezifische Anpassungen die restlichen 5–10 % ausmachen. Dieser Artikel konzentriert sich auf diese gerätespezifischen Anpassungen, wie man gerätespezifische Richtlinien schreibt und einige der Fallstricke, die es dabei zu vermeiden gilt.
Geräteaufruf
Befolgen Sie beim Schreiben einer gerätespezifischen Richtlinie die folgenden Schritte.
Im zulässigen Modus ausführen
Wenn sich ein Gerät im Permissivmodus befindet, werden Ablehnungen protokolliert, aber nicht erzwungen. Der Permissivmodus ist aus zwei Gründen wichtig:
- Der permissive Modus stellt sicher, dass das Einschalten der Richtlinie andere frühe Geräteeinschaltaufgaben nicht verzögert.
- Eine erzwungene Ablehnung kann andere Ablehnungen überdecken. Beispielsweise umfasst der Dateizugriff normalerweise eine Verzeichnissuche, das Öffnen der Datei und das anschließende Lesen der Datei. Im Erzwingungsmodus würde nur die Verweigerung der Verzeichnissuche erfolgen. Der permissive Modus stellt sicher, dass alle Ablehnungen gesehen werden.
Der einfachste Weg, ein Gerät in den permissiven Modus zu versetzen, ist die Verwendung der Kernel-Befehlszeile . Dies kann zur BoardConfig.mk
Datei 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
und flashen Sie das neue Boot-Image.
Bestätigen Sie anschließend den zulässigen Modus mit:
adb shell getenforce
Zwei Wochen sind eine angemessene Zeitspanne, um im globalen Freizügigkeitsmodus zu sein. Nachdem Sie die meisten Ablehnungen behoben haben, kehren Sie in den Durchsetzungsmodus zurück und beheben Sie auftretende Fehler. Domains, die immer noch Ablehnungen hervorrufen, oder Dienste, die sich noch in der intensiven Entwicklung befinden, können vorübergehend in den Genehmigungsmodus versetzt werden, aber versetzen Sie sie so schnell wie möglich wieder in den Durchsetzungsmodus.
Frühzeitig durchsetzen
Im Durchsetzungsmodus werden Ablehnungen sowohl protokolliert als auch durchgesetzt. Es empfiehlt sich, Ihr Gerät so früh wie möglich in den Durchsetzungsmodus zu versetzen. Das Warten auf die Erstellung und Durchsetzung gerätespezifischer Richtlinien führt oft zu einem fehlerhaften Produkt und einer schlechten Benutzererfahrung. Beginnen Sie früh genug, um am Dogfooding teilzunehmen und sicherzustellen, dass die Funktionalität im realen Einsatz vollständig getestet wird. Ein frühzeitiger Beginn stellt sicher, dass Sicherheitsbedenken in Designentscheidungen einfließen. Umgekehrt ist die Erteilung von Berechtigungen ausschließlich auf der Grundlage beobachteter Ablehnungen ein unsicherer Ansatz. Nutzen Sie diese Zeit, um eine Sicherheitsüberprüfung der Geräte- und Dateifehler auf Verhalten durchzuführen, das nicht zulässig sein sollte.
Entfernen oder löschen Sie die vorhandene Richtlinie
Es gibt eine Reihe guter Gründe, auf einem neuen Gerät eine gerätespezifische Richtlinie von Grund auf zu erstellen, darunter:
- Sicherheitsüberprüfung
- Übermäßig freizügige Politik
- Reduzierung der Richtliniengröße
- Tote Politik
Beheben Sie Ablehnungen von Kerndiensten
Von Kerndiensten generierte Ablehnungen werden in der Regel durch Dateikennzeichnung behoben. Zum 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 ordnungsgemäße Kennzeichnung /dev/kgsl-3d0
vollständig behoben. In diesem Beispiel ist tcontext
device
. Dies stellt einen Standardkontext dar, in dem alles in /dev
die Bezeichnung „ Gerät “ erhält, sofern keine spezifischere Bezeichnung zugewiesen wird. Das einfache Akzeptieren der Ausgabe von audit2allow würde hier zu einer falschen und übermäßig freizügigen Regel führen.
Um ein solches Problem zu lösen, geben Sie der Datei eine spezifischere Bezeichnung, in diesem Fall gpu_device . Es sind keine weiteren Berechtigungen erforderlich, da der Medienserver in der Kernrichtlinie bereits über die erforderlichen Berechtigungen für den Zugriff auf das gpu_device verfügt .
Andere gerätespezifische Dateien, die mit in der Kernrichtlinie vordefinierten Typen gekennzeichnet werden sollten:
- Geräte blockieren
- Audiogeräte
- Videogeräte
- Sensoren
- NFC
- gps_device
- Dateien in /sys
- Dateien in /proc
Im Allgemeinen ist es falsch, Berechtigungen für Standardbezeichnungen zu erteilen. Viele dieser Berechtigungen werden durch Neverallow- Regeln nicht zugelassen, aber auch wenn sie nicht ausdrücklich verboten sind, empfiehlt es sich, eine bestimmte Bezeichnung bereitzustellen.
Kennzeichnen Sie neue Dienste und adressieren Sie Ablehnungen
Init-gestartete Dienste müssen in ihren eigenen SELinux-Domänen ausgeführt werden. Das folgende Beispiel fügt den Dienst „foo“ in seine eigene SELinux-Domäne ein und erteilt ihm Berechtigungen.
Der Dienst wird im init. device .rc
Datei als:
service foo /system/bin/foo class core
- Erstellen Sie eine neue Domain „foo“
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 anfängliche Vorlage für die foo SELinux-Domäne, zu der Sie Regeln hinzufügen können, die auf den spezifischen Vorgängen basieren, die von dieser ausführbaren Datei ausgeführt werden.
- Beschriften Sie
/system/bin/foo
Fügen Sie Folgendes zu
device/ manufacturer / device-name /sepolicy/file_contexts
hinzu:/system/bin/foo u:object_r:foo_exec:s0
Dadurch wird sichergestellt, dass die ausführbare Datei ordnungsgemäß gekennzeichnet ist, sodass SELinux den Dienst in der richtigen Domäne ausführt.
- Erstellen und flashen Sie die Boot- und System-Images.
- Verfeinern Sie die SELinux-Regeln für die Domäne.
Verwenden Sie Ablehnungen, um die erforderlichen Berechtigungen zu ermitteln. Das Tool audit2allow bietet gute Richtlinien, verwendet es jedoch nur als Grundlage für die Erstellung von Richtlinien. Kopieren Sie nicht einfach die Ausgabe.
Wechseln Sie zurück in den Durchsetzungsmodus
Es ist in Ordnung, Fehler im permissiven Modus zu beheben, aber wechseln Sie so früh wie möglich wieder in den erzwingenden Modus und versuchen Sie, dort zu bleiben.
Häufige Fehler
Hier finden Sie einige Lösungen für häufige Fehler, die beim Schreiben gerätespezifischer Richtlinien passieren.
Übermäßiger Gebrauch der Verneinung
Die folgende Beispielregel ähnelt dem Abschließen der Haustür, aber dem Offenlassen der Fenster:
allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms
Die Absicht ist klar: Jeder außer Drittanbieter-Apps kann Zugriff auf das Debug-Gerät haben.
Die Regel weist in mehrfacher Hinsicht Mängel auf. Der Ausschluss von untrusted_app
lässt sich leicht umgehen, da alle Apps optional Dienste in der Domäne isolated_app
ausführen können. Wenn dem AOSP neue Domänen für Apps von Drittanbietern hinzugefügt werden, haben diese ebenfalls Zugriff auf scary_debug_device
. Die Regel ist zu freizügig. Die meisten Domänen profitieren nicht vom Zugriff auf dieses Debugging-Tool. Die Regel sollte so geschrieben sein, dass nur die Domänen zugelassen werden, die Zugriff benötigen.
Debugging-Funktionen in der Produktion
Debugfunktionen sollten weder in Produktionsbuilds noch in deren Richtlinien vorhanden sein.
Die einfachste Alternative besteht darin, die Debug-Funktion nur zuzulassen, wenn SELinux in eng/userdebug-Builds deaktiviert ist, wie z. adb root
und adb shell setenforce 0
.
Eine weitere sichere Alternative besteht darin, Debug-Berechtigungen in eine userdebug_or_eng- Anweisung einzuschließen.
Explosion der Policengröße
Die Charakterisierung von SEAndroid Policies in the Wild beschreibt einen besorgniserregenden Trend bei der Zunahme der Anpassung von Geräterichtlinien. Die gerätespezifische Richtlinie sollte 5–10 % der gesamten auf einem Gerät ausgeführten Richtlinie ausmachen. Anpassungen im Bereich von über 20 % beinhalten mit ziemlicher Sicherheit überprivilegierte Domänen und tote Richtlinien.
Unnötig große Police:
- Der Speicher wird doppelt beansprucht, da sich die Richtlinie auf der Ramdisk befindet und auch in den Kernel-Speicher geladen wird.
- Verschwendet Speicherplatz, da ein größeres Bootimage erforderlich ist.
- Beeinflusst die Suchzeiten für Laufzeitrichtlinien.
Das folgende Beispiel zeigt zwei Geräte, bei denen die herstellerspezifische Richtlinie 50 % und 40 % der geräteinternen Richtlinie ausmachte. Eine Neufassung der Richtlinie führte zu erheblichen Sicherheitsverbesserungen ohne Einbußen bei der Funktionalität, wie unten gezeigt. (Zum Vergleich sind die AOSP-Geräte Shamu und Flounder enthalten.)
In beiden Fällen wurde die Richtlinie sowohl im Umfang als auch in der Anzahl der Berechtigungen drastisch reduziert. Die Verringerung der Richtliniengröße ist fast ausschließlich auf die Entfernung unnötiger Berechtigungen zurückzuführen, bei denen es sich bei vielen wahrscheinlich um von audit2allow
generierte Regeln handelte, die der Richtlinie wahllos hinzugefügt wurden. Auch tote Domains waren bei beiden Geräten ein Problem.
Gewähren der dac_override-Fähigkeit
Eine dac_override
Ablehnung bedeutet, dass der fehlerhafte Prozess versucht, auf eine Datei mit den falschen Unix-Benutzer-/Gruppen-/Weltberechtigungen zuzugreifen. Die richtige Lösung besteht fast nie darin, die Berechtigung dac_override
zu erteilen. Ändern Sie stattdessen die Unix-Berechtigungen für die Datei oder den Prozess . Einige Domänen 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 .