Das Android Open Source Project (AOSP) bietet eine solide Basisrichtlinie für die Anwendungen und Dienste, die allen Android-Geräten gemeinsam sind. Mitarbeiter von AOSP entwickeln diese Richtlinie regelmäßig weiter. Es wird erwartet, dass die Kernrichtlinie etwa 90–95 % der endgültigen Richtlinie auf dem Gerät ausmacht, wobei gerätespezifische Anpassungen die restlichen 5–10 % ausmachen. Dieser Artikel konzentriert sich auf diese gerätespezifischen Anpassungen, das Schreiben gerätespezifischer Richtlinien und einige der Fallstricke, die dabei vermieden werden sollten.
Geräteaufruf
Führen Sie beim Schreiben der gerätespezifischen Richtlinie die folgenden Schritte aus.
Im zulässigen Modus ausführen
Wenn sich ein Gerät im Permissive-Modus befindet, werden Ablehnungen protokolliert, aber nicht erzwungen. Der zulässige Modus ist aus zwei Gründen wichtig:
- Der zulässige Modus stellt sicher, dass die Richtlinieneinführung andere frühe Geräteeinführungsaufgaben nicht verzögert.
- Eine erzwungene Ablehnung kann andere Ablehnungen maskieren. Zum Beispiel beinhaltet der Dateizugriff typischerweise eine Verzeichnissuche, Dateiöffnen, dann Dateilesen. Im Erzwingungsmodus würde nur die Verzeichnissuchverweigerung auftreten. Der zulässige Modus stellt sicher, dass alle Ablehnungen gesehen werden.
Der einfachste Weg, ein Gerät in den Permissive-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
. Führen Sie nach dem Ändern der Befehlszeile make clean
, dann make bootimage
aus und flashen Sie das neue Boot-Image.
Bestätigen Sie danach den Freigabemodus mit:
adb shell getenforce
Zwei Wochen sind ein angemessener Zeitraum, um sich im globalen Permissivmodus zu befinden. Nachdem Sie die Mehrheit der Denials behoben haben, wechseln Sie zurück in den Enforcing-Modus und beheben Sie Fehler, sobald sie auftreten. Domains, die noch Denials produzieren, oder Dienste, die sich noch in der intensiven Entwicklung befinden, können vorübergehend in den Permissive-Modus versetzt werden, aber verschieben Sie sie so schnell wie möglich wieder in den Enforcing-Modus.
Früh durchsetzen
Im Erzwingungsmodus werden Ablehnungen sowohl protokolliert als auch erzwungen. Es hat sich bewährt, Ihr Gerät so früh wie möglich in den Erzwingungsmodus 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 stellen Sie sicher, dass die Funktionalität in der Praxis vollständig durch Tests abgedeckt wird. Ein früher Beginn stellt sicher, dass Sicherheitsbedenken Designentscheidungen beeinflussen. Umgekehrt ist das Gewähren von Berechtigungen ausschließlich auf der Grundlage beobachteter Ablehnungen ein unsicherer Ansatz. Verwenden Sie diese Zeit, um eine Sicherheitsüberprüfung des Geräts durchzuführen und Bugs gegen Verhalten zu melden, das nicht zulässig sein sollte.
Entfernen oder löschen Sie eine vorhandene Richtlinie
Es gibt eine Reihe guter Gründe, eine gerätespezifische Richtlinie auf einem neuen Gerät von Grund auf neu zu erstellen, darunter:
- Sicherheitsüberprüfung
- Übermäßig freizügige Politik
- Reduzierung der Richtliniengröße
- Tote Politik
Adressieren Sie Ablehnungen von Kerndiensten
Denials, die von Kerndiensten generiert werden, werden normalerweise durch Dateikennzeichnung adressiert. 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 richtige Bezeichnung von /dev/kgsl-3d0
vollständig angegangen. In diesem Beispiel ist tcontext
das device
. Dies stellt einen Standardkontext dar, in dem alles in /dev
das Label „ Gerät “ erhält, es sei denn, es wird ein spezifischeres Label zugewiesen. Das einfache Akzeptieren der Ausgabe von audit2allow hier würde zu einer falschen und übermäßig freizügigen Regel führen.
Um diese Art von 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 bereits über die erforderlichen Berechtigungen in der Kernrichtlinie verfügt, um auf gpu_device zuzugreifen.
Andere gerätespezifische Dateien, die mit in der Kernrichtlinie vordefinierten Typen gekennzeichnet werden sollten:
- Geräte blockieren
- Audiogeräte
- Videogeräte
- Sensoren
- nfc
- GPS-Gerät
- Dateien in /sys
- Dateien in /proc
Im Allgemeinen ist es falsch, Standardlabels Berechtigungen zu erteilen. Viele dieser Berechtigungen werden durch Neverallow- Regeln verweigert, aber selbst wenn sie nicht ausdrücklich verweigert werden, empfiehlt es sich, eine bestimmte Bezeichnung bereitzustellen.
Kennzeichnen Sie neue Dienste und Adressverweigerungen
Von 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 gewährt ihm Berechtigungen.
Der Dienst wird in der 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 Operationen basieren, die von dieser ausführbaren Datei ausgeführt werden.
- Bezeichnung
/system/bin/foo
Fügen Sie Folgendes zu
device/ manufacturer / device-name /sepolicy/file_contexts
:/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 audit2allow- Tool bietet gute Richtlinien, aber verwenden Sie es nur zum Verfassen von Richtlinien. Kopieren Sie nicht einfach die Ausgabe.
Wechseln Sie zurück in den Erzwingungsmodus
Es ist in Ordnung, den Fehler im zulässigen Modus zu beheben, aber wechseln Sie so früh wie möglich zurück in den erzwingenden Modus und versuchen Sie, dort zu bleiben.
Häufige Fehler
Hier sind einige Lösungen für häufige Fehler, die beim Schreiben gerätespezifischer Richtlinien auftreten.
Überbeanspruchung der Verneinung
Die folgende Beispielregel ist so, als würde man die Haustür abschließen, aber die Fenster offen lassen:
allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms
Die Absicht ist klar: Jeder außer Apps von Drittanbietern kann Zugriff auf das Debug-Gerät haben.
Die Regel ist in einigen Punkten fehlerhaft. Der Ausschluss von untrusted_app
ist einfach zu umgehen, da alle Apps optional Dienste in der Domäne „ isolated_app
“ ausführen können. Wenn neue Domains für Apps von Drittanbietern zu AOSP hinzugefügt werden, haben sie 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 werden, dass nur die Domänen zugelassen werden, die Zugriff benötigen.
Debugging-Funktionen in der Produktion
Debug-Features sollten in Produktions-Builds nicht vorhanden sein, und auch ihre Richtlinie sollte nicht vorhanden sein.
Die einfachste Alternative besteht darin, die Debug-Funktion nur zuzulassen, wenn SELinux auf eng/userdebug-Builds wie adb root
und adb shell setenforce 0
ist.
Eine weitere sichere Alternative besteht darin, Debug-Berechtigungen in eine userdebug_or_eng- Anweisung einzuschließen.
Explosion der Richtliniengröße
Characterizing SEAndroid Policies in the Wild beschreibt einen besorgniserregenden Trend bei der Zunahme von Geräterichtlinienanpassungen. Gerätespezifische Richtlinien sollten 5–10 % der Gesamtrichtlinie ausmachen, die auf einem Gerät ausgeführt wird. Anpassungen im Bereich von über 20 % enthalten mit ziemlicher Sicherheit überprivilegierte Domänen und tote Richtlinien.
Unnötig große Richtlinie:
- Erhält einen doppelten Arbeitsspeicher, da sich die Richtlinie auf der Ramdisk befindet und auch in den Kernel-Speicher geladen wird.
- Verschwendet Speicherplatz, indem 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 Richtlinie auf dem Gerät ausmachte. Eine Neufassung der Richtlinie führte zu erheblichen Sicherheitsverbesserungen ohne Funktionsverlust, wie unten gezeigt. (Die AOSP-Geräte Shamu und Flounder sind zum Vergleich enthalten.)
Abbildung 1 . Vergleich der gerätespezifischen Richtliniengröße nach dem Sicherheitsaudit.
In beiden Fällen wurde die Richtlinie sowohl in der Größe als auch in der Anzahl der Berechtigungen drastisch reduziert. Die Verringerung der Richtliniengröße ist fast ausschließlich auf das Entfernen unnötiger Berechtigungen zurückzuführen, von denen viele wahrscheinlich von audit2allow
generierte Regeln waren, die wahllos der Richtlinie hinzugefügt wurden. Auch tote Domains waren bei beiden Geräten ein Thema.
Gewähren der dac_override-Fähigkeit
Eine dac_override
Verweigerung bedeutet, dass der angreifende Prozess versucht, auf eine Datei mit den falschen Unix-Benutzer-/Gruppen-/World-Berechtigungen zuzugreifen. Die richtige Lösung besteht fast nie darin, die dac_override
Berechtigung 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 wirklich die Möglichkeit, Unix-Dateiberechtigungen zu überschreiben, um auf die Dateien anderer Prozesse zuzugreifen. Siehe Dan Walshs Blog für eine ausführlichere Erklärung.