Richtlinienkompatibilität

In diesem Artikel wird beschrieben, wie Android mit Richtlinienkompatibilitätsproblemen bei Plattform-OTAs umgeht, bei denen sich die neuen SELinux-Einstellungen der Plattform von den alten SELinux-Einstellungen des Anbieters unterscheiden können.

Bei der Treble-basierten SELinux-Richtlinienentwicklung wird zwischen Plattform- und Anbieterrichtlinien unterschieden. Das System wird komplizierter, wenn Anbieterpartitionen Abhängigkeiten erzeugen, 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 für eine Plattformversion garantiert verfügbar sind. Diese Richtlinie wird Anbietern zur Verfügung gestellt, damit sie eine Anbieterrichtliniendatei erstellen können, die in Kombination mit der von der Plattform bereitgestellten Richtlinie eine voll funktionsfähige Richtlinie für ein Gerät ergibt.

  • Für die Versionierung werden die exportierten öffentlichen Plattformrichtlinien als Attribute geschrieben.
  • Für die leichtere Erstellung von Richtlinien werden exportierte Typen im Rahmen des Richtlinienerstellungsprozesses in versionierte Attribute umgewandelt. Öffentliche Typen können auch direkt in Entscheidungen zur Kennzeichnung verwendet werden, die in Dateien mit Anbieterkontexten enthalten sind.

Android pflegt eine Zuordnung zwischen den exportierten konkreten Typen in der Plattformrichtlinie und den entsprechenden versionierten Attributen für jede Plattformversion. So wird sichergestellt, dass das Verhalten von Objekten, die mit einem Typ gekennzeichnet sind, nicht gegen die in einer früheren Version der Plattform-Richtlinien für die Öffentlichkeit garantierten Verhaltensweisen verstößt. Diese Zuordnung wird durch eine Zuordnungsdatei für jede Plattformversion aufrechterhalten, in der Informationen zur Attributmitgliedschaft für jeden Typ gespeichert werden, der in den öffentlichen Richtlinien exportiert wird.

Eigentumsrechte an Objekten und Labeling

Wenn Sie die Richtlinie unter Android 8.0 und höher anpassen, muss die Inhaberschaft für jedes Objekt klar definiert sein, damit Plattform- und Anbieterrichtlinien getrennt bleiben. Wenn der Anbieter beispielsweise /dev/foo und die Plattform dann /dev/foo in einer nachfolgenden OTA-Transaktion kennzeichnet, ist das Verhalten nicht definiert. Bei SELinux führt dies zu einer Labelkonflikt. Der Geräteknoten kann nur ein einzelnes Label haben, das auf das zuletzt angewendete Label verweist. Daraus ergeben sich folgende Konsequenzen:

  • Prozesse, die Zugriff auf das erfolglos angewendete Label benötigen, verlieren den Zugriff auf die Ressource.
  • Prozesse, die Zugriff auf die Datei erhalten, können fehlerhaft laufen, weil der falsche Geräteknoten erstellt wurde.

Systemeigenschaften können auch zu Namenskollisionen führen, die zu undefiniertem Verhalten des Systems (sowie zu SELinux-Labeln) führen können. Kollisionen zwischen Plattform- und Anbieterlabels können bei allen Objekten mit einem SELinux-Label auftreten, einschließlich Properties, Diensten, Prozessen, Dateien und Sockets. Um diese Probleme zu vermeiden, sollten Sie die Eigentumsrechte an diesen Objekten klar definieren.

Neben Labelkollisionen können auch SELinux-Typ-/Attributnamen kollidieren. Ein Konflikt zwischen dem Namen eines Typs und dem Namen eines Attributs führt immer zu einem Richtlinien-Compilerfehler.

Namespace für Typ/Attribut

SELinux erlaubt keine Mehrfachdeklarationen desselben Typs/Attributs. Richtlinien mit doppelten Deklarationen können nicht kompiliert werden. Um Namenskollisionen bei Typen und Attributen zu vermeiden, sollten alle Anbieterdeklarationen mit vendor_ beginnen.

type foo, domain;  type vendor_foo, domain;

Eigentumsrechte an Systemeigenschaften und Prozesslabeln

Kollisionen bei Labels lassen sich am besten mithilfe von Property-Namespaces vermeiden. Damit Sie Plattformeigenschaften leicht identifizieren und Namenskonflikte beim Umbenennen oder Hinzufügen von exportierten Plattformeigenschaften vermeiden können, sollten alle Anbietereigenschaften eigene Präfixe haben:

Property-Typ Zulässige Präfixe
Steuerelementeigenschaften ctl.vendor.
ctl.start$vendor.
ctl.stop$vendor.
init.svc.vendor.
Lese-/Schreibzugriff vendor.
schreibgeschützt ro.vendor.
ro.boot.
ro.hardware.
persistent persist.vendor.

Anbieter können weiterhin ro.boot.* (aus der Kernel-cmdline) und ro.hardware.* (eine offensichtlich hardwarebezogene Eigenschaft) verwenden.

Alle Anbieterdienste in init-rc-Dateien sollten vendor. für Dienste in init-rc-Dateien von nicht systemeigenen Partitionen haben. Ähnliche Regeln gelten für die SELinux-Labels für die Anbietereigenschaften (vendor_ für die Anbietereigenschaften).

