In diesem Artikel wird beschrieben, wie Android mit den Richtlinienkompatibilitätsproblemen mit Plattform-OTAs umgeht, bei denen neue SELinux-Plattformeinstellungen von den SELinux-Einstellungen alter Anbieter abweichen können.
Das dreifache SELinux-Richtliniendesign berücksichtigt eine binäre Unterscheidung zwischen Plattform- und Anbieterrichtlinie . Das Schema wird komplizierter, wenn Herstellerpartitionen Abhängigkeiten generieren, z. B. platform
< vendor
< oem
.
In Android 8.0 und höher ist die globale SELinux-Richtlinie in private und öffentliche Komponenten unterteilt. Öffentliche Komponenten bestehen aus der Richtlinie und der zugehörigen Infrastruktur, die garantiert für eine Plattformversion verfügbar sind. Diese Richtlinie wird Anbieterrichtlinienautoren zur Verfügung gestellt, damit Anbieter eine Anbieterrichtliniendatei erstellen können, die in Kombination mit der von der Plattform bereitgestellten Richtlinie zu einer voll funktionsfähigen Richtlinie für ein Gerät führt.
- Zur Versionierung werden die exportierten Plattform-Public-Richtlinien als Attribute geschrieben.
- Um das Verfassen von Richtlinien zu vereinfachen, werden exportierte Typen im Rahmen des Richtlinienerstellungsprozesses in versionierte Attribute umgewandelt. Öffentliche Typen können auch direkt in Kennzeichnungsentscheidungen verwendet werden, die von Anbieterkontextdateien bereitgestellt werden.
Android verwaltet eine Zuordnung zwischen exportierten konkreten Typen in der Plattformrichtlinie und den entsprechenden versionierten Attributen für jede Plattformversion . Dadurch wird sichergestellt, dass das durch die Plattform-Public-Richtlinie in einer früheren Version garantierte Verhalten nicht beeinträchtigt wird, wenn Objekte mit einem Typ gekennzeichnet werden. Diese Zuordnung wird aufrechterhalten, indem eine Zuordnungsdatei für jede Plattformversion auf dem neuesten Stand gehalten wird, die die Attributmitgliedschaftsinformationen für jeden in der öffentlichen Richtlinie exportierten Typ speichert.
Objektbesitz und -kennzeichnung
Beim Anpassen von Richtlinien in Android 8.0 und höher muss der Besitz für jedes Objekt klar definiert werden, um Plattform- und Anbieterrichtlinien getrennt zu halten. Wenn beispielsweise der Anbieter /dev/foo
und die Plattform in einem nachfolgenden OTA dann /dev/foo
beschriften, kommt es zu undefiniertem Verhalten. Bei SELinux äußert sich dies in einer Etikettierungskollision. Der Geräteknoten kann nur eine einzige Bezeichnung haben, die in die zuletzt angewendete Bezeichnung aufgelöst wird. Infolge:
- Prozesse, die Zugriff auf das erfolglos angewendete Label benötigen, verlieren den Zugriff auf die Ressource.
- Prozesse, die Zugriff auf die Datei erhalten , brechen möglicherweise ab, weil der falsche Geräteknoten erstellt wurde.
Systemeigenschaften können auch zu Namenskollisionen führen, die zu undefiniertem Verhalten auf dem System führen können (sowie zur SELinux-Kennzeichnung). Kollisionen zwischen Plattform- und Anbieterlabels können für jedes Objekt auftreten, das über ein SELinux-Label verfügt, einschließlich Eigenschaften, Dienste, Prozesse, Dateien und Sockets. Um diese Probleme zu vermeiden, definieren Sie den Besitz dieser Objekte klar.
Zusätzlich zu Labelkollisionen können auch SELinux-Typ-/Attributnamen kollidieren. Eine Typ-/Attributnamenkollision führt immer zu einem Richtlinien-Compiler-Fehler.
Typ-/Attribut-Namespace
SELinux erlaubt nicht mehrere Deklarationen desselben Typs/Attributs. Richtlinien mit doppelten Deklarationen können nicht kompiliert werden. Um Kollisionen zwischen Typ- und Attributnamen zu vermeiden, sollten alle Herstellerdeklarationen einen Namensraum haben, der mit np_
beginnt.
type foo, domain; → type np_foo, domain;
Eigentum an Systemeigenschaften und Prozesskennzeichnungen
Die Vermeidung von Beschriftungskollisionen lässt sich am besten mithilfe von Eigenschaftsnamensräumen lösen. Um Plattformeigenschaften einfach zu identifizieren und Namenskonflikte beim Umbenennen oder Hinzufügen exportierter Plattformeigenschaften zu vermeiden, stellen Sie sicher, dass alle Anbietereigenschaften ihre eigenen Präfixe haben:
Art der Immobilie | Akzeptable Präfixe |
---|---|
Steuereigenschaften | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor. |
lesbar und beschreibbar | vendor. |
schreibgeschützt | ro.vendor. ro.boot. ro.hardware. |
hartnäckig | persist.vendor. |
Anbieter können weiterhin ro.boot.*
(das aus der Kernel-Cmdline stammt) und ro.hardware.*
(eine offensichtliche hardwarebezogene Eigenschaft) verwenden.
Alle Anbieterdienste in Init-RC-Dateien sollten vendor.
für Dienste in Init-RC-Dateien von Nicht-Systempartitionen. Ähnliche Regeln werden auf die SELinux-Bezeichnungen für die Anbietereigenschaften angewendet ( vendor_
für die Anbietereigenschaften).
Dateieigentum
Kollisionen für Dateien zu verhindern ist eine Herausforderung, da Plattform- und Herstellerrichtlinien üblicherweise Bezeichnungen für alle Dateisysteme bereitstellen. Im Gegensatz zur Typbenennung ist die Benennung von Dateinamen nicht praktikabel, da viele Dateien vom Kernel erstellt werden. Um diese Kollisionen zu verhindern, befolgen Sie die Benennungshinweise für Dateisysteme in diesem Abschnitt. Für Android 8.0 handelt es sich um Empfehlungen ohne technische Durchsetzung. Zukünftig werden diese Empfehlungen durch die Vendor Test Suite (VTS) durchgesetzt.
System (/system)
Nur das Systemabbild muss Beschriftungen für /system
Komponenten über file_contexts
, service_contexts
usw. bereitstellen. Wenn Beschriftungen für /system
Komponenten in /vendor
Richtlinie hinzugefügt werden, ist ein OTA-Update nur für das Framework möglicherweise nicht möglich.
Anbieter (/vendor)
Die AOSP SELinux-Richtlinie kennzeichnet bereits Teile der vendor
, mit der die Plattform interagiert, was das Schreiben von SELinux-Regeln für Plattformprozesse ermöglicht, damit Teile der vendor
kommunizieren und/oder darauf zugreifen können. Beispiele:
/vendor Pfad | Von der Plattform bereitgestelltes Etikett | Plattformprozesse abhängig vom Label |
---|---|---|
/vendor(/. * )? | vendor_file | Alle HAL-Clients im Framework, ueventd usw. |
/vendor/framework(/. * )? | vendor_framework_file | dex2oat , appdomain usw. |
/vendor/app(/. * )? | vendor_app_file | dex2oat , installd , idmap usw. |
/vendor/overlay(/. * ) | vendor_overlay_file | system_server , zygote , idmap usw. |
Daher müssen beim Kennzeichnen zusätzlicher Dateien in vendor
bestimmte Regeln befolgt werden (durchgesetzt durch neverallows
):
-
vendor_file
muss die Standardbezeichnung für alle Dateien invendor
Partition sein. Die Plattformrichtlinie erfordert dies, um auf Passthrough-HAL-Implementierungen zuzugreifen. - Alle neuen
exec_types
, die über die Vendor-SEPolicy in dervendor
Partition hinzugefügt werden, müssen über das Attributvendor_file_type
verfügen. Dies wird durch Neverallows erzwungen. - Um Konflikte mit zukünftigen Plattform-/Framework-Updates zu vermeiden, vermeiden Sie die Kennzeichnung anderer Dateien als
exec_types
in dervendor
. - Alle Bibliotheksabhängigkeiten für AOSP-identifizierte HALs desselben Prozesses müssen als
same_process_hal_file.
Prozesse (/proc)
Dateien in /proc
dürfen nur mit der Bezeichnung genfscon
gekennzeichnet werden. In Android 7.0 verwendeten sowohl die Plattform- als auch die Anbieterrichtlinie genfscon
, um Dateien in procfs
zu kennzeichnen.
Empfehlung: Nur Plattformrichtlinienbezeichnungen /proc
. Wenn vendor
Zugriff auf Dateien in /proc
benötigen, die derzeit mit der Standardbezeichnung ( proc
) gekennzeichnet sind, sollte die Anbieterrichtlinie sie nicht explizit kennzeichnen und stattdessen den generischen proc
Typ verwenden, um Regeln für Anbieterdomänen hinzuzufügen. Dies ermöglicht es den Plattformaktualisierungen, zukünftige Kernel-Schnittstellen zu berücksichtigen, die über procfs
verfügbar gemacht werden, und sie bei Bedarf explizit zu kennzeichnen.
Debugfs (/sys/kernel/debug)
Debugfs
können sowohl in file_contexts
als auch genfscon
gekennzeichnet werden. In Android 7.0 bis Android 10 tragen sowohl die Plattform- als auch die Herstellerbezeichnung debugfs
.
In Android 11 kann debugfs
nicht auf Produktionsgeräten zugegriffen oder diese gemountet werden. Gerätehersteller sollten debugfs
entfernen.
Tracefs (/sys/kernel/debug/tracing)
Tracefs
können sowohl in file_contexts
als auch genfscon
gekennzeichnet werden. In Android 7.0 trägt nur die Plattform die Bezeichnung tracefs
.
Empfehlung: Nur die Plattform darf tracefs
kennzeichnen.
Sysfs (/sys)
Dateien in /sys
können sowohl mit file_contexts
als auch genfscon
gekennzeichnet werden. In Android 7.0 verwenden sowohl die Plattform als auch der Anbieter file_contexts
und genfscon
, um Dateien in sysfs
zu kennzeichnen.
Empfehlung: Die Plattform kann sysfs
Knoten kennzeichnen, die nicht gerätespezifisch sind. Andernfalls darf nur der Anbieter Dateien kennzeichnen.
tmpfs (/dev)
Dateien in /dev
können in file_contexts
gekennzeichnet sein. In Android 7.0 finden Sie hier sowohl Plattform- als auch Hersteller-Labeldateien.
Empfehlung: Der Anbieter darf nur Dateien in /dev/vendor
kennzeichnen (z. B. /dev/vendor/foo
, /dev/vendor/socket/bar
).
Rootfs (/)
Dateien in /
können in file_contexts
gekennzeichnet werden. In Android 7.0 finden Sie hier sowohl Plattform- als auch Hersteller-Labeldateien.
Empfehlung: Nur das System darf Dateien in /
kennzeichnen.
Daten (/data)
Daten werden durch eine Kombination aus file_contexts
und seapp_contexts
gekennzeichnet.
Empfehlung: Anbieterkennzeichnung außerhalb von /data/vendor
nicht zulassen. Nur die Plattform darf andere Teile von /data
kennzeichnen.
Kompatibilitätsattribute
Bei der SELinux-Richtlinie handelt es sich um eine Interaktion zwischen Quell- und Zieltypen für bestimmte Objektklassen und Berechtigungen. Jedes Objekt (Prozesse, Dateien usw.), das von der SELinux-Richtlinie betroffen ist, kann nur einen Typ haben, dieser Typ kann jedoch mehrere Attribute haben.
Richtlinien werden hauptsächlich in Bezug auf vorhandene Typen geschrieben:
allow source_type target_type:target_class permission(s);
Dies funktioniert, weil die Richtlinie mit Wissen aller Art verfasst wurde. Wenn jedoch die Anbieterrichtlinie und die Plattformrichtlinie bestimmte Typen verwenden und sich die Bezeichnung eines bestimmten Objekts nur in einer dieser Richtlinien ändert, enthält die andere möglicherweise eine Richtlinie, die zuvor den Zugriff erlangt oder verloren hat. Zum Beispiel:
File_contexts: /sys/A u:object_r:sysfs:s0 Platform: allow p_domain sysfs:class perm; Vendor: allow v_domain sysfs:class perm;
Könnte geändert werden in:
File_contexts: /sys/A u:object_r:sysfs_A:s0
Obwohl die Anbieterrichtlinie dieselbe bleiben würde, würde die v_domain
aufgrund der fehlenden Richtlinie für den neuen Typ sysfs_A
den Zugriff verlieren.
Indem wir eine Richtlinie anhand von Attributen definieren, können wir dem zugrunde liegenden Objekt einen Typ zuweisen, der über ein Attribut verfügt, das der Richtlinie sowohl für die Plattform als auch für den Anbietercode entspricht. Dies kann für alle Typen durchgeführt werden, um effektiv eine Attributrichtlinie zu erstellen, in der konkrete Typen niemals verwendet werden. In der Praxis ist dies nur für die Teile der Richtlinie erforderlich, die sich zwischen Plattform und Anbieter überschneiden und als öffentliche Plattformrichtlinie definiert und bereitgestellt werden, die als Teil der Anbieterrichtlinie erstellt wird.
Durch die Definition öffentlicher Richtlinien als versionierte Attribute werden zwei Richtlinienkompatibilitätsziele erfüllt:
- Stellen Sie sicher, dass der Herstellercode nach der Plattformaktualisierung weiterhin funktioniert . Erreicht wird dies durch das Hinzufügen von Attributen zu konkreten Objekttypen, die denen entsprechen, auf denen der Herstellercode basiert, wodurch der Zugriff erhalten bleibt.
- Möglichkeit, Richtlinien abzulehnen . Dies wird erreicht, indem Richtliniensätze klar in Attribute unterteilt werden, die entfernt werden können, sobald die Version, der sie entsprechen, nicht mehr unterstützt wird. Die Entwicklung kann auf der Plattform fortgesetzt werden, da die alte Richtlinie immer noch in der Anbieterrichtlinie enthalten ist und bei einem Upgrade automatisch entfernt wird.
Beschreibbarkeit von Richtlinien
Um das Ziel zu erreichen, dass für die Richtlinienentwicklung keine Kenntnisse über bestimmte Versionsänderungen erforderlich sind, enthält Android 8.0 eine Zuordnung zwischen plattformöffentlichen Richtlinientypen und ihren Attributen. Der Typ foo
wird dem Attribut foo_v N
zugeordnet, wobei N
die Zielversion ist. vN
entspricht der Build-Variable PLATFORM_SEPOLICY_VERSION
und hat die Form MM.NN
, wobei MM
der Plattform-SDK-Nummer entspricht und NN
eine plattformspezifische Sepolicy-Version ist.
Attribute in der öffentlichen Richtlinie sind nicht versioniert, sondern existieren als API, auf der Plattform- und Anbieterrichtlinien aufbauen können, um die Schnittstelle zwischen den beiden Partitionen stabil zu halten. Sowohl Plattform- als auch Hersteller-Richtlinienautoren können weiterhin Richtlinien so schreiben, wie sie heute verfasst sind.
Plattform-öffentliche Richtlinie exportiert allow source_foo target_bar: class perm ;
ist Teil der Anbieterrichtlinie. Während der Kompilierung (einschließlich der entsprechenden Version) wird sie in die Richtlinie umgewandelt, die an den Herstellerteil des Geräts gesendet wird (dargestellt in der transformierten Common Intermediate Language (CIL)):
(allow source_foo_vN target_bar_vN (class (perm)))
Da die Richtlinien des Anbieters niemals der Plattform voraus sind, sollten sie sich nicht mit früheren Versionen befassen. Allerdings muss die Plattformrichtlinie wissen, wie weit die Herstellerrichtlinie zurückliegt, Attribute zu ihren Typen hinzufügen und Richtlinien festlegen, die versionierten Attributen entsprechen.
Richtlinienunterschiede
Das automatische Erstellen von Attributen durch Hinzufügen _v N
am Ende jedes Typs bewirkt nichts ohne die Zuordnung von Attributen zu Typen über Versionsunterschiede hinweg. Android verwaltet eine Zuordnung zwischen Versionen für Attribute und eine Zuordnung von Typen zu diesen Attributen. Dies geschieht in den oben genannten Mapping-Dateien mit Anweisungen, wie zum Beispiel (CIL):
(typeattributeset foo_vN (foo))
Plattform-Upgrades
Im folgenden Abschnitt werden Szenarios für Plattform-Upgrades detailliert beschrieben.
Gleiche Typen
Dieses Szenario tritt auf, wenn ein Objekt die Bezeichnungen in Richtlinienversionen nicht ändert. Dies gilt für Quell- und Zieltypen und kann anhand von /dev/binder
gesehen werden, das in allen Versionen mit binder_device
gekennzeichnet ist. Es wird in der transformierten Politik dargestellt als:
binder_device_v1 … binder_device_vN
Beim Upgrade von v1
→ v2
muss die Plattformrichtlinie Folgendes enthalten:
type binder_device; -> (type binder_device) (in CIL)
In der v1-Zuordnungsdatei (CIL):
(typeattributeset binder_device_v1 (binder_device))
In der v2-Zuordnungsdatei (CIL):
(typeattributeset binder_device_v2 (binder_device))
In der V1-Anbieterrichtlinie (CIL):
(typeattribute binder_device_v1) (allow binder_device_v1 …)
In der V2-Anbieterrichtlinie (CIL):
(typeattribute binder_device_v2) (allow binder_device_v2 …)
Neue Typen
Dieses Szenario tritt auf, wenn die Plattform einen neuen Typ hinzugefügt hat, was beim Hinzufügen neuer Funktionen oder während der Richtlinienhärtung passieren kann.
- Neue Funktion . Wenn der Typ ein Objekt kennzeichnet, das zuvor nicht vorhanden war (z. B. einen neuen Serviceprozess), hat der Anbietercode zuvor nicht direkt mit ihm interagiert, sodass keine entsprechende Richtlinie vorhanden ist. Das neue Attribut, das dem Typ entspricht, verfügt über kein Attribut in der vorherigen Version und benötigt daher keinen Eintrag in der Zuordnungsdatei, die auf diese Version abzielt.
- Politikverhärtung . Wenn der Typ eine Richtlinienhärtung darstellt, muss das neue Typattribut mit einer Kette von Attributen verknüpft sein, die dem vorherigen entsprechen (ähnlich wie im vorherigen Beispiel, bei dem
/sys/A
vonsysfs
insysfs_A
geändert wurde). Der Code des Anbieters basiert auf einer Regel, die den Zugriff aufsysfs
ermöglicht, und muss diese Regel als Attribut des neuen Typs einschließen.
Beim Upgrade von v1
→ v2
muss die Plattformrichtlinie Folgendes enthalten:
type sysfs_A; -> (type sysfs_A) (in CIL) type sysfs; (type sysfs) (in CIL)
In der v1-Zuordnungsdatei (CIL):
(typeattributeset sysfs_v1 (sysfs sysfs_A))
In der v2-Zuordnungsdatei (CIL):
(typeattributeset sysfs_v2 (sysfs)) (typeattributeset sysfs_A_v2 (sysfs_A))
In der V1-Anbieterrichtlinie (CIL):
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
In der V2-Anbieterrichtlinie (CIL):
(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)
Entfernte Typen
Dieses (seltene) Szenario tritt auf, wenn ein Typ entfernt wird, was passieren kann, wenn das zugrunde liegende Objekt:
- Bleibt, erhält aber ein anderes Etikett.
- Wird von der Plattform entfernt.
Bei der Lockerung der Richtlinien wird ein Typ entfernt und das mit diesem Typ gekennzeichnete Objekt erhält eine andere, bereits vorhandene Bezeichnung. Dies stellt eine Verschmelzung von Attributzuordnungen dar: Der Herstellercode muss weiterhin über das Attribut, das er zuvor besaß, auf das zugrunde liegende Objekt zugreifen können, der Rest des Systems muss jedoch jetzt über sein neues Attribut darauf zugreifen können.
Wenn das Attribut, auf das umgestellt wurde, neu ist, erfolgt die Umbenennung auf die gleiche Weise wie im Fall des neuen Typs, mit der Ausnahme, dass bei Verwendung einer vorhandenen Bezeichnung das Hinzufügen des neuen Typs des alten Attributs dazu führen würde, dass auch andere Objekte mit diesem Typ beschriftet werden neu zugänglich sein. Dies geschieht im Wesentlichen durch die Plattform und wird als akzeptabler Kompromiss zur Aufrechterhaltung der Kompatibilität angesehen.
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
Beispielversion 1: Reduzieren von Typen (Entfernen von sysfs_A)
Beim Upgrade von v1
→ v2
muss die Plattformrichtlinie Folgendes enthalten:
type sysfs; (type sysfs) (in CIL)
In der v1-Zuordnungsdatei (CIL):
(typeattributeset sysfs_v1 (sysfs)) (type sysfs_A) # in case vendors used the sysfs_A label on objects (typeattributeset sysfs_A_v1 (sysfs sysfs_A))
In der v2-Zuordnungsdatei (CIL):
(typeattributeset sysfs_v2 (sysfs))
In der V1-Anbieterrichtlinie (CIL):
(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)
In der V2-Anbieterrichtlinie (CIL):
(typeattribute sysfs_v2) (allow … sysfs_v2 …)
Beispielversion 2: Vollständig entfernen (Typ foo)
Beim Upgrade von v1
→ v2
muss die Plattformrichtlinie Folgendes enthalten:
# nothing - we got rid of the type
In der v1-Zuordnungsdatei (CIL):
(type foo) #needed in case vendors used the foo label on objects (typeattributeset foo_v1 (foo))
In der v2-Zuordnungsdatei (CIL):
# nothing - get rid of it
In der V1-Anbieterrichtlinie (CIL):
(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)
In der V2-Anbieterrichtlinie (CIL):
(typeattribute sysfs_v2) (allow sysfs_v2 …)
Neue Klasse/Berechtigungen
Dieses Szenario tritt auf, wenn bei einem Plattform-Upgrade neue Richtlinienkomponenten eingeführt werden, die in früheren Versionen nicht vorhanden waren. Als Android beispielsweise den servicemanager
Objektmanager hinzufügte, der die Berechtigungen zum Hinzufügen, Suchen und Auflisten erstellte, benötigten Anbieterdämonen, die sich beim servicemanager
registrieren wollten, Berechtigungen, die nicht verfügbar waren. In Android 8.0 darf nur die Plattformrichtlinie neue Klassen und Berechtigungen hinzufügen.
Um allen Domänen, die durch Anbieterrichtlinien hätten erstellt oder erweitert werden können, die ungehinderte Nutzung der neuen Klasse zu ermöglichen, muss die Plattformrichtlinie eine Regel ähnlich der folgenden enthalten:
allow {domain -coredomain} *:new_class perm;
Dies erfordert möglicherweise sogar eine Richtlinie, die den Zugriff für alle Schnittstellentypen (öffentliche Richtlinie) ermöglicht, um sicherzustellen, dass das Anbieter-Image Zugriff erhält. Wenn dies zu einer inakzeptablen Sicherheitsrichtlinie führt (wie es bei den Servicemanager-Änderungen der Fall sein kann), könnte möglicherweise ein Anbieter-Upgrade erzwungen werden.
Klasse/Berechtigungen entfernt
Dieses Szenario tritt auf, wenn ein Objektmanager entfernt wird (z. B. der ZygoteConnection
Objektmanager) und sollte keine Probleme verursachen. Die Objektmanagerklasse und -berechtigungen könnten in der Richtlinie definiert bleiben, bis sie von der Anbieterversion nicht mehr verwendet werden. Dies erfolgt durch Hinzufügen der Definitionen zur entsprechenden Mapping-Datei.
Anbieteranpassung für neue/umbenannte Typen
Neue Anbietertypen stehen im Mittelpunkt der Entwicklung von Anbieterrichtlinien, da sie zur Beschreibung neuer Prozesse, Binärdateien, Geräte, Subsysteme und gespeicherter Daten benötigt werden. Daher ist es unbedingt erforderlich, die Erstellung herstellerdefinierter Typen zu ermöglichen.
Da die Anbieterrichtlinie immer die älteste auf dem Gerät ist, besteht keine Notwendigkeit, alle Anbietertypen automatisch in Attribute in der Richtlinie umzuwandeln. Die Plattform verlässt sich nicht auf irgendetwas, was in den Richtlinien des Anbieters angegeben ist, da die Plattform keine Kenntnis davon hat; Die Plattform stellt jedoch die Attribute und öffentlichen Typen bereit, die sie für die Interaktion mit Objekten verwendet, die mit diesen Typen gekennzeichnet sind (z. B. domain
, sysfs_type
usw.). Damit die Plattform weiterhin korrekt mit diesen Objekten interagieren kann, müssen die Attribute und Typen ordnungsgemäß angewendet werden und möglicherweise müssen bestimmte Regeln zu den anpassbaren Domänen hinzugefügt werden (z. B. init
).
Attributänderungen für Android 9
Geräte, die auf Android 9 aktualisieren, können die folgenden Attribute verwenden, Geräte, die mit Android 9 starten, dürfen dies jedoch nicht.
Attribute des Verstoßes
Android 9 umfasst diese domänenbezogenen Attribute:
-
data_between_core_and_vendor_violators
. Attribut für alle Domänen, die gegen die Anforderung verstoßen, Dateien nicht nach Pfad zwischenvendor
undcoredomains
zu teilen. Plattform- und Anbieterprozesse sollten keine Dateien auf der Festplatte zur Kommunikation verwenden (instabile ABI). Empfehlung:- Der Anbietercode sollte
/data/vendor
verwenden. - Das System sollte
/data/vendor
nicht verwenden.
- Der Anbietercode sollte
-
system_executes_vendor_violators
. Attribut für alle Systemdomänen (außerinit
undshell domains
), die gegen die Anforderung verstoßen, keine Anbieterbinärdateien auszuführen. Die Ausführung von Anbieter-Binärdateien hat eine instabile API. Die Plattform sollte die Binärdateien des Anbieters nicht direkt ausführen. Empfehlung:- Solche Plattformabhängigkeiten von Anbieter-Binärdateien müssen hinter HIDL-HALs stehen.
ODER
-
coredomains
, die Zugriff auf Binärdateien des Anbieters benötigen, sollten in die Vendor-Partition verschoben werden und daher nicht mehrcoredomain
sein.
- Solche Plattformabhängigkeiten von Anbieter-Binärdateien müssen hinter HIDL-HALs stehen.
Nicht vertrauenswürdige Attribute
Nicht vertrauenswürdige Apps, die beliebigen Code hosten, sollten keinen Zugriff auf HwBinder-Dienste haben, es sei denn, sie gelten als ausreichend sicher für den Zugriff durch solche Apps (siehe sichere Dienste unten). Die beiden Hauptgründe dafür sind:
- HwBinder-Server führen keine Clientauthentifizierung durch, da HIDL derzeit keine Anrufer-UID-Informationen offenlegt. Selbst wenn HIDL solche Daten offengelegt hätte, operieren viele HwBinder-Dienste entweder auf einer Ebene unterhalb der von Apps (z. B. HALs) oder dürfen sich bei der Autorisierung nicht auf die App-Identität verlassen. Aus Sicherheitsgründen wird daher standardmäßig davon ausgegangen, dass jeder HwBinder-Dienst alle seine Clients als gleichermaßen berechtigt behandelt, die vom Dienst angebotenen Vorgänge auszuführen.
- HAL-Server (eine Teilmenge der HwBinder-Dienste) enthalten Code mit einer höheren Inzidenzrate von Sicherheitsproblemen als
system/core
und haben Zugriff auf die unteren Schichten des Stapels (bis hinunter zur Hardware), wodurch sich die Möglichkeiten zur Umgehung des Android-Sicherheitsmodells erhöhen .
Sichere Dienste
Zu den sicheren Dienstleistungen gehören:
-
same_process_hwservice
. Diese Dienste werden (per Definition) im Prozess des Clients ausgeführt und haben daher denselben Zugriff wie die Clientdomäne, in der der Prozess ausgeführt wird. -
coredomain_hwservice
. Diese Dienste stellen keine mit Grund Nr. 2 verbundenen Risiken dar. -
hal_configstore_ISurfaceFlingerConfigs
. Dieser Dienst ist speziell für die Nutzung durch jede Domain konzipiert. -
hal_graphics_allocator_hwservice
. Diese Vorgänge werden auch vomsurfaceflinger
Binder-Dienst angeboten, auf den Apps zugreifen dürfen. -
hal_omx_hwservice
. Dies ist eine HwBinder-Version desmediacodec
Binder-Dienstes, auf den Apps zugreifen dürfen. -
hal_codec2_hwservice
. Dies ist eine neuere Version vonhal_omx_hwservice
.
Verwendbare Attribute
Alle nicht als sicher geltenden hwservices
haben das Attribut untrusted_app_visible_hwservice
. Die entsprechenden HAL-Server haben das Attribut untrusted_app_visible_halserver
. Geräte, die mit Android 9 gestartet werden, DÜRFEN KEINES der nicht untrusted
Attribute verwenden.
Empfehlung:
- Nicht vertrauenswürdige Apps sollten stattdessen mit einem Systemdienst kommunizieren, der mit dem Anbieter HIDL HAL kommuniziert. Apps können beispielsweise mit
binderservicedomain
kommunizieren, dann kommuniziertmediaserver
(der einebinderservicedomain
ist) wiederum mithal_graphics_allocator
.ODER
- Apps, die direkten Zugriff auf
vendor
HALs benötigen, sollten über eine eigene, vom Anbieter definierte Sepolicy-Domäne verfügen.
Dateiattributtests
Android 9 umfasst Buildzeittests , die sicherstellen, dass alle Dateien an bestimmten Speicherorten über die entsprechenden Attribute verfügen (z. B. alle Dateien in sysfs
über das erforderliche sysfs_type
Attribut).
Plattform-öffentliche Politik
Die plattformöffentliche Richtlinie ist der Kern der Konformität mit dem Android 8.0-Architekturmodell, ohne einfach die Vereinigung der Plattformrichtlinien von Version 1 und Version 2 beizubehalten. Anbieter sind einem Teilsatz der Plattformrichtlinie ausgesetzt, der verwendbare Typen und Attribute sowie Regeln für diese Typen und Attribute enthält, die dann Teil der Anbieterrichtlinie werden (z. B. vendor_sepolicy.cil
“).
Typen und Regeln werden in der vom Anbieter generierten Richtlinie automatisch in attribute_v N
übersetzt, sodass alle von der Plattform bereitgestellten Typen versionierte Attribute sind (Attribute sind jedoch nicht versioniert). Die Plattform ist dafür verantwortlich, die von ihr bereitgestellten konkreten Typen den entsprechenden Attributen zuzuordnen, um sicherzustellen, dass die Anbieterrichtlinie weiterhin funktioniert und die für eine bestimmte Version bereitgestellten Regeln enthalten sind. Die Kombination aus öffentlicher Plattformrichtlinie und Anbieterrichtlinie erfüllt das Ziel des Android 8.0-Architekturmodells, unabhängige Plattform- und Anbieter-Builds zu ermöglichen.
Zuordnung zu Attributketten
Bei der Verwendung von Attributen zur Zuordnung zu Richtlinienversionen wird ein Typ einem oder mehreren Attributen zugeordnet, wodurch sichergestellt wird, dass mit dem Typ gekennzeichnete Objekte über Attribute zugänglich sind, die ihren vorherigen Typen entsprechen.
Um das Ziel beizubehalten, Versionsinformationen vor dem Richtlinienautor zu verbergen, müssen die versionierten Attribute automatisch generiert und den entsprechenden Typen zugewiesen werden. Im allgemeinen Fall statischer Typen ist dies unkompliziert: type_foo
wird auf type_foo_v1
abgebildet.
Für eine Objektbezeichnungsänderung wie sysfs
→ sysfs_A
oder mediaserver
→ audioserver
ist das Erstellen dieser Zuordnung nicht trivial (und wird in den obigen Beispielen beschrieben). Betreuer von Plattformrichtlinien müssen bestimmen, wie die Zuordnung an Übergangspunkten für Objekte erstellt wird. Dazu ist es erforderlich, die Beziehung zwischen Objekten und den ihnen zugewiesenen Bezeichnungen zu verstehen und zu bestimmen, wann dies geschieht. Aus Gründen der Abwärtskompatibilität muss diese Komplexität auf der Plattformseite verwaltet werden, die die einzige Partition ist, die möglicherweise aktualisiert wird.
Version uprevs
Der Einfachheit halber veröffentlicht die Android-Plattform eine separate Version, wenn ein neuer Release-Zweig geschnitten wird. Wie oben beschrieben ist die Versionsnummer in PLATFORM_SEPOLICY_VERSION
enthalten und hat die Form MM.nn
, wobei MM
dem SDK-Wert entspricht und nn
ein privater Wert ist, der in /platform/system/sepolicy.
Zum Beispiel 19.0
für Kitkat, 21.0
für Lollipop, 22.0
für Lollipop-MR1, 23.0
für Marshmallow, 24.0
für Nougat, 25.0
für Nougat-MR1, 26.0
für Oreo, 27.0
für Oreo-MR1 und 28.0
für Android 9. Uprevs sind es nicht immer ganze Zahlen. Wenn beispielsweise eine MR-Änderung an einer Version eine inkompatible Änderung in system/sepolicy/public
erfordert, aber keine API-Anhebung, dann könnte diese Sepolicy-Version sein: vN.1
. Die in einem Entwicklungszweig vorhandene Version ist eine 10000.0
, die niemals in Versandgeräten verwendet werden darf.
Android veraltet beim Hochrüsten möglicherweise die älteste Version. Als Eingabe dafür, wann eine Version veraltet sein sollte, erfasst Android möglicherweise die Anzahl der Geräte mit Anbieterrichtlinien, auf denen diese Android-Version ausgeführt wird und die noch wichtige Plattformupdates erhalten. Wenn die Anzahl unter einem bestimmten Schwellenwert liegt, ist diese Version veraltet.
Auswirkungen mehrerer Attribute auf die Leistung
Wie unter https://github.com/SELinuxProject/cil/issues/9 beschrieben, führt eine große Anzahl von einem Typ zugewiesenen Attributen zu Leistungsproblemen im Falle eines Richtlinien-Cache-Fehlers.
Es wurde bestätigt, dass es sich hierbei um ein Problem in Android handelt. Daher wurden Änderungen an Android 8.0 vorgenommen , um Attribute zu entfernen, die der Richtlinie vom Richtlinien-Compiler hinzugefügt wurden, sowie um nicht verwendete Attribute zu entfernen. Durch diese Änderungen wurden Leistungsrückgänge behoben.
Öffentliche System_ext- und öffentliche Produktrichtlinie
Ab Android 11 dürfen die Partitionen „system_ext“ und „product“ ihre festgelegten öffentlichen Typen in die Vendor-Partition exportieren. Wie die öffentlichen Richtlinien der Plattform verwendet der Anbieter Typen und Regeln, die automatisch in die versionierten Attribute übersetzt werden, z. B. von type
in type_ N
, wobei N
die Version der Plattform ist, auf der die Anbieterpartition basiert.
Wenn die system_ext- und Produktpartitionen auf derselben Plattformversion N
basieren, generiert das Build-System Basiszuordnungsdateien für system_ext/etc/selinux/mapping/ N .cil
und product/etc/selinux/mapping/ N .cil
, die Identität enthalten Zuordnungen von type
zu type_ N
. Der Anbieter kann mit dem versionierten Attribut type_ N
auf type
zugreifen.
Falls nur die system_ext- und Produktpartitionen aktualisiert werden, sagen wir N
auf N+1
(oder höher), während der Anbieter bei N
bleibt, verliert der Anbieter möglicherweise den Zugriff auf die Typen der system_ext- und Produktpartitionen. Um einen Bruch zu verhindern, sollten die system_ext- und Produktpartitionen Zuordnungsdateien von konkreten Typen in type_ N
Attribute bereitstellen. Jeder Partner ist für die Pflege der Zuordnungsdateien verantwortlich, wenn er N
Anbieter mit N+1
(oder höher) system_ext- und Produktpartitionen unterstützen will.
Um dies zu erreichen, wird von den Partnern Folgendes erwartet:
- Kopieren Sie die generierten Basiszuordnungsdateien von
N
system_ext und Produktpartitionen in ihren Quellbaum. - Ändern Sie die Zuordnungsdateien nach Bedarf.
- Installieren Sie die Zuordnungsdateien auf
N+1
(oder höher) system_ext- und Produktpartitionen.
Angenommen, N
system_ext hat einen öffentlichen Typ namens foo_type
. Dann sieht system_ext/etc/selinux/mapping/ N .cil
in der N
system_ext-Partition so aus:
(typeattributeset foo_type_N (foo_type)) (expandtypeattribute foo_type_N true) (typeattribute foo_type_N)
Wenn bar_type
zu N+1
system_ext hinzugefügt wird und bar_type
foo_type
für N
Anbieter zugeordnet werden soll, kann N .cil
von aktualisiert werden
(typeattributeset foo_type_N (foo_type))
Zu
(typeattributeset foo_type_N (foo_type bar_type))
und dann auf der Partition von N+1
system_ext installiert. N
Anbieter können weiterhin auf foo_type
und bar_type
von N+1
system_ext zugreifen.
Beschriftung von SELinux-Kontexten
Um die Unterscheidung zwischen Plattform- und Anbieter-Separatpolitik zu unterstützen, erstellt das System SELinux-Kontextdateien unterschiedlich, um sie getrennt zu halten.
Dateikontexte
Android 8.0 führte die folgenden Änderungen für file_contexts
ein:
- Um zusätzlichen Kompilierungsaufwand auf dem Gerät während des Startvorgangs zu vermeiden, existieren
file_contexts
nicht mehr in binärer Form. Stattdessen handelt es sich um lesbare Textdateien mit regulären Ausdrücken wie{property, service}_contexts
(wie vor 7.0). - Die
file_contexts
sind auf zwei Dateien aufgeteilt:-
plat_file_contexts
-
file_context
der Android-Plattform, der keine gerätespezifischen Bezeichnungen hat, mit Ausnahme der Kennzeichnung von Teilen der/vendor
Partition, die genau gekennzeichnet werden müssen, um die ordnungsgemäße Funktion der Sepolicy-Dateien sicherzustellen. - Muss sich in
system
unter/system/etc/selinux/plat_file_contexts
auf dem Gerät befinden und voninit
beim Start zusammen mit demfile_context
des Anbieters geladen werden.
-
-
vendor_file_contexts
- Gerätespezifischer
file_context
der durch Kombinierenfile_contexts
erstellt wird, die in den Verzeichnissen gefunden werden, auf dieBOARD_SEPOLICY_DIRS
in denBoardconfig.mk
Dateien des Geräts verweist. - Muss unter
/vendor/etc/selinux/vendor_file_contexts
invendor
Partition installiert und voninit
beim Start zusammen mit der Plattformfile_context
geladen werden.
- Gerätespezifischer
-
Eigentumskontexte
In Android 8.0 ist property_contexts
auf zwei Dateien aufgeteilt:
-
plat_property_contexts
-
property_context
der Android-Plattform, der keine gerätespezifischen Bezeichnungen hat. - Muss sich in
system
unter/system/etc/selinux/plat_property_contexts
befinden und voninit
zu Beginn zusammen mit denproperty_contexts
des Anbieters geladen werden.
-
-
vendor_property_contexts
- Gerätespezifischer
property_context
, der durch Kombination vonproperty_contexts
erstellt wird, die in den Verzeichnissen gefunden werden, auf dieBOARD_SEPOLICY_DIRS
inBoardconfig.mk
Dateien des Geräts verweist. - Muss sich in
vendor
Partition unter/vendor/etc/selinux/vendor_property_contexts
befinden und voninit
beim Start zusammen mit dem Plattform-property_context
geladen werden
- Gerätespezifischer
Servicekontexte
In Android 8.0 sind die service_contexts
auf die folgenden Dateien aufgeteilt:
-
plat_service_contexts
- Android-plattformspezifischer
service_context
für denservicemanager
. Derservice_context
hat keine gerätespezifischen Bezeichnungen. - Muss sich in
system
unter/system/etc/selinux/plat_service_contexts
befinden und vonservicemanager
beim Start zusammen mit denservice_contexts
des Anbieters geladen werden.
- Android-plattformspezifischer
-
vendor_service_contexts
- Gerätespezifischer
service_context
der durch Kombinierenservice_contexts
erstellt wird, die in den Verzeichnissen gefunden werden, auf dieBOARD_SEPOLICY_DIRS
in denBoardconfig.mk
Dateien des Geräts verweist. - Muss sich in
vendor
Partition unter/vendor/etc/selinux/vendor_service_contexts
befinden und vonservicemanager
beim Start zusammen mit der Plattformservice_contexts
geladen werden. - Obwohl
servicemanager
beim Booten nach dieser Datei sucht, DÜRFEN dievendor_service_contexts
für ein vollständig kompatiblesTREBLE
Gerät NICHT vorhanden sein. Dies liegt daran, dass die gesamte Interaktion zwischenvendor
undsystem
überhwservicemanager
/hwbinder
erfolgen MUSS.
- Gerätespezifischer
-
plat_hwservice_contexts
- Android-Plattform
hwservice_context
fürhwservicemanager
, die keine gerätespezifischen Bezeichnungen hat. - Muss sich in
system
unter/system/etc/selinux/plat_hwservice_contexts
befinden und vonhwservicemanager
beim Start zusammen mitvendor_hwservice_contexts
geladen werden.
- Android-Plattform
-
vendor_hwservice_contexts
- Gerätespezifischer
hwservice_context
, der durch Kombinationhwservice_contexts
erstellt wird, die in den Verzeichnissen gefunden werden, auf dieBOARD_SEPOLICY_DIRS
in denBoardconfig.mk
Dateien des Geräts verweist. - Muss sich in
vendor
Partition unter/vendor/etc/selinux/vendor_hwservice_contexts
befinden und vonhwservicemanager
beim Start zusammen mitplat_service_contexts
geladen werden.
- Gerätespezifischer
-
vndservice_contexts
- Gerätespezifischer
service_context
für denvndservicemanager
, der durch Kombinierenvndservice_contexts
erstellt wird, die in den Verzeichnissen gefunden werden, auf dieBOARD_SEPOLICY_DIRS
in derBoardconfig.mk
des Geräts verweist. - Diese Datei muss sich in der
vendor
unter/vendor/etc/selinux/vndservice_contexts
befinden und beim Start vonvndservicemanager
geladen werden.
- Gerätespezifischer
Seapp-Kontexte
In Android 8.0 ist seapp_contexts
auf zwei Dateien aufgeteilt:
-
plat_seapp_contexts
- Android-Plattform
seapp_context
, die keine gerätespezifischen Änderungen aufweist. - Muss sich in
system
unter/system/etc/selinux/plat_seapp_contexts.
- Android-Plattform
-
vendor_seapp_contexts
- Gerätespezifische Erweiterung der Plattform
seapp_context
, die durch Kombination vonseapp_contexts
erstellt wird, die in den Verzeichnissen gefunden werden, auf dieBOARD_SEPOLICY_DIRS
in denBoardconfig.mk
Dateien des Geräts verweist. - Muss sich in der
vendor
unter/vendor/etc/selinux/vendor_seapp_contexts
befinden.
- Gerätespezifische Erweiterung der Plattform
MAC-Berechtigungen
In Android 8.0 ist die mac_permissions.xml
auf zwei Dateien aufgeteilt:
- Plattform
mac_permissions.xml
- Android-Plattform
mac_permissions.xml
, die keine gerätespezifischen Änderungen aufweist. - Muss sich in der
system
unter/system/etc/selinux/.
- Android-Plattform
- Nicht-Plattform
mac_permissions.xml
- Gerätespezifische Erweiterung der Plattform
mac_permissions.xml
, erstellt ausmac_permissions.xml
, gefunden in den Verzeichnissen, auf dieBOARD_SEPOLICY_DIRS
in denBoardconfig.mk
Dateien des Geräts verweist. - Muss sich in der
vendor
unter/vendor/etc/selinux/.
- Gerätespezifische Erweiterung der Plattform
In diesem Artikel wird beschrieben, wie Android mit den Richtlinienkompatibilitätsproblemen mit Plattform-OTAs umgeht, bei denen neue SELinux-Plattformeinstellungen von den SELinux-Einstellungen alter Anbieter abweichen können.
Das dreifache SELinux-Richtliniendesign berücksichtigt eine binäre Unterscheidung zwischen Plattform- und Anbieterrichtlinie . Das Schema wird komplizierter, wenn Herstellerpartitionen Abhängigkeiten generieren, z. B. platform
< vendor
< oem
.
In Android 8.0 und höher ist die globale SELinux-Richtlinie in private und öffentliche Komponenten unterteilt. Öffentliche Komponenten bestehen aus der Richtlinie und der zugehörigen Infrastruktur, die garantiert für eine Plattformversion verfügbar sind. Diese Richtlinie wird Anbieterrichtlinienautoren zur Verfügung gestellt, damit Anbieter eine Anbieterrichtliniendatei erstellen können, die in Kombination mit der von der Plattform bereitgestellten Richtlinie zu einer voll funktionsfähigen Richtlinie für ein Gerät führt.
- Zur Versionierung werden die exportierten Plattform-Public-Richtlinien als Attribute geschrieben.
- For ease of policy writing, exported types will be transformed into versioned attributes as part of the policy build process. Public types may also be used directly in labeling decisions provided by vendor contexts files.
Android maintains a mapping between exported concrete types in platform policy and the corresponding versioned attributes for each platform version . This ensures that when objects are labeled with a type, it does not break behavior guaranteed by the platform-public policy in a previous version. This mapping is maintained by keeping a mapping file up-to-date for each platform version , which keeps attribute membership information for each type exported in public policy.
Object ownership and labeling
When customizing policy in Android 8.0 and higher, ownership must be clearly defined for each object to keep platform and vendor policy separate. For example, if the vendor labels /dev/foo
and the platform then labels /dev/foo
in a subsequent OTA, there will be undefined behavior. For SELinux, this manifests as a labeling collision. The device node can have only a single label which resolves to whichever label is applied last. As a result:
- Processes that need access to the unsuccessfully applied label will lose access to the resource.
- Processes that gain access to the file may break because the wrong device node was created.
System properties also have potential for naming collisions that could result in undefined behavior on the system (as well as for SELinux labeling). Collisions between platform and vendor labels can occur for any object that has an SELinux label, including properties, services, processes, files, and sockets. To avoid these issues, clearly define ownership of these objects.
In addition to label collisions, SELinux type/attribute names may also collide. A type/attribute name collision will always result in a policy compiler error.
Type/attribute namespacing
SELinux does not allow multiple declarations of the same type/attribute. Policy with duplicate declarations will fail to compilation. To avoid type and attribute name collisions, all vendor declarations should be namespaced starting with np_
.
type foo, domain; → type np_foo, domain;
System property and process labeling ownership
Avoiding labeling collisions is best solved using property namespaces. To easily identify platform properties and avoid name conflicts when renaming or adding exported-platform properties, ensure all vendor properties have their own prefixes:
Property type | Acceptable prefixes |
---|---|
control properties | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor. |
read-writable | vendor. |
read-only | ro.vendor. ro.boot. ro.hardware. |
persistent | persist.vendor. |
Vendors can continue to use ro.boot.*
(which comes from the kernel cmdline) and ro.hardware.*
(an obvious hardware-related property).
All the vendor services in init rc files should have vendor.
for services in init rc files of non-system partitions. Similar rules are applied to the SELinux labels for the vendor properties ( vendor_
for the vendor properties).
File ownership
Preventing collisions for files is challenging because platform and vendor policy both commonly provide labels for all filesystems. Unlike type naming, namespacing of files is not practical since many of them are created by the kernel. To prevent these collisions, follow the naming guidance for filesystems in this section. For Android 8.0, these are recommendations without technical enforcement. In the future, these recommendations will be enforced by the Vendor Test Suite (VTS).
System (/system)
Only the system image must provide labels for /system
components through file_contexts
, service_contexts
, etc. If labels for /system
components are added in /vendor
policy, a framework-only OTA update may not be possible.
Vendor (/vendor)
The AOSP SELinux policy already labels parts of vendor
partition the platform interacts with, which enables writing SELinux rules for platform processes to be able to talk and/or access parts of vendor
partition. Examples:
/vendor path | Platform-provided label | Platform processes depending on the label |
---|---|---|
/vendor(/. * )? | vendor_file | All HAL clients in framework, ueventd , etc. |
/vendor/framework(/. * )? | vendor_framework_file | dex2oat , appdomain , etc. |
/vendor/app(/. * )? | vendor_app_file | dex2oat , installd , idmap , etc. |
/vendor/overlay(/. * ) | vendor_overlay_file | system_server , zygote , idmap , etc. |
As a result, specific rules must be followed (enforced through neverallows
) when labelling additional files in vendor
partition:
-
vendor_file
must be the default label for all files invendor
partition. The platform policy requires this to access passthrough HAL implementations. - All new
exec_types
added invendor
partition through vendor SEPolicy must havevendor_file_type
attribute. This is enforced through neverallows. - To avoid conflicts with future platform/framework updates, avoid labelling files other than
exec_types
invendor
partition. - All library dependencies for AOSP-identified same process HALs must be labelled as
same_process_hal_file.
Procfs (/proc)
Files in /proc
may be labeled using only the genfscon
label. In Android 7.0, both the platform and vendor policy used genfscon
to label files in procfs
.
Recommendation: Only platform policy labels /proc
. If vendor
processes need access to files in /proc
that are currently labeled with the default label ( proc
), vendor policy should not explicitly label them and should instead use the generic proc
type to add rules for vendor domains. This allows the platform updates to accommodate future kernel interfaces exposed through procfs
and label them explicitly as needed.
Debugfs (/sys/kernel/debug)
Debugfs
can be labeled in both file_contexts
and genfscon
. In Android 7.0 to Android 10, both platform and vendor label debugfs
.
In Android 11, debugfs
can't be accessed or mounted on production devices. Device manufacturers should remove debugfs
.
Tracefs (/sys/kernel/debug/tracing)
Tracefs
can be labeled in both file_contexts
and genfscon
. In Android 7.0, only the platform labels tracefs
.
Recommendation: Only platform may label tracefs
.
Sysfs (/sys)
Files in /sys
may be labeled using both file_contexts
and genfscon
. In Android 7.0, both platform and vendor use file_contexts
and genfscon
to label files in sysfs
.
Recommendation: The platform may label sysfs
nodes that are not device-specific. Otherwise, only vendor may label files.
tmpfs (/dev)
Files in /dev
may be labeled in file_contexts
. In Android 7.0, both platform and vendor label files here.
Recommendation: Vendor may label only files in /dev/vendor
(eg, /dev/vendor/foo
, /dev/vendor/socket/bar
).
Rootfs (/)
Files in /
may be labeled in file_contexts
. In Android 7.0, both platform and vendor label files here.
Recommendation: Only system may label files in /
.
Data (/data)
Data is labeled through a combination of file_contexts
and seapp_contexts
.
Recommendation: Disallow vendor labeling outside /data/vendor
. Only platform may label other parts of /data
.
Compatibility attributes
SELinux policy is an interaction between source and target types for specific object classes and permissions. Every object (processes, files, etc.) affected by SELinux policy may have only one type, but that type may have multiple attributes.
Policy is written mostly in terms of existing types:
allow source_type target_type:target_class permission(s);
This works because the policy was written with knowledge of all types. However, if the vendor policy and platform policy use specific types, and the label of a specific object changes in only one of those policies, the other may contain policy that gained or lost access previously relied upon. Zum Beispiel:
File_contexts: /sys/A u:object_r:sysfs:s0 Platform: allow p_domain sysfs:class perm; Vendor: allow v_domain sysfs:class perm;
Could be changed to:
File_contexts: /sys/A u:object_r:sysfs_A:s0
Although the vendor policy would remain the same, the v_domain
would lose access due to the lack of policy for the new sysfs_A
type.
By defining a policy in terms of attributes, we can give the underlying object a type that has an attribute corresponding to policy for both the platform and vendor code. This can be done for all types to effectively create an attribute-policy wherein concrete types are never used. In practice, this is required only for the portions of policy that overlap between platform and vendor, which are defined and provided as platform public policy that gets built as part of the vendor policy.
Defining public policy as versioned attributes satisfies two policy compatibility goals:
- Ensure vendor code continues to work after platform update . Achieved by adding attributes to concrete types for objects corresponding to those on which vendor code relied, preserving access.
- Ability to deprecate policy . Achieved by clearly delineating policy sets into attributes that can be removed as soon as the version to which they correspond no longer is supported. Development can continue in the platform, knowing the old policy is still present in the vendor policy and will be automatically removed when/if it upgrades.
Policy writability
To meet the goal of not requiring knowledge of specific version changes for policy development, Android 8.0 includes a mapping between platform-public policy types and their attributes. Type foo
is mapped to attribute foo_v N
, where N
is the version targeted. vN
corresponds to the PLATFORM_SEPOLICY_VERSION
build variable and is of the form MM.NN
, where MM
corresponds to the platform SDK number and NN
is a platform sepolicy specific version.
Attributes in public policy are not versioned, but rather exist as an API on which platform and vendor policy can build to keep the interface between the two partitions stable. Both platform and vendor policy writers can continue to write policy as it is written today.
Platform-public policy exported as allow source_foo target_bar: class perm ;
is included as part of the vendor policy. During compilation (which includes the corresponding version) it is transformed into the policy that will go to the vendor portion of the device (shown in the transformed Common Intermediate Language (CIL)):
(allow source_foo_vN target_bar_vN (class (perm)))
As vendor policy is never ahead of the platform, it should not be concerned with prior versions. However, platform policy will need to know how far back vendor policy is, include attributes to its types, and set policy corresponding to versioned attributes.
Policy diffs
Automatically creating attributes by adding _v N
to the end of each type does nothing without mapping of attributes to types across version diffs. Android maintains a mapping between versions for attributes and a mapping of types to those attributes. This is done in the aforementioned mapping files with statements, such as (CIL):
(typeattributeset foo_vN (foo))
Platform upgrades
The following section details scenarios for platform upgrades.
Same types
This scenario occurs when an object does not change labels in policy versions. This is the same for source and target types and can be seen with /dev/binder
, which is labeled binder_device
across all releases. It is represented in transformed policy as:
binder_device_v1 … binder_device_vN
When upgrading from v1
→ v2
, the platform policy must contain:
type binder_device; -> (type binder_device) (in CIL)
In the v1 mapping file (CIL):
(typeattributeset binder_device_v1 (binder_device))
In the v2 mapping file (CIL):
(typeattributeset binder_device_v2 (binder_device))
In the v1 vendor policy (CIL):
(typeattribute binder_device_v1) (allow binder_device_v1 …)
In the v2 vendor policy (CIL):
(typeattribute binder_device_v2) (allow binder_device_v2 …)
New types
This scenario occurs when the platform has added a new type, which can happen when adding new features or during policy hardening.
- New feature . When the type is labeling an object that was previously non-existent (such as a new service process), the vendor code did not previously interact with it directly so no corresponding policy exists. The new attribute corresponding to the type does not have an attribute in the previous version, and so would not need an entry in the mapping file targeting that version.
- Policy hardening . When the type represents policy hardening, the new type attribute must link back to a chain of attributes corresponding to the previous one (similar to the previous example changing
/sys/A
fromsysfs
tosysfs_A
). Vendor code relies on a rule enabling access tosysfs
, and needs to include that rule as an attribute of the new type.
When upgrading from v1
→ v2
, the platform policy must contain:
type sysfs_A; -> (type sysfs_A) (in CIL) type sysfs; (type sysfs) (in CIL)
In the v1 mapping file (CIL):
(typeattributeset sysfs_v1 (sysfs sysfs_A))
In the v2 mapping file (CIL):
(typeattributeset sysfs_v2 (sysfs)) (typeattributeset sysfs_A_v2 (sysfs_A))
In the v1 vendor policy (CIL):
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
In the v2 vendor policy (CIL):
(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)
Removed types
This (rare) scenario occurs when a type is removed, which can happen when the underlying object:
- Remains but gets a different label.
- Is removed by the platform.
During policy loosening, a type is removed and the object labeled with that type is given a different, already-existing label. This represents a merging of attribute mappings: The vendor code must still be able to access the underlying object by the attribute it used to possess, but the rest of the system must now be able to access it with its new attribute.
If the attribute to which it has been switched is new, then relabeling is the same as in the new type case, except that when an existing label is used, the addition of the old attribute new type would cause other objects also labeled with this type to be newly accessible. This is essentially what is done by the platform and is deemed to be an acceptable tradeoff to maintain compatibility.
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
Example Version 1: Collapsing types (removing sysfs_A)
When upgrading from v1
→ v2
, the platform policy must contain:
type sysfs; (type sysfs) (in CIL)
In the v1 mapping file (CIL):
(typeattributeset sysfs_v1 (sysfs)) (type sysfs_A) # in case vendors used the sysfs_A label on objects (typeattributeset sysfs_A_v1 (sysfs sysfs_A))
In the v2 mapping file (CIL):
(typeattributeset sysfs_v2 (sysfs))
In the v1 vendor policy (CIL):
(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)
In the v2 vendor policy (CIL):
(typeattribute sysfs_v2) (allow … sysfs_v2 …)
Example Version 2: Removing completely (foo type)
When upgrading from v1
→ v2
, the platform policy must contain:
# nothing - we got rid of the type
In the v1 mapping file (CIL):
(type foo) #needed in case vendors used the foo label on objects (typeattributeset foo_v1 (foo))
In the v2 mapping file (CIL):
# nothing - get rid of it
In the v1 vendor policy (CIL):
(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)
In the v2 vendor policy (CIL):
(typeattribute sysfs_v2) (allow sysfs_v2 …)
New class/permissions
This scenario occurs when a platform upgrade introduces new policy components that do not exist in previous versions. For example, when Android added the servicemanager
object manager that created the add, find, and list permissions, vendor daemons wanting to register with the servicemanager
needed permissions that were not available. In Android 8.0, only the platform policy may add new classes and permissions.
To allow all domains that could have been created or extended by vendor policy to use the new class without obstruction, the platform policy needs to include a rule similar to:
allow {domain -coredomain} *:new_class perm;
This may even require policy allowing access for all interface (public policy) types, to be sure vendor image gains access. If this results in unacceptable security policy (as it may have with the servicemanager changes), a vendor upgrade could potentially be forced.
Removed class/permissions
This scenario occurs when an object manager is removed (such as the ZygoteConnection
object manager) and should not cause issues. The object manager class and permissions could remain defined in policy until the vendor version no longer uses it. This is done by adding the definitions to the corresponding mapping file.
Vendor customization for new/relabeled types
New vendor types are at the core of vendor policy development as they are needed to describe new processes, binaries, devices, subsystems, and stored data. As such, it is imperative to allow the creation of vendor-defined types.
As vendor policy is always the oldest on the device, there is no need to automatically convert all vendor types to attributes in policy. The platform does not rely on anything labeled in vendor policy because the platform has no knowledge of it; however, the platform will provide the attributes and public types it uses to interact with objects labeled with these types (such as domain
, sysfs_type
, etc.). For the platform to continue to interact correctly with these objects, the attributes and types must be appropriately applied and specific rules may need to be added to the customizable domains (such as init
).
Attribute changes for Android 9
Devices upgrading to Android 9 can use the following attributes, but devices launching with Android 9 must not.
Violator attributes
Android 9 includes these domain-related attributes:
-
data_between_core_and_vendor_violators
. Attribute for all domains that violate the requirement of not sharing files by path betweenvendor
andcoredomains
. Platform and vendor processes shouldn't use on-disk files to communicate (unstable ABI). Recommendation:- Vendor code should use
/data/vendor
. - System should not use
/data/vendor
.
- Vendor code should use
-
system_executes_vendor_violators
. Attribute for all system domains (exceptinit
andshell domains
) that violate the requirement of not executing vendor binaries. Execution of vendor binaries has unstable API. Platform shouldn't execute vendor binaries directly. Recommendation:- Such platform dependencies on vendor binaries must be behind HIDL HALs.
OR
-
coredomains
that need access to vendor binaries should be moved to the vendor partition and thus, stop beingcoredomain
.
- Such platform dependencies on vendor binaries must be behind HIDL HALs.
Untrusted attributes
Untrusted apps that host arbitrary code shouldn't have access to HwBinder services, except those considered sufficiently safe for access from such apps (see safe services below). The two main reasons for this are:
- HwBinder servers do not perform client authentication because HIDL currently does not expose caller UID information. Even if HIDL did expose such data, many HwBinder services either operate at a level below that of apps (such as, HALs) or must not rely on app identity for authorization. Thus, to be safe, the default assumption is that every HwBinder service treats all its clients as equally authorized to perform operations offered by the service.
- HAL servers (a subset of HwBinder services) contain code with higher incidence rate of security issues than
system/core
components and have access to the lower layers of the stack (all the way down to hardware) thus increasing opportunities for bypassing the Android security model.
Safe services
Safe services include:
-
same_process_hwservice
. These services (by definition) run in the process of the client and thus have the same access as the client domain in which the process runs. -
coredomain_hwservice
. These services do not pose risks associated with reason #2. -
hal_configstore_ISurfaceFlingerConfigs
. This service is specifically designed for use by any domain. -
hal_graphics_allocator_hwservice
. These operations are also offered bysurfaceflinger
Binder service, which apps are permitted to access. -
hal_omx_hwservice
. This is a HwBinder version of themediacodec
Binder service, which apps are permitted to access. -
hal_codec2_hwservice
. This is a newer version ofhal_omx_hwservice
.
Useable attributes
All hwservices
not considered safe have the attribute untrusted_app_visible_hwservice
. The corresponding HAL servers have the attribute untrusted_app_visible_halserver
. Devices launching with Android 9 MUST NOT use either untrusted
attribute.
Recommendation:
- Untrusted apps should instead talk to a system service that talks to the vendor HIDL HAL. For example, apps can talk to
binderservicedomain
, thenmediaserver
(which is abinderservicedomain
) in turn talks to thehal_graphics_allocator
.OR
- Apps that need direct access to
vendor
HALs should have their own vendor-defined sepolicy domain.
File attribute tests
Android 9 includes build time tests that ensure all files in specific locations have the appropriate attributes (such as, all files in sysfs
have the required sysfs_type
attribute).
Platform-public policy
The platform-public policy is the core of conforming to the Android 8.0 architecture model without simply maintaining the union of platform policies from v1 and v2. Vendors are exposed to a subset of platform policy that contains useable types and attributes and rules on those types and attributes which then becomes part of vendor policy (ie vendor_sepolicy.cil
).
Types and rules are automatically translated in the vendor-generated policy into attribute_v N
such that all platform-provided types are versioned attributes (however attributes are not versioned). The platform is responsible for mapping the concrete types it provides into the appropriate attributes to ensure that vendor policy continues to function and that the rules provided for a particular version are included. The combination of platform-public policy and vendor policy satisfies the Android 8.0 architecture model goal of allowing independent platform and vendor builds.
Mapping to attribute chains
When using attributes to map to policy versions, a type maps to an attribute or multiple attributes, ensuring objects labeled with the type are accessible via attributes corresponding to their previous types.
Maintaining a goal to hide version information from the policy writer means automatically generating the versioned attributes and assigning them to the appropriate types. In the common case of static types, this is straightforward: type_foo
maps to type_foo_v1
.
For an object label change such as sysfs
→ sysfs_A
or mediaserver
→ audioserver
, creating this mapping is non-trivial (and is described in the examples above). Platform policy maintainers must determine how to create the mapping at transition points for objects, which requires understanding the relationship between objects and their assigned labels and determining when this occurs. For backwards compatibility, this complexity needs to be managed on the platform side, which is the only partition that may uprev.
Version uprevs
For simplicity, the Android platform releases an sepolicy version when a new release branch is cut. As described above, the version number is contained in PLATFORM_SEPOLICY_VERSION
and is of the form MM.nn
, where MM
corresponds to the SDK value and nn
is a private value maintained in /platform/system/sepolicy.
For example, 19.0
for Kitkat, 21.0
for Lollipop, 22.0
for Lollipop-MR1 23.0
for Marshmallow, 24.0
for Nougat, 25.0
for Nougat-MR1, 26.0
for Oreo, 27.0
for Oreo-MR1, and 28.0
for Android 9. Uprevs aren't always whole numbers. For example, if an MR bump to a versions necessitates an incompatible change in system/sepolicy/public
but not an API bump, then that sepolicy version could be: vN.1
. The version present in a development branch is a never-to-be-used-in-shipping-devices 10000.0
.
Android may deprecate oldest version when upreving. For input on when to deprecate a version, Android may collect the number of devices with vendor policies running that Android version and still receiving major platform updates. If the number is less than a certain threshold, that version is deprecated.
Performance impact of multiple attributes
As described in https://github.com/SELinuxProject/cil/issues/9 , a large number of attributes assigned to a type result in performance issues in the event of a policy cache miss.
This was confirmed to be an issue in Android, so changes were made to Android 8.0 to remove attributes added to the policy by the policy compiler, as well as to remove unused attributes. These changes resolved performance regressions.
System_ext public and product public policy
Starting from Android 11, the system_ext and product partitions are allowed to export their designated public types to the vendor partition. Like platform public policy, the vendor uses types and rules automatically translated into the versioned attributes, eg from type
into type_ N
, where N
is the version of the platform which the vendor partition is built against.
When the system_ext and product partitions are based on the same platform version N
, the build system generates base mapping files to system_ext/etc/selinux/mapping/ N .cil
and product/etc/selinux/mapping/ N .cil
, which contain identity mappings from type
to type_ N
. The vendor can access type
with the versioned attribute type_ N
.
In case that only the system_ext and product partitions are updated, say N
to N+1
(or later), while the vendor stays at N
, the vendor may lose access to the types of the system_ext and product partitions. To prevent breakage, the system_ext and product partitions should provide mapping files from concrete types into type_ N
attributes. Each partner is responsible for maintaining the mapping files, if they are going to support N
vendor with N+1
(or later) system_ext and product partitions.
To do that, partners are expected to:
- Copy the generated base mapping files from
N
system_ext and product partitions to their source tree. - Amend the mapping files as needed.
- Install the mapping files to
N+1
(or later) system_ext and product partitions.
For example, suppose that N
system_ext has one public type named foo_type
. Then system_ext/etc/selinux/mapping/ N .cil
in the N
system_ext partition will look like:
(typeattributeset foo_type_N (foo_type)) (expandtypeattribute foo_type_N true) (typeattribute foo_type_N)
If bar_type
is added to N+1
system_ext, and if bar_type
should be mapped to foo_type
for N
vendor, N .cil
can be updated from
(typeattributeset foo_type_N (foo_type))
to
(typeattributeset foo_type_N (foo_type bar_type))
and then installed to N+1
system_ext's partition. N
vendor can continue accessing to N+1
system_ext's foo_type
and bar_type
.
SELinux contexts labeling
To support the distinction between platform and vendor sepolicy, the system builds SELinux context files differently to keep them separate.
File contexts
Android 8.0 introduced the following changes for file_contexts
:
- To avoid additional compilation overhead on device during boot,
file_contexts
cease to exist in the binary form. Instead, they are readable, regular expression text file such as{property, service}_contexts
(as they were pre-7.0). - The
file_contexts
are split between two files:-
plat_file_contexts
- Android platform
file_context
that has no device-specific labels, except for labeling parts of/vendor
partition that must be labeled precisely to ensure proper functioning of the sepolicy files. - Must reside in
system
partition at/system/etc/selinux/plat_file_contexts
on device and be loaded byinit
at the start along with the vendorfile_context
.
- Android platform
-
vendor_file_contexts
- Device-specific
file_context
built by combiningfile_contexts
found in the directories pointed to byBOARD_SEPOLICY_DIRS
in the device'sBoardconfig.mk
files. - Must be installed at
/vendor/etc/selinux/vendor_file_contexts
invendor
partition and be loaded byinit
at the start along with the platformfile_context
.
- Device-specific
-
Property contexts
In Android 8.0, the property_contexts
is split between two files:
-
plat_property_contexts
- Android platform
property_context
that has no device-specific labels. - Must reside in
system
partition at/system/etc/selinux/plat_property_contexts
and be loaded byinit
at the start along with the vendorproperty_contexts
.
- Android platform
-
vendor_property_contexts
- Device-specific
property_context
built by combiningproperty_contexts
found in the directories pointed to byBOARD_SEPOLICY_DIRS
in device'sBoardconfig.mk
files. - Must reside in
vendor
partition at/vendor/etc/selinux/vendor_property_contexts
and be loaded byinit
at the start along with the platformproperty_context
- Device-specific
Service contexts
In Android 8.0, the service_contexts
is split between the following files:
-
plat_service_contexts
- Android platform-specific
service_context
for theservicemanager
. Theservice_context
has no device-specific labels. - Must reside in
system
partition at/system/etc/selinux/plat_service_contexts
and be loaded byservicemanager
at the start along with the vendorservice_contexts
.
- Android platform-specific
-
vendor_service_contexts
- Device-specific
service_context
built by combiningservice_contexts
found in the directories pointed to byBOARD_SEPOLICY_DIRS
in the device'sBoardconfig.mk
files. - Must reside in
vendor
partition at/vendor/etc/selinux/vendor_service_contexts
and be loaded byservicemanager
at the start along with the platformservice_contexts
. - Although
servicemanager
looks for this file at boot time, for a fully compliantTREBLE
device, thevendor_service_contexts
MUST NOT exist. This is because all interaction betweenvendor
andsystem
processes MUST go throughhwservicemanager
/hwbinder
.
- Device-specific
-
plat_hwservice_contexts
- Android platform
hwservice_context
forhwservicemanager
that has no device-specific labels. - Must reside in
system
partition at/system/etc/selinux/plat_hwservice_contexts
and be loaded byhwservicemanager
at the start along with thevendor_hwservice_contexts
.
- Android platform
-
vendor_hwservice_contexts
- Device-specific
hwservice_context
built by combininghwservice_contexts
found in the directories pointed to byBOARD_SEPOLICY_DIRS
in the device'sBoardconfig.mk
files. - Must reside in
vendor
partition at/vendor/etc/selinux/vendor_hwservice_contexts
and be loaded byhwservicemanager
at the start along with theplat_service_contexts
.
- Device-specific
-
vndservice_contexts
- Device-specific
service_context
for thevndservicemanager
built by combiningvndservice_contexts
found in the directories pointed to byBOARD_SEPOLICY_DIRS
in the device'sBoardconfig.mk
. - This file must reside in
vendor
partition at/vendor/etc/selinux/vndservice_contexts
and be loaded byvndservicemanager
at the start.
- Device-specific
Seapp contexts
In Android 8.0, the seapp_contexts
is split between two files:
-
plat_seapp_contexts
- Android platform
seapp_context
that has no device-specific changes. - Must reside in
system
partition at/system/etc/selinux/plat_seapp_contexts.
- Android platform
-
vendor_seapp_contexts
- Device-specific extension to platform
seapp_context
built by combiningseapp_contexts
found in the directories pointed to byBOARD_SEPOLICY_DIRS
in the device'sBoardconfig.mk
files. - Must reside in
vendor
partition at/vendor/etc/selinux/vendor_seapp_contexts
.
- Device-specific extension to platform
MAC permissions
In Android 8.0, the mac_permissions.xml
is split between two files:
- Platform
mac_permissions.xml
- Android platform
mac_permissions.xml
that has no device-specific changes. - Must reside in
system
partition at/system/etc/selinux/.
- Android platform
- Non-Platform
mac_permissions.xml
- Device-specific extension to platform
mac_permissions.xml
built frommac_permissions.xml
found in the directories pointed to byBOARD_SEPOLICY_DIRS
in the device'sBoardconfig.mk
files. - Must reside in
vendor
partition at/vendor/etc/selinux/.
- Device-specific extension to platform