Richtlinienkompatibilität

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, um auf Teile der vendor zu kommunizieren und/oder darauf zuzugreifen. 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 in vendor Partition sein. Die Plattformrichtlinie erfordert dies, um auf Passthrough-HAL-Implementierungen zuzugreifen.
  • Alle neuen exec_types , die über die Vendor-SEPolicy in der vendor Partition hinzugefügt werden, müssen über das Attribut vendor_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 der vendor .
  • 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 v1v2 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 von sysfs in sysfs_A geändert wurde). Der Code des Anbieters basiert auf einer Regel, die den Zugriff auf sysfs ermöglicht, und muss diese Regel als Attribut des neuen Typs einschließen.

Beim Upgrade von v1v2 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 früher 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 v1v2 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 v1v2 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.

Damit alle Domänen, die durch die Richtlinien des Anbieters hätten erstellt oder erweitert werden können, die neue Klasse ungehindert nutzen können, 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 zwischen vendor und coredomains 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.
  • system_executes_vendor_violators . Attribut für alle Systemdomänen (außer init und shell 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 mehr coredomain sein.

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:

  1. HwBinder-Server führen keine Clientauthentifizierung durch, da HIDL derzeit keine Anrufer-UID-Informationen offenlegt. Auch 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.
  2. 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 vom surfaceflinger Binder-Dienst 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 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 kommuniziert mediaserver (der eine binderservicedomain ist) wiederum mit hal_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 sysfssysfs_A oder mediaserveraudioserver 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, beispielsweise 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:

  1. Kopieren Sie die generierten Basiszuordnungsdateien von N system_ext und Produktpartitionen in ihren Quellbaum.
  2. Ändern Sie die Zuordnungsdateien nach Bedarf.
  3. 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 von init beim Start zusammen mit dem file_context des Anbieters geladen werden.
    • vendor_file_contexts
      • Gerätespezifischer file_context der durch Kombinieren file_contexts erstellt wird, die in den Verzeichnissen gefunden werden, auf die BOARD_SEPOLICY_DIRS in den Boardconfig.mk Dateien des Geräts verweist.
      • Muss unter /vendor/etc/selinux/vendor_file_contexts in vendor Partition installiert und von init beim Start zusammen mit der Plattform file_context geladen werden.

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 von init zu Beginn zusammen mit den property_contexts des Anbieters geladen werden.
  • vendor_property_contexts
    • Gerätespezifischer property_context , der durch Kombination von property_contexts erstellt wird, die in den Verzeichnissen gefunden werden, auf die BOARD_SEPOLICY_DIRS in Boardconfig.mk Dateien des Geräts verweist.
    • Muss sich in vendor Partition unter /vendor/etc/selinux/vendor_property_contexts befinden und von init beim Start zusammen mit dem Plattform- property_context geladen werden

Servicekontexte

In Android 8.0 sind die service_contexts auf die folgenden Dateien aufgeteilt:

  • plat_service_contexts
    • Android-plattformspezifischer service_context für den servicemanager . Der service_context hat keine gerätespezifischen Bezeichnungen.
    • Muss sich in system unter /system/etc/selinux/plat_service_contexts befinden und von servicemanager beim Start zusammen mit den service_contexts des Anbieters geladen werden.
  • vendor_service_contexts
    • Gerätespezifischer service_context der durch Kombinieren service_contexts erstellt wird, die in den Verzeichnissen gefunden werden, auf die BOARD_SEPOLICY_DIRS in den Boardconfig.mk Dateien des Geräts verweist.
    • Muss sich in vendor Partition unter /vendor/etc/selinux/vendor_service_contexts befinden und von servicemanager beim Start zusammen mit der Plattform service_contexts geladen werden.
    • Obwohl servicemanager beim Booten nach dieser Datei sucht, DÜRFEN die vendor_service_contexts für ein vollständig kompatibles TREBLE Gerät NICHT vorhanden sein. Dies liegt daran, dass die gesamte Interaktion zwischen vendor und system über hwservicemanager / hwbinder erfolgen MUSS.
  • plat_hwservice_contexts
    • Android-Plattform hwservice_context für hwservicemanager , die keine gerätespezifischen Bezeichnungen hat.
    • Muss sich in system unter /system/etc/selinux/plat_hwservice_contexts befinden und von hwservicemanager beim Start zusammen mit vendor_hwservice_contexts geladen werden.
  • vendor_hwservice_contexts
    • Gerätespezifischer hwservice_context , der durch Kombination hwservice_contexts erstellt wird, die in den Verzeichnissen gefunden werden, auf die BOARD_SEPOLICY_DIRS in den Boardconfig.mk Dateien des Geräts verweist.
    • Muss sich in vendor Partition unter /vendor/etc/selinux/vendor_hwservice_contexts befinden und von hwservicemanager beim Start zusammen mit plat_service_contexts geladen werden.
  • vndservice_contexts
    • Gerätespezifischer service_context für den vndservicemanager , der durch Kombinieren vndservice_contexts erstellt wird, die in den Verzeichnissen gefunden werden, auf die BOARD_SEPOLICY_DIRS in der Boardconfig.mk des Geräts verweist.
    • Diese Datei muss sich in der vendor unter /vendor/etc/selinux/vndservice_contexts befinden und beim Start von vndservicemanager geladen werden.

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.
  • vendor_seapp_contexts
    • Gerätespezifische Erweiterung der Plattform seapp_context , die durch Kombination von seapp_contexts erstellt wird, die in den Verzeichnissen gefunden werden, auf die BOARD_SEPOLICY_DIRS in den Boardconfig.mk Dateien des Geräts verweist.
    • Muss sich in der vendor unter /vendor/etc/selinux/vendor_seapp_contexts befinden.

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/.
  • Nicht-Plattform mac_permissions.xml
    • Gerätespezifische Erweiterung der Plattform mac_permissions.xml , erstellt aus mac_permissions.xml gefunden in den Verzeichnissen, auf die BOARD_SEPOLICY_DIRS in den Boardconfig.mk Dateien des Geräts verweist.
    • Muss sich in der vendor unter /vendor/etc/selinux/.