Arm v9 führt Arm Memory ein Tagging Extension (MTE), eine Hardwareimplementierung von getaggte Speicher.
Grundsätzlich kennzeichnet MTE jede Arbeitsspeicherzuweisung/-zuweisung mit zusätzliche Metadaten. Sie weist einem Speicherstandort ein Tag zu, der dann die mit Zeigern verknüpft sind, die auf diesen Speicherort verweisen. Während der Laufzeit überprüft, ob der Zeiger und die Metadaten-Tags bei jedem Laden und Speicher übereinstimmen.
In Android 12 kann die Heap-Speicher-Zuweisung für Kernel und Userspace jede Zuweisung mit Metadaten. So lässt sich erkennen, Pufferüberlauf-Fehler, die die häufigste Ursache für unserer Codebasen.
MTE-Betriebsmodi
MTE hat drei Betriebsmodi:
- Synchroner Modus (SYNC)
- Asynchroner Modus (ASYNC)
- Asymmetrischer Modus (ASYMM)
Synchroner Modus (SYNC)
Dieser Modus ist im Hinblick auf Fehlererkennung
im Hinblick auf Leistung optimiert und
kann als präzises Tool zur Fehlererkennung verwendet werden, wenn
akzeptabel. Wenn MTE SYNC aktiviert ist, dient MTE SYNC als Abhilfe für die Sicherheit.
Bei einem nicht übereinstimmenden Tag bricht der Prozessor die Ausführung sofort ab
beendet den Prozess mit SIGSEGV
(Code
SEGV_MTESERR
) sowie die vollständigen Informationen zum Arbeitsspeicherzugriff und zu den
fehlerhafte Adresse.
Wir empfehlen, diesen Modus beim Testen als Alternative zu HWASan/KASAN oder in der Produktion, wenn der Zielprozess eine Schwachstelle darstellt Angriffsfläche. Wenn der ASYNC-Modus anzeigt, dass ein Fehler enthalten, können Sie einen genauen Fehlerbericht abrufen, indem Sie die Laufzeit-APIs verwenden, um den SYNC-Modus an.
Im SYNC-Modus zeichnet der Android-Allocator Stacktraces für alle Zuweisungen und Deallocations sowie verwendet sie, um bessere Fehlerberichte bereitzustellen, die eine Erläuterung eines Gedächtnisses enthalten. wie Use-After-Free oder buffer-Overflow, und die Stacktraces der relevante Gedächtnis-Ereignisse. Solche Berichte enthalten mehr Kontextinformationen und Fehler leichter nachzuverfolgen und zu beheben.
Asynchroner Modus (ASYNC)
Dieser Modus ist eher auf Leistung als auf Genauigkeit von Fehlerberichten ausgelegt und kann
zur Erkennung von geringen Mehraufwand bei sicherheitsrelevanten Fehlern im Arbeitsspeicher verwendet werden.
Bei einem nicht übereinstimmenden Tag fährt der Prozessor bis zum nächsten Tag
Kernel-Eintrag (z. B. Systemaufruf oder Timer-Unterbrechung), bei dem er beendet wird
Prozess mit SIGSEGV
(Code SEGV_MTEAERR
) ohne
die fehlerhafte Adresse
oder den Arbeitsspeicherzugriff auf.
Wir empfehlen, diesen Modus in der Produktion auf gut getesteten Codebasen zu verwenden,
Es ist bekannt, dass die Dichte der Sicherheitsfehler niedrig ist. Dies wird erreicht, indem
den SYNC-Modus verwenden.
Asymmetrischer Modus (ASYMM)
Der asymmetrische MTE-Modus ist eine zusätzliche Funktion in Arm-Version 8.7-A und ermöglicht synchrone die Überprüfung von Lesevorgängen im Arbeitsspeicher und die asynchrone Prüfung von Speicherschreibvorgängen, mit einer ähnlichen Leistung wie der ASYNC-Modus. In den meisten Fällen ist eine Verbesserung gegenüber dem ASYNC-Modus. Wir empfehlen, ihn anstelle des ASYNC, wann immer es verfügbar ist.
Aus diesem Grund wird die asymmetrische API in keiner der unten beschriebenen APIs erwähnt. . Stattdessen kann das Betriebssystem so konfiguriert werden, dass immer der asymmetrische Modus verwendet wird, wenn Asynchron wird angefordert. Weitere Informationen dazu finden Sie im Abschnitt "CPU-spezifische bevorzugter MTE-Level .
MTE im Userspace
In den folgenden Abschnitten wird beschrieben, wie MTE für Systemprozesse aktiviert werden kann. und Apps. MTE ist standardmäßig deaktiviert, es sei denn, eine der folgenden Optionen ist für einen bestimmten Prozess festgelegt sind (für welche Komponenten MTE aktiviert ist).
MTE mit dem Build-System aktivieren
Als prozessweites Attribut wird MTE von der Build-Zeiteinstellung des der ausführbaren Hauptdatei. Mit den folgenden Optionen können Sie diese Einstellung für für einzelne ausführbare Dateien oder für ganze Unterverzeichnisse in der Quellstruktur. Die wird für Bibliotheken oder Ziele, die weder ausführbar noch testen.
1. Aktivierung von MTE in Android.bp
(Beispiel)
für ein bestimmtes Projekt:
MTE-Modus | Einstellung |
---|---|
Asynchrone MTE | sanitize: { memtag_heap: true, } |
Synchroner MTE | sanitize: { memtag_heap: true, diag: { memtag_heap: true, }, } |
oder in Android.mk:
MTE-Modus | Einstellung |
---|---|
Asynchronous MTE |
LOCAL_SANITIZE := memtag_heap |
Synchronous MTE |
LOCAL_SANITIZE := memtag_heap LOCAL_SANITIZE_DIAG := memtag_heap |
2. MTE mithilfe eines Produkts in einem Unterverzeichnis in der Quellstruktur aktivieren Variable:
MTE-Modus | Einschlussliste | Ausschlussliste |
---|---|---|
asynchron | PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS
MEMTAG_HEAP_ASYNC_INCLUDE_PATHS |
PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS
MEMTAG_HEAP_EXCLUDE_PATHS |
Sync | PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS
MEMTAG_HEAP_SYNC_INCLUDE_PATHS |
oder
MTE-Modus | Einstellung |
---|---|
Asynchrone MTE | MEMTAG_HEAP_ASYNC_INCLUDE_PATHS |
Synchroner MTE | MEMTAG_HEAP_SYNC_INCLUDE_PATHS |
oder durch Angabe des Ausschlusspfads einer ausführbaren Datei:
MTE-Modus | Einstellung |
---|---|
Asynchrone MTE | PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS
MEMTAG_HEAP_EXCLUDE_PATHS |
Synchroner MTE |
Beispiel (ähnliche Verwendung wie PRODUCT_CFI_INCLUDE_PATHS
)
PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS=vendor/$(vendor) PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS=vendor/$(vendor)/projectA \ vendor/$(vendor)/projectB
MTE mithilfe von Systemeigenschaften aktivieren
Die obigen Build-Einstellungen können während der Laufzeit überschrieben werden. Legen Sie dazu den Parameter folgende Systemeigenschaft:
arm64.memtag.process.<basename> = (off|sync|async)
Dabei steht basename
für den Basisnamen der ausführbaren Datei.
Um beispielsweise /system/bin/ping
oder /data/local/tmp/ping
festzulegen,
Um den asynchronen MTE zu verwenden, verwenden Sie adb shell setprop arm64.memtag.process.ping async
.
MTE mit einer Umgebungsvariable aktivieren
Eine weitere Möglichkeit, die Build-Einstellung zu überschreiben, ist das Definieren der Umgebung
Variable: MEMTAG_OPTIONS=(off|sync|async)
Wenn sowohl die Umgebungsvariable als auch die Systemeigenschaft definiert sind,
Variable Vorrang hat.
MTE für Apps aktivieren
Wenn nicht angegeben, ist MTE standardmäßig deaktiviert,
Apps, die MTE nutzen möchten, können dies tun, indem du android:memtagMode
festlegst
gemäß der <application>
oder
<process>
-Tag im
AndroidManifest.xml
.
android:memtagMode=(off|default|sync|async)
Bei Festlegung im <application>
-Tag wird der Parameter
Attribut wirkt sich auf alle von der App verwendeten Prozesse aus und kann überschrieben werden.
für einzelne Prozesse, indem Sie die
<process>
-Tag.
Zum Experimentieren: Kompatibilität mit
Änderungen können Sie den Standardwert für
memtagMode
-Attribut für eine App, die
im Manifest keinen Wert angeben (oder
default
.
Diese finden Sie im Menü für globale Einstellungen unter System > Advanced > Developer options
> App Compatibility Changes
. Einstellung
NATIVE_MEMTAG_ASYNC
oder NATIVE_MEMTAG_SYNC
aktiviert MTE
für eine bestimmte App.
Alternativ kann dies mit der am
festgelegt werden.
-Befehl so an:
$ adb shell am compat enable NATIVE_MEMTAG_[A]SYNC my.app.name
MTE-System-Image erstellen
Wir empfehlen dringend, MTE während der Entwicklung für alle nativen Binärprogramme zu aktivieren. und es bringt es auf. So lassen sich Sicherheitsrisiken frühzeitig erkennen und realistische Nutzerabdeckung, sofern in Test-Builds aktiviert.
Es wird dringend empfohlen, MTE während der Entwicklung im synchronen Modus für alle nativen Binärdateien zu aktivieren.
SANITIZE_TARGET=memtag_heap SANITIZE_TARGET_DIAG=memtag_heap m
Wie bei jeder Variablen im Build-System kann SANITIZE_TARGET
auch
als Umgebungsvariable oder make
-Einstellung verwendet wird (z. B. in
eine product.mk
-Datei).
Beachten Sie, dass dadurch MTE für alle nativen Prozesse aktiviert wird, aber nicht für
Apps (die aus zygote64
abgeleitet wurden), für die MTE verwendet werden kann
gemäß der Anleitung oben aktiviert.
CPU-spezifische bevorzugte MTE-Ebene konfigurieren
Auf einigen CPUs kann die Leistung von MTE im ASYMM- oder sogar SYNC-Modi der folgenden ähneln:
von ASYNC. Daher lohnt es sich,
strengere Prüfungen dieser CPUs erforderlich sind, wenn ein weniger strenger Prüfmodus angefordert wird.
um die Vorteile der strengeren Prüfungen zur Fehlererkennung zu nutzen,
die Leistung beeinträchtigen.
Standardmäßig werden Prozesse, die für die Ausführung im ASYNC-Modus konfiguriert sind, in ASYNC ausgeführt
Modus auf allen CPUs. Um den Kernel so zu konfigurieren, dass diese Prozesse im SYNC-Modus auf
muss der Wert "sync" in den
sysfs
Eintrag
/sys/devices/system/cpu/cpu<N>/mte_tcf_preferred
beim Start
. Dazu können Sie ein Initialisierungsskript verwenden. Um z. B. CPUs 0-1 zu konfigurieren,
um Prozesse im ASYNC-Modus im SYNC-Modus auszuführen, und CPUs 2-3, um im ASYMM-Modus auszuführen.
Folgendes kann der Init-Klausel eines Anbieter-Initialisierungsskripts hinzugefügt werden:
write /sys/devices/system/cpu/cpu0/mte_tcf_preferred sync write /sys/devices/system/cpu/cpu1/mte_tcf_preferred sync write /sys/devices/system/cpu/cpu2/mte_tcf_preferred asymm write /sys/devices/system/cpu/cpu3/mte_tcf_preferred asymm
Tombstones aus Prozessen im ASYNC-Modus, die im SYNC-Modus ausgeführt werden, enthalten ein Den genauen Stacktrace der Position des Speicherfehlers. Sie werden jedoch nicht einen Zuordnungs- oder Deallocation-Stacktrace. Diese Stacktraces sind nur verfügbar, wenn der Prozess für die Ausführung im SYNC-Modus konfiguriert ist.
int mallopt(M_THREAD_DISABLE_MEM_INIT, level)
Dabei ist level
0 oder 1.
Deaktiviert die Initialisierung des Arbeitsspeichers in Malloc und vermeidet das Ändern von Speicher-Tags.
es sei denn, dies ist zur Richtigkeit erforderlich.
int mallopt(M_MEMTAG_TUNING, level)
Dabei steht level
für:
M_MEMTAG_TUNING_BUFFER_OVERFLOW
M_MEMTAG_TUNING_UAF
Hiermit wird eine Strategie für die Tag-Zuweisung ausgewählt.
- Die Standardeinstellung ist
M_MEMTAG_TUNING_BUFFER_OVERFLOW
. M_MEMTAG_TUNING_BUFFER_OVERFLOW
: aktiviert den deterministischen Erkennung von linearen Pufferüberlauf- und Unterlauffehlern durch Zuweisung unterschiedlicher Tags auf benachbarte Zuweisungen anwenden. In diesem Modus ist die Wahrscheinlichkeit geringer, „Use After Free“-Programmfehler erkennen, da nur die Hälfte der möglichen Tag-Werte die für jeden Speicherort verfügbar sind. Beachten Sie, dass MTE die innerhalb derselben Tag-Granule (16-Byte-konformer Block) überlaufen und kleine Mengen auch in diesem Modus überläuft. Ein solcher Überlauf kann nicht der Grund für den Speicher sein da der Speicher innerhalb einer Granule nie für mehrere Zuweisungen.M_MEMTAG_TUNING_UAF
: aktiviert unabhängige, randomisierte Tags für eine einheitliche ~93% ige Wahrscheinlichkeit, dass sowohl räumliche (Pufferüberlauf) als auch temporale (Verwendung nach kostenloser) Bugs.
Neben den oben beschriebenen APIs möchten erfahrene Nutzer möglicherweise beachten Sie Folgendes:
- Das Einrichten der
PSTATE.TCO
-Hardwareregisterkarte kann vorübergehend Tag-Überprüfung zu unterdrücken (Beispiel). Beispielsweise beim Kopieren eines Speicherbereichs mit unbekanntem Tag-Inhalt oder einen Leistungsengpass in einem Hot Loop zu beseitigen. - Bei Verwendung von
M_HEAP_TAGGING_LEVEL_SYNC
wird der Systemabsturz-Handler liefert zusätzliche Informationen wie Stacktraces für die Zuweisung und die Freigabe. Diese Funktion erfordert Zugriff auf die Tag-Bits und wird aktiviert, indem derSA_EXPOSE_TAGBITS
, wenn Sie den Signal-Handler festlegen. Jedes Programm, das sein eigenes Signal festlegt und delegiert unbekannte Abstürze an das System. nicht identisch sind.
MTE im Kernel
Um MTE-beschleunigtes KASAN für den Kernel zu aktivieren, konfigurieren Sie den Kernel mit
CONFIG_KASAN=y
, CONFIG_KASAN_HW_TAGS=y
. Diese Konfigurationen
sind in GKI-Kernels standardmäßig aktiviert, beginnend mit Android
12-5.10
.
Dies kann beim Booten mit den folgenden Befehlszeilenargumenten gesteuert werden:
kasan=[on|off]
: KASAN aktivieren oder deaktivieren (Standard:on
)kasan.mode=[sync|async]
– Zwischen synchronem und asynchronem Modus wählen (Standardeinstellung:sync
)kasan.stacktrace=[on|off]
– ob erfasst werden soll Stacktraces (Standard:on
)- ist es außerdem erforderlich,
stack_depot_disable=off
- ist es außerdem erforderlich,
kasan.fault=[report|panic]
: Gibt an, ob nur der Bericht gedruckt werden soll, oder eine Panik im Kernel verursachen (Standardeinstellung:report
). Unabhängig davon wird die Tag-Überprüfung nach dem ersten gemeldeten Fehler deaktiviert.
Empfohlene Verwendung
Wir empfehlen dringend, den SYNC-Modus während der Bereitstellung, Entwicklung und Tests durchführen. Diese Option sollte global für alle Prozesse aktiviert werden, die die Umgebungsvariable oder das Build-System verwenden. In diesem Modus werden Fehler erkannt zu Beginn des Entwicklungsprozesses, wird die Codebasis schneller stabilisiert und die Kosten für die spätere Erkennung von Fehlern in der Produktion entfallen.
Wir empfehlen dringend, den ASYNC-Modus in der Produktion zu verwenden. Dies sorgt für eine geringe um das Vorhandensein von Fehlern in Bezug auf die Speichersicherheit in einem Prozess zu erkennen, sowie weitere tief greifende Verteidigung. Sobald ein Fehler gefunden wurde, kann der Entwickler Nutzen Sie die Laufzeit-APIs, um in den SYNC-Modus zu wechseln und einen genauen Stacktrace zu erhalten aus einer Stichprobe von Nutzenden.
Wir empfehlen dringend, die CPU-spezifische bevorzugte MTE-Ebene für das SoC. Der Asymm-Modus hat in der Regel die gleichen Leistungsmerkmale wie ASYNC, und ist fast immer besser geeignet. Kleine Kerne nach Reihenfolge weisen oft ähnliche in allen drei Modi und kann so konfiguriert werden, dass SYNC bevorzugt wird.
Entwickler sollten das Vorhandensein von Abstürzen prüfen, indem sie Folgendes prüfen:
/data/tombstones
,
logcat
oder durch Überwachen des Anbieters DropboxManager
für Programmfehler von Endnutzern. Weitere Informationen zum Debuggen von nativem Android-Code finden Sie unter
finden Sie hier.
MTE-fähige Plattformkomponenten
In Android 12 verwenden eine Reihe von sicherheitskritischen Systemkomponenten MTE ASYNC um Abstürze von Endnutzern zu erkennen und als zusätzliche gestaffelte Sicherheitsebenen. Diese Komponenten sind:
- Netzwerk-Daemons und Dienstprogramme (mit Ausnahme von
netd
) - Bluetooth, SecureElement, NFC-HALs und System-Apps
statsd
Daemonsystem_server
zygote64
(damit Apps die Verwendung von MTE aktivieren können)
Diese Ziele wurden anhand der folgenden Kriterien ausgewählt:
- Ein privilegierter Prozess (definiert als ein Prozess, der Zugriff auf etwas hat) die die SELinux-Domain unprivileged_app nicht tut)
- Verarbeitet nicht vertrauenswürdige Eingaben (Regel von zwei)
- Akzeptable Leistungsabschwächung (Verlangsamung sorgt dafür, dass Nutzer nicht sichtbar sind) Latenz)
Wir empfehlen Anbietern, MTE in der Produktion für weitere Komponenten zu aktivieren,
unter Berücksichtigung der oben genannten Kriterien. Wir empfehlen, während der Entwicklungsphase
mithilfe des SYNC-Modus an, um Fehler leicht zu beheben und
ASYNC beeinflusst ihre Leistung.
Für die Zukunft plant Android, die Liste der Systemkomponenten (MTE) zu erweitern,
basierend auf den Leistungsmerkmalen zukünftiger Hardwaredesigns aktiviert.