Dateieigentümer

Kollisionen bei Dateien zu verhindern, ist schwierig, da sowohl Plattform- als auch Anbieterrichtlinien in der Regel Labels für alle Dateisysteme bereitstellen. Im Gegensatz zur Benennung von Typen ist die Benennung von Dateien im Namespace nicht praktikabel, da viele von ihnen vom Kernel erstellt werden. Folgen Sie der Anleitung in diesem Abschnitt, um diese Kollisionen zu vermeiden. Bei Android 8.0 handelt es sich dabei um Empfehlungen ohne technische Erzwingung. Künftig werden diese Empfehlungen durch die Vendor Test Suite (VTS) erzwungen.

System (/system)

Nur das Systemimage muss Labels für /system-Komponenten (file_contexts, service_contexts usw.) bereitstellen. Wenn Labels für /system-Komponenten in der /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-Partition, mit denen die Plattform interagiert. Dadurch können SELinux-Regeln für Plattformprozesse geschrieben werden, damit sie mit Teilen der vendor-Partition kommunizieren und/oder darauf zugreifen können. Beispiele:

Pfad zu /vendor Von der Plattform bereitgestelltes Label Plattformprozesse, die vom Label abhängen
/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 Beschriften zusätzlicher Dateien in der vendor-Partition bestimmte Regeln befolgt werden, die über neverallows erzwungen werden:

  • vendor_file muss das Standardlabel für alle Dateien in der vendor-Partition sein. Laut der Plattformrichtlinie ist dies für den Zugriff auf Passthrough-HAL-Implementierungen erforderlich.
  • Alle neuen exec_types, die über die SEPolicy des Anbieters der vendor-Partition hinzugefügt werden, müssen das Attribut vendor_file_type haben. Dies wird durch „neverallows“ erzwungen.
  • Um Konflikte mit zukünftigen Plattform-/Framework-Updates zu vermeiden, sollten Sie in der Partition vendor keine anderen Dateien als exec_types kennzeichnen.
  • Alle Bibliotheksabhängigkeiten für von AOSP identifizierte HALs für denselben Prozess müssen als same_process_hal_file. gekennzeichnet sein.

Procfs (/proc)

Dateien in /proc dürfen nur mit dem Label genfscon gekennzeichnet werden. In Android 7.0 wurde sowohl in der Plattform als auch in der Anbieterrichtlinie genfscon zum Beschriften von Dateien in procfs verwendet.

Empfehlung:Nur Labels für Plattformrichtlinien /proc Wenn vendor-Prozesse Zugriff auf Dateien in /proc benötigen, die derzeit mit dem Standardlabel (proc) gekennzeichnet sind, sollten sie in der Anbieterrichtlinie nicht explizit gekennzeichnet werden. Stattdessen sollte der generische Typ proc verwendet werden, um Regeln für Anbieterdomains hinzuzufügen. So können die Plattformupdates zukünftige Kernel-Schnittstellen berücksichtigen, die über procfs freigegeben werden, und sie bei Bedarf explizit kennzeichnen.

Debugfs (/sys/kernel/debug)

Debugfs kann sowohl in file_contexts als auch in genfscon beschriftet werden. Unter Android 7.0 bis Android 10 werden sowohl das Plattform- als auch das Anbieterlabel verwendet. debugfs

Unter Android 11 kann auf debugfs nicht zugegriffen oder es kann nicht auf Produktionsgeräten bereitgestellt werden. Gerätehersteller sollten debugfs entfernen.

Tracefs (/sys/kernel/debug/tracing)

Tracefs kann sowohl in file_contexts als auch in genfscon beschriftet werden. Unter Android 7.0 werden nur die Plattformlabels angezeigt.tracefs

Empfehlung:Nur die Plattform darf tracefs kennzeichnen.

Sysfs (/sys)

Dateien in /sys können sowohl mit file_contexts als auch mit genfscon gekennzeichnet werden. Unter Android 7.0 verwenden sowohl die Plattform als auch der Anbieter genfscon, um Dateien in sysfs zu labeln.

Empfehlung:Die Plattform kann sysfs-Knoten kennzeichnen, die nicht gerätespezifisch sind. Andernfalls kann nur der Anbieter Dateien labeln.

tmpfs (/dev)

Dateien in /dev können in file_contexts gekennzeichnet werden. Unter Android 7.0 sind hier sowohl Plattform- als auch Anbieterlabeldateien verfügbar.

Empfehlung:Der Anbieter darf nur Dateien in /dev/vendor labeln (z. B. /dev/vendor/foo, /dev/vendor/socket/bar).

Rootfs (/)

Dateien in / können in file_contexts gekennzeichnet werden. Unter Android 7.0 finden Sie hier sowohl Plattform- als auch Anbieterlabeldateien.

Empfehlung:Dateien in / dürfen nur vom System getaggt werden.

Daten (/data)

Daten werden durch eine Kombination aus file_contexts und seapp_contexts gekennzeichnet.

Empfehlung:Legen Sie fest, dass Anbieterlabels außerhalb von /data/vendor nicht zulässig sind. Nur die Plattform darf andere Teile von /data kennzeichnen.

Version der Genfs-Labels

Ab dem API-Level des Anbieters 202504 sind neuere SELinux-Labels, die mit genfscon in system/sepolicy/compat/plat_sepolicy_genfs_{ver}.cil zugewiesen sind, für ältere Anbieterpartitionen optional. So können ältere Anbieterpartitionen ihre vorhandene SEPolicy-Implementierung beibehalten. Dies wird durch die Makefile-Variable BOARD_GENFS_LABELS_VERSION gesteuert, die in /vendor/etc/selinux/genfs_labels_version.txt gespeichert ist.

Beispiel:

  • In der API-Ebene des Anbieters 202404 ist der Knoten /sys/class/udc standardmäßig mit sysfs gekennzeichnet.
  • Ab der Anbieter-API-Ebene 202504 wird /sys/class/udc als sysfs_udc gekennzeichnet.

/sys/class/udc wird jedoch möglicherweise von Anbieterpartitionen mit API-Ebene 202404 verwendet, entweder mit dem Standardlabel sysfs oder einem anbieterspezifischen Label. Wenn /sys/class/udc bedingungslos als sysfs_udc gekennzeichnet wird, kann die Kompatibilität mit diesen Partitionen des Anbieters beeinträchtigt werden. Wenn Sie BOARD_GENFS_LABELS_VERSION aktivieren, verwendet die Plattform weiterhin die vorherigen Labels und Berechtigungen für die älteren Anbieterpartitionen.

BOARD_GENFS_LABELS_VERSION kann größer oder gleich der Anbieter-API-Ebene sein. Anbieterpartitionen, die API-Level 202404 verwenden, können BOARD_GENFS_LABELS_VERSION beispielsweise auf 202504 festlegen, um neue Labels zu übernehmen, die 202504 eingeführt wurden. Liste der 202504-spezifischen genfs-Labels

Beim Beschriften von genfscon-Knoten muss die Plattform ältere Anbieterpartitionen berücksichtigen und bei Bedarf Fallback-Mechanismen für die Kompatibilität implementieren. Die Plattform kann nur für die Plattform bestimmte Bibliotheken verwenden, um die Genfs-Labels-Version abzufragen.

Kompatibilitätsattribute

Eine SELinux-Richtlinie ist 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.

Die Richtlinie bezieht sich hauptsächlich auf vorhandene Typen:

allow source_type target_type:target_class permission(s);

Das funktioniert, weil die Richtlinie mit dem Wissen um alle Arten verfasst wurde. Wenn jedoch in der Anbieterrichtlinie und der Plattformrichtlinie bestimmte Typen verwendet werden und sich das Label eines bestimmten Objekts nur in einer dieser Richtlinien ändert, kann die andere Richtlinie Zugriff gewähren oder entziehen, auf den zuvor vertraut wurde. 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 zu Folgendem geändert werden:

File_contexts:
/sys/A   u:object_r:sysfs_A:s0

Die Richtlinie des Anbieters bleibt gleich, aber der v_domain verliert den Zugriff, da es keine Richtlinie für den neuen sysfs_A-Typ gibt.

Wenn wir eine Richtlinie in Form von Attributen definieren, können wir dem zugrunde liegenden Objekt einen Typ zuweisen, der ein Attribut mit einer Richtlinie für den Plattform- und Anbietercode hat. Das kann für alle Typen erfolgen, um eine Attributrichtlinie zu erstellen, in der keine konkreten Typen verwendet werden. In der Praxis ist dies nur für die Teile der Richtlinie erforderlich, die sich zwischen Plattform und Anbieter überschneiden. Diese werden als öffentliche Plattformrichtlinie definiert und als Teil der Anbieterrichtlinie bereitgestellt.

Wenn Sie öffentliche Richtlinien als versionierte Attribute definieren, werden zwei Ziele der Richtlinienkompatibilität erfüllt:

  • Achten Sie darauf, dass der Anbietercode nach der Plattformaktualisierung weiterhin funktioniert. Dazu werden Attribute zu bestimmten Typen für Objekte hinzugefügt, die denen entsprechen, auf die sich der Anbietercode stützte, um den Zugriff zu erhalten.
  • Möglichkeit, Richtlinien einzustellen 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 weiterhin in der Anbieterrichtlinie vorhanden ist und bei einem Upgrade automatisch entfernt wird.

Schreibbarkeit von Richtlinien

Damit für die Richtlinienentwicklung keine Kenntnisse zu bestimmten Versionsänderungen erforderlich sind, enthält Android 8.0 eine Zuordnung zwischen plattformöffentlichen Richtlinientypen und ihren Attributen. Der Typ foo ist dem Attribut foo_vN zugeordnet. N ist die Version, auf die die Ausrichtung erfolgt. vN entspricht der Buildvariablen PLATFORM_SEPOLICY_VERSION und hat das Format MM.NN, wobei MM der SDK-Nummer der Plattform entspricht und NN eine plattformspezifische Sepolicy-Version ist.

Attribute in öffentlichen Richtlinien sind nicht versioniert, sondern existieren als API, auf der Plattform- und Anbieterrichtlinien aufgebaut werden können, um die Schnittstelle zwischen den beiden Partitionen stabil zu halten. Sowohl Plattform- als auch Anbieterrichtlinien können weiterhin wie bisher verfasst werden.

Die als allow source_foo target_bar:class perm; exportierte Plattform-Richtlinie ist Teil der Anbieterrichtlinie. Während der Kompilierung (einschließlich der entsprechenden Version) wird sie in die Richtlinie umgewandelt, die an den Anbieterbereich des Geräts gesendet wird (in der umgewandelten Common Intermediate Language (CIL) dargestellt):

 (allow source_foo_vN target_bar_vN (class (perm)))

Da die Richtlinien der Anbieter nie der Plattform voraus sind, sollten sie sich nicht auf frühere Versionen beziehen. Die Plattformrichtlinie muss jedoch wissen, wie alt die Anbieterrichtlinie ist, Attribute zu den Typen einschließen und eine Richtlinie für die versionierten Attribute festlegen.

Richtlinienabweichungen

Wenn Sie Attribute automatisch erstellen, indem Sie am Ende jedes Typs _vN hinzufügen, passiert ohne Zuordnung von Attributen zu Typen über Versionsunterschiede hinweg nichts. Android unterstützt eine Zuordnung zwischen Versionen für Attribute und eine Zuordnung von Typen zu diesen Attributen. Dies geschieht in den oben genannten Zuordnungsdateien mit Anweisungen wie (CIL):

(typeattributeset foo_vN (foo))

Plattformupdates

Im folgenden Abschnitt werden Szenarien für Plattformupgrades beschrieben.

Gleiche Typen

Dieses Szenario tritt auf, wenn für ein Objekt keine Labels in Richtlinienversionen geändert werden. Das gilt für Quell- und Zieltypen gleichermaßen und kann anhand von /dev/binder veranschaulicht werden, das in allen Releases mit binder_device gekennzeichnet ist. In der umgewandelten Richtlinie wird sie so dargestellt:

binder_device_v1 … binder_device_vN

Beim Upgrade von v1 auf 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 Anbieterrichtlinie der Version 1 (CIL):

(typeattribute binder_device_v1)
(allow binder_device_v1 )

In der Anbieterrichtlinie der Version 2 (CIL):

(typeattribute binder_device_v2)
(allow binder_device_v2 )
Neue Typen

Dieses Szenario tritt auf, wenn der Plattform ein neuer Typ hinzugefügt wurde. Das kann beim Hinzufügen neuer Funktionen oder bei der Richtlinienverschärfung passieren.

  • Neue Funktion Wenn der Typ ein Objekt kennzeichnet, das zuvor nicht vorhanden war (z. B. einen neuen Dienstprozess), hat der Anbietercode zuvor nicht direkt mit ihm interagiert. Daher gibt es keine entsprechende Richtlinie. Das neue Attribut, das dem Typ entspricht, hat in der vorherigen Version kein Attribut. Daher ist kein Eintrag in der Zuordnungsdatei für diese Version erforderlich.
  • Richtlinienhärtung Wenn der Typ eine Richtlinienverschärfung darstellt, muss das neue Typattribut auf eine Kette von Attributen verweisen, die der vorherigen entsprechen (ähnlich wie im vorherigen Beispiel, in dem /sys/A von sysfs in sysfs_A geändert wird). Der Anbietercode basiert auf einer Regel, die den Zugriff auf sysfs ermöglicht, und muss diese Regel als Attribut des neuen Typs enthalten.

Beim Upgrade von v1 auf 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 Anbieterrichtlinie der Version 1 (CIL):

(typeattribute sysfs_v1)
(allow  sysfs_v1 )

In der Anbieterrichtlinie der Version 2 (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. Das kann passieren, wenn das zugrunde liegende Objekt:

  • Bleibt erhalten, erhält aber ein anderes Label.
  • von der Plattform entfernt wird.

Bei der Lockerung einer Richtlinie wird ein Typ entfernt und dem mit diesem Typ gekennzeichneten Objekt wird ein anderes, bereits vorhandenes Label zugewiesen. Dies entspricht einer Zusammenführung von Attributzuordnungen: Der Anbietercode muss weiterhin über das Attribut, das er zuvor hatte, auf das zugrunde liegende Objekt zugreifen können. Der Rest des Systems muss jetzt jedoch über das neue Attribut darauf zugreifen können.

Wenn das Attribut, zu dem gewechselt wurde, neu ist, erfolgt das Umbenennen wie beim neuen Typ. Wenn jedoch ein vorhandenes Label verwendet wird, würde das Hinzufügen des alten Attributtyps dazu führen, dass andere Objekte, die ebenfalls mit diesem Typ gekennzeichnet sind, neu zugänglich werden. Das ist im Wesentlichen das, was die Plattform tut, und wird als akzeptabler Kompromiss zur Aufrechterhaltung der Kompatibilität angesehen.

(typeattribute sysfs_v1)
(allow  sysfs_v1 )

Beispiel Version 1: Zusammenklappbare Typen (Entfernen von sysfs_A)

Beim Upgrade von v1 auf 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 Anbieterrichtlinie der Version 1 (CIL):

(typeattribute sysfs_A_v1)
(allow  sysfs_A_v1 )
(typeattribute sysfs_v1)
(allow  sysfs_v1 )

In der Anbieterrichtlinie der Version 2 (CIL):

(typeattribute sysfs_v2)
(allow  sysfs_v2 )

Beispielversion 2: Vollständiges Entfernen (Typ „foo“)

Beim Upgrade von v1 auf 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 Anbieterrichtlinie der Version 1 (CIL):

(typeattribute foo_v1)
(allow foo )
(typeattribute sysfs_v1)
(allow sysfs_v1 )

In der Anbieterrichtlinie der Version 2 (CIL):

(typeattribute sysfs_v2)
(allow sysfs_v2 )
Neue Kurse/Berechtigungen

Dieses Szenario tritt auf, wenn durch ein Plattformupdate neue Richtlinienkomponenten eingeführt werden, die in früheren Versionen nicht vorhanden sind. Als Android beispielsweise den servicemanager-Objektmanager hinzufügte, der die Berechtigungen „Hinzufügen“, „Suchen“ und „Auflisten“ erstellte, benötigten Anbieter-Dämonen, die sich beim servicemanager registrieren wollten, Berechtigungen, die nicht verfügbar waren. Unter Android 8.0 können nur in der Plattformrichtlinie neue Klassen und Berechtigungen hinzugefügt werden.

Damit alle Domains, die gemäß der Anbieterrichtlinie erstellt oder erweitert werden konnten, die neue Klasse ohne Einschränkungen verwenden können, muss die Plattformrichtlinie eine Regel wie die folgende enthalten:

allow {domain -coredomain} *:new_class perm;

Möglicherweise ist sogar eine Richtlinie erforderlich, die den Zugriff für alle Arten von Oberflächen (öffentliche Richtlinie) zulässt, damit das Anbieterbild Zugriff erhält. Wenn dies zu einer nicht akzeptablen Sicherheitsrichtlinie führt (wie es bei den Änderungen am Dienstmanager der Fall sein könnte), kann ein Anbieterupgrade erzwungen werden.

Entfernte Klasse/Berechtigungen

Dieses Szenario tritt auf, wenn ein Objektmanager entfernt wird, z. B. der ZygoteConnection-Objektmanager. Es sollte keine Probleme verursachen. Die Objektmanager-Klasse und die Berechtigungen können in der Richtlinie so lange definiert bleiben, bis sie in der Anbieterversion nicht mehr verwendet werden. Dazu fügen Sie die Definitionen der entsprechenden Zuordnungsdatei hinzu.

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 erforderlich sind. Daher ist es unerlässlich, das Erstellen von vom Anbieter definierten Typen zuzulassen.

Da die Richtlinien des Anbieters immer die ältesten auf dem Gerät sind, müssen nicht alle Anbietertypen automatisch in Attribute in der Richtlinie umgewandelt werden. Die Plattform verwendet keine in den Richtlinien des Anbieters gekennzeichneten Elemente, da sie diese nicht kennt. Sie stellt jedoch die Attribute und öffentlichen Typen bereit, die sie zur Interaktion mit Objekten verwendet, die mit diesen Typen gekennzeichnet sind (z. B. domain, sysfs_type usw.). Damit die Plattform weiterhin richtig mit diesen Objekten interagieren kann, müssen die Attribute und Typen richtig angewendet werden. Möglicherweise müssen den anpassbaren Domains (z. B. init) auch bestimmte Regeln hinzugefügt werden.

Attributänderungen für Android 9

Die folgenden Attribute können auf Geräten verwendet werden, die auf Android 9 umgestellt werden. Auf Geräten, die mit Android 9 ausgeliefert werden, sind sie jedoch nicht zulässig.

Attribute für Richtlinienverstöße

Android 9 umfasst die folgenden domainbezogenen Attribute:

  • data_between_core_and_vendor_violators: Attribut für alle Domains, die gegen die Anforderung verstoßen, Dateien nicht über den Pfad zwischen vendor und coredomains freizugeben. Plattform- und Anbieterprozesse sollten keine Dateien auf dem Laufwerk zur Kommunikation verwenden (instabiles ABI). Empfehlung:
    • Für den Anbietercode sollte /data/vendor verwendet werden.
    • Das System sollte /data/vendor nicht verwenden.
  • system_executes_vendor_violators: Attribut für alle Systemdomains (außer init und shell domains), die gegen die Anforderung verstoßen, keine Binärdateien von Anbietern auszuführen. Die Ausführung von Anbieter-Binärdateien hat eine instabile API. Die Plattform darf Anbieter-Binärdateien nicht direkt ausführen. Empfehlung:
    • Solche Plattformabhängigkeiten von Anbieterbinärdateien müssen hinter HIDL HALs liegen.

      ODER

    • coredomains, die Zugriff auf Anbieterbinärdateien benötigen, sollten in die Anbieterpartition verschoben werden und sind dann keine coredomain mehr.

Nicht vertrauenswürdige Attribute

Nicht vertrauenswürdige Apps, die beliebigen Code hosten, sollten keinen Zugriff auf HwBinder-Dienste haben, mit Ausnahme derjenigen, die für den Zugriff durch solche Apps als ausreichend sicher eingestuft werden (siehe unten). Die beiden Hauptgründe dafür sind:

  1. HwBinder-Server führen keine Clientauthentifizierung durch, da HIDL derzeit keine Informationen zur UID des Anrufers preisgibt. Selbst wenn HIDL solche Daten offenlegen würde, arbeiten viele HwBinder-Dienste entweder auf einer Ebene unterhalb der von Apps (z. B. HALs) oder dürfen für die Autorisierung nicht auf die App-Identität angewiesen sein. 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.
  2. HAL-Server (eine Teilmenge der HwBinder-Dienste) enthalten Code mit einer höheren Häufigkeit von Sicherheitsproblemen als system/core-Komponenten und haben Zugriff auf die unteren Schichten des Stacks (bis hinunter zur Hardware). Dadurch steigt die Wahrscheinlichkeit, das Android-Sicherheitsmodell zu umgehen.

Safe-Dienste

Zu den sicheren Diensten gehören:

  • same_process_hwservice. Diese Dienste werden (per Definition) im Prozess des Clients ausgeführt und haben daher denselben Zugriff wie die Clientdomain, in der der Prozess ausgeführt wird.
  • coredomain_hwservice. Diese Dienste stellen keine Risiken im Zusammenhang mit Punkt 2 dar.
  • hal_configstore_ISurfaceFlingerConfigs. Dieser Dienst ist speziell für die Verwendung durch jede Domain konzipiert.
  • hal_graphics_allocator_hwservice. Diese Vorgänge werden auch vom surfaceflinger-Binderdienst angeboten, auf den Apps zugreifen dürfen.
  • hal_omx_hwservice. Dies ist eine HwBinder-Version des mediacodec-Binder-Dienstes, auf den Apps zugreifen dürfen.
  • hal_codec2_hwservice. Dies ist eine neuere Version von hal_omx_hwservice.

Verwendbare Attribute

Alle hwservices, die nicht als sicher eingestuft werden, haben das Attribut untrusted_app_visible_hwservice. Die entsprechenden HAL-Server haben das Attribut untrusted_app_visible_halserver. Auf Geräten mit Android 9 darf KEIN untrusted-Attribut verwendet werden.

Empfehlung:

  • Nicht vertrauenswürdige Apps sollten stattdessen mit einem Systemdienst kommunizieren, der mit der HIDL HAL des Anbieters kommuniziert. Apps können beispielsweise mit binderservicedomain kommunizieren, dann mediaserver (eine binderservicedomain) mit der hal_graphics_allocator.

    ODER

  • Apps, die direkten Zugriff auf vendor HALs benötigen, sollten eine eigene vom Anbieter definierte SEPolicy-Domain haben.

Dateiattributtests

Android 9 enthält Buildzeittests, die dafür sorgen, dass alle Dateien an bestimmten Speicherorten die entsprechenden Attribute haben (z. B. dass alle Dateien in sysfs das erforderliche sysfs_type-Attribut haben).

Plattformrichtlinien

Die Plattformrichtlinie ist der Kern der Einhaltung des Architekturmodells von Android 8.0, ohne einfach die Vereinigung der Plattformrichtlinien von Version 1 und Version 2 beizubehalten. Anbietern wird ein Teil der Plattformrichtlinie angezeigt, der verwendbare Typen und Attribute sowie Regeln für diese Typen und Attribute enthält. Diese werden dann Teil der Anbieterrichtlinie (vendor_sepolicy.cil).

Typen und Regeln werden in der vom Anbieter generierten Richtlinie automatisch in attribute_vN übersetzt, sodass alle von der Plattform bereitgestellten Typen Versionsattribute sind (Attribute werden jedoch nicht versioniert). Die Plattform ist dafür verantwortlich, die von ihr bereitgestellten Typen den entsprechenden Attributen zuzuordnen, damit die Anbieterrichtlinie weiterhin funktioniert und die für eine bestimmte Version bereitgestellten Regeln enthalten sind. Die Kombination aus öffentlichen Plattformrichtlinien und Anbieterrichtlinien erfüllt das Ziel des Architekturmodells von Android 8.0, unabhängige Plattform- und Anbieter-Builds zu ermöglichen.

Zuordnung zu Attributketten

Wenn Sie Attribute verwenden, um Richtlinienversionen zuzuordnen, wird ein Typ einem Attribut oder mehreren Attributen zugeordnet. So ist sichergestellt, dass auf Objekte, die mit dem Typ gekennzeichnet sind, über Attribute zugegriffen werden kann, die ihren vorherigen Typen entsprechen.

Wenn Sie Versionsinformationen vor dem Richtlinienschreiber verbergen möchten, müssen Sie die versionierten Attribute automatisch generieren und den entsprechenden Typen zuweisen. Im häufigen Fall statischer Typen ist das ganz einfach: type_foo wird type_foo_v1 zugeordnet.

Bei einer Objektlabeländerung wie sysfs → sysfs_A oder mediaserver → audioserver ist das Erstellen dieser Zuordnung nicht trivial (siehe die Beispiele oben). Die Verantwortlichen für die Plattformrichtlinien müssen festlegen, wie die Zuordnung an Übergangspunkten für Objekte erstellt wird. Dazu müssen sie die Beziehung zwischen Objekten und ihren zugewiesenen Labels verstehen und bestimmen, wann dies der Fall ist. Aus Gründen der Abwärtskompatibilität muss diese Komplexität auf Plattformebene verwaltet werden. Dies ist die einzige Partition, die aktualisiert werden kann.

Versionsvorgänger

Aus Gründen der Einfachheit wird auf der Android-Plattform eine SEPolicy-Version veröffentlicht, wenn ein neuer Release-Zweig erstellt wird. Wie oben beschrieben, ist die Versionsnummer in PLATFORM_SEPOLICY_VERSION enthalten und hat das Format MM.nn. Dabei entspricht MM dem SDK-Wert und nn ist ein privater Wert, der in /platform/system/sepolicy. gespeichert wird. Beispiele: 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 nicht immer ganze Zahlen. Wenn beispielsweise eine MR-Änderung an einer Version eine inkompatible Änderung an system/sepolicy/public, aber keine API-Änderung erfordert, könnte diese Sepolicy-Version vN.1 sein. Die Version in einem Entwicklungszweig ist eine 10000.0, die niemals in Geräten verwendet werden darf.

Android kann die älteste Version beim Upgraden verwerfen. Um zu ermitteln, wann eine Version eingestellt werden sollte, kann Android die Anzahl der Geräte mit Anbieterrichtlinien erfassen, auf denen diese Android-Version ausgeführt wird und die noch wichtige Plattformupdates erhalten. Wenn die Anzahl unter einem bestimmten Grenzwert liegt, wird die Version eingestellt.

Auswirkungen mehrerer Attribute auf die Leistung

Wie unter https://github.com/SELinuxProject/cil/issues/9 beschrieben, führt eine große Anzahl von Attributen, die einem Typ zugewiesen sind, bei einem Richtliniencache-Miss zu Leistungsproblemen.

Dieses Problem wurde bestätigt. Daher wurden Änderungen an Android 8.0 vorgenommen, um Attribute zu entfernen, die der Richtlinie vom Richtliniencompiler hinzugefügt wurden, sowie ungenutzte Attribute. Durch diese Änderungen wurden Leistungseinbrüche behoben.

system_ext public and product public policy

Ab Android 11 können die Partitionen system_ext und product ihre angegebenen öffentlichen Typen in die Anbieterpartition exportieren. Wie bei den ö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 erstellt wurde.

Wenn die system_ext- und product-Partitionen auf derselben Plattformversion N basieren, generiert das Buildsystem Basiszuordnungsdateien für system_ext/etc/selinux/mapping/N.cil und product/etc/selinux/mapping/N.cil, die Identitätszuordnungen von type zu type_N enthalten. Der Anbieter kann über das versionierte Attribut type_N auf type zugreifen.

Wenn nur die Partitionen system_ext und product aktualisiert werden, z. B. von N auf N+1 (oder höher), während der Anbieter bei N bleibt, verliert er möglicherweise den Zugriff auf die Typen der Partitionen system_ext und product. Um Unterbrechungen zu vermeiden, sollten die Partitionen system_ext und product Zuordnungsdateien von konkreten Typen zu type_N-Attributen enthalten. Jeder Partner ist für die Pflege der Zuordnungsdateien verantwortlich, wenn er den N-Anbieter mit N+1 (oder höher) system_ext- und product-Partitionen unterstützen möchte.

Dazu müssen Partner Folgendes tun:

  1. Kopieren Sie die generierten Basiszuordnungsdateien aus den Partitionen N, system_ext und product in das entsprechende Quellverzeichnis.
  2. Ändern Sie die Zuordnungsdateien nach Bedarf.
  3. Installieren Sie die Zuordnungsdateien auf den Partitionen N+1 (oder höher) system_ext und product.

Angenommen, N system_ext hat einen öffentlichen Typ namens foo_type. Dann sieht system_ext/etc/selinux/mapping/N.cil in der Partition N system_ext 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 für den Anbieter N mit foo_type abgeglichen werden soll, kann N.cil über

(typeattributeset foo_type_N (foo_type))

to

(typeattributeset foo_type_N (foo_type bar_type))

und dann auf der Partition N+1 system_ext installiert. Der N-Anbieter kann weiterhin auf foo_type und bar_type von N+1system_ext zugreifen.

SELinux-Kontexte kennzeichnen

Um die Unterscheidung zwischen Plattform- und Anbieter-SEPolicy zu unterstützen, werden SELinux-Kontextdateien vom System unterschiedlich erstellt, um sie voneinander zu trennen.

Dateikontexte

Mit Android 8.0 wurden die folgenden Änderungen für file_contexts eingeführt:

  • Um zusätzlichen Kompilierungsoverhead auf dem Gerät während des Starts zu vermeiden, existiert file_contexts nicht mehr in der Binärform. Stattdessen sind sie lesbare reguläre Ausdrucksdateien wie {property, service}_contexts (wie vor Version 7.0).
  • Die file_contexts-Dateien sind auf zwei Dateien aufgeteilt:
    • plat_file_contexts
      • Android-Plattform file_context ohne gerätespezifische Labels, mit Ausnahme der Labels für Teile der /vendor-Partition, die genau gekennzeichnet werden müssen, damit die sepolicy-Dateien ordnungsgemäß funktionieren.
      • Muss sich in der system-Partition unter /system/etc/selinux/plat_file_contexts auf dem Gerät befinden und muss von init zusammen mit dem Anbieter file_context zu Beginn geladen werden.
    • vendor_file_contexts
      • Gerätespezifische file_context, die durch Kombinieren von file_contexts aus den Verzeichnissen erstellt werden, auf die in den Boardconfig.mk-Dateien des Geräts durch BOARD_SEPOLICY_DIRS verwiesen wird.
      • Muss in der Partition vendor unter /vendor/etc/selinux/vendor_file_contexts installiert und von init zusammen mit der Plattform file_context zu Beginn geladen werden.

Property-Kontexte

Unter Android 8.0 wird die property_contexts in zwei Dateien aufgeteilt:

  • plat_property_contexts
    • Android-Plattform property_context ohne gerätespezifische Labels
    • Muss sich in der system-Partition unter /system/etc/selinux/plat_property_contexts befinden und muss von init zusammen mit dem Anbieterproperty_contexts zu Beginn geladen werden.
  • vendor_property_contexts
    • Gerätespezifische property_context, die durch Kombinieren von property_contexts aus den Verzeichnissen erstellt wird, auf die in den Boardconfig.mk-Dateien des Geräts durch BOARD_SEPOLICY_DIRS verwiesen wird.
    • Muss sich in der vendor-Partition unter /vendor/etc/selinux/vendor_property_contexts befinden und von init zusammen mit der Plattform property_context zu Beginn geladen werden.

Dienstkontexte

Unter Android 8.0 wird die service_contexts auf die folgenden Dateien aufgeteilt:

  • plat_service_contexts
    • Android-plattformspezifische service_context für die servicemanager. Die service_context hat keine gerätespezifischen Labels.
    • Muss sich in der system-Partition unter /system/etc/selinux/plat_service_contexts befinden und zusammen mit dem Anbieterservice_contexts von servicemanager zu Beginn geladen werden.
  • vendor_service_contexts
    • Gerätespezifische service_context, die durch Zusammenführen von service_contexts aus den Verzeichnissen erstellt wurden, auf die in den Boardconfig.mk-Dateien des Geräts durch BOARD_SEPOLICY_DIRS verwiesen wird.
    • Muss sich in der vendor-Partition unter /vendor/etc/selinux/vendor_service_contexts befinden und von servicemanager zusammen mit der Plattform service_contexts zu Beginn geladen werden.
    • servicemanager sucht zwar beim Start nach dieser Datei, für ein vollständig konformes TREBLE-Gerät darf vendor_service_contexts jedoch NICHT vorhanden sein. Das liegt daran, dass alle Interaktionen zwischen vendor- und system-Prozessen über hwservicemanager/hwbinder erfolgen MÜSSEN.
  • plat_hwservice_contexts
    • Android-Plattform hwservice_context für hwservicemanager ohne gerätespezifische Labels.
    • Muss sich in der system-Partition unter /system/etc/selinux/plat_hwservice_contexts befinden und zusammen mit der vendor_hwservice_contexts von hwservicemanager zu Beginn geladen werden.
  • vendor_hwservice_contexts
    • Gerätespezifische hwservice_context, die durch Zusammenführen von hwservice_contexts aus den Verzeichnissen erstellt wurden, auf die in den Boardconfig.mk-Dateien des Geräts durch BOARD_SEPOLICY_DIRS verwiesen wird.
    • Muss sich in der vendor-Partition unter /vendor/etc/selinux/vendor_hwservice_contexts befinden und am Anfang zusammen mit der plat_service_contexts von hwservicemanager geladen werden.
  • vndservice_contexts
    • Gerätespezifische service_context für die vndservicemanager, die durch Kombinieren von vndservice_contexts aus den Verzeichnissen erstellt wird, auf die BOARD_SEPOLICY_DIRS im Boardconfig.mk des Geräts verweist.
    • Diese Datei muss sich in der Partition vendor unter /vendor/etc/selinux/vndservice_contexts befinden und zu Beginn von vndservicemanager geladen werden.

Seapp-Kontexte

Unter Android 8.0 wird die seapp_contexts in zwei Dateien aufgeteilt:

  • plat_seapp_contexts
    • Android-Plattform seapp_context ohne gerätespezifische Änderungen.
    • Muss sich in der system-Partition unter /system/etc/selinux/plat_seapp_contexts. befinden
  • vendor_seapp_contexts
    • Gerätespezifische Erweiterung der Plattform seapp_context, die durch Kombinieren von seapp_contexts aus den Verzeichnissen erstellt wird, auf die in den Boardconfig.mk-Dateien des Geräts über BOARD_SEPOLICY_DIRS verwiesen wird.
    • Muss sich in der vendor-Partition unter /vendor/etc/selinux/vendor_seapp_contexts befinden.

MAC-Berechtigungen

Unter Android 8.0 wird die mac_permissions.xml in zwei Dateien aufgeteilt:

  • Bahnsteig mac_permissions.xml
    • Android-Plattform mac_permissions.xml ohne gerätespezifische Änderungen.
    • Muss sich in der system-Partition unter /system/etc/selinux/. befinden
  • Nicht Plattform-bezogen mac_permissions.xml
    • Gerätespezifische Erweiterung der Plattformmac_permissions.xml, die aus mac_permissions.xml erstellt wurde und sich in den Verzeichnissen befindet, auf die in den Boardconfig.mk-Dateien des Geräts über BOARD_SEPOLICY_DIRS verwiesen wird.
    • Muss sich in der vendor-Partition unter /vendor/etc/selinux/. befinden