Bis 2016 betraf etwa 86% aller Sicherheitslücken bei Android die Arbeitsspeichersicherheit. verwandt. Die meisten Schwachstellen werden von Angreifern ausgenutzt, die den Normalzustand ändern Steuerung des Ablaufs einer App, um beliebige schädliche Aktivitäten mit alle Berechtigungen der ausgenutzten App nutzen. Ablauf steuern Integrität (CFI) ist ein Sicherheitsmechanismus, der Änderungen an der ursprünglichen Kontrollflussdiagramm einer kompilierten Binärdatei, was es erheblich schwieriger macht, um solche Angriffe auszuführen.
In Android 8.1 haben wir die Implementierung von CFI durch LLVM im Media-Stack aktiviert. In Mit Android 9 haben wir CFI in mehr Komponenten und auch im Kernel aktiviert. CFI des Systems ist standardmäßig aktiviert, Sie müssen jedoch Kernel-CFI aktivieren.
Das CFI von LLVM erfordert eine Kompilierung mit Optimierung der Verknüpfungszeit (LTO) LTO behält die LLVM-Bitcode-Darstellung von Objektdateien bei, bis Link-Zeit, wodurch der Compiler besser einordnen kann, welche Optimierungen durchgeführt werden kann. Durch die Aktivierung von LTO verkleinert sich die endgültige Binärdatei und die Kompilierungszeit erhöht. Bei Tests auf Android wurde die Kombination der LTO und CFI führt zu einem geringen Mehraufwand für Codegröße und -leistung; in einem in einigen Fällen besser.
Weitere technische Details zum CFI und zu anderen Forward-Control-Prüfungen finden Sie im LLVM-Design Dokumentation.
Beispiele und Quelle
CFI wird vom Compiler bereitgestellt und fügt währenddessen der Binärdatei eine Instrumentierung hinzu. der Kompilierungszeit. Wir unterstützen CFI in der Clang-Toolchain und dem Android-Build-System bei AOSP.
CFI ist für Arm64-Geräte standardmäßig für die Komponenten in
/platform/build/target/product/cfi-common.mk
Es wird auch direkt in einer Reihe von Medienkomponenten aktiviert. Makefiles/Entwurf
Dateien, z. B. /platform/frameworks/av/media/libmedia/Android.bp
und /platform/frameworks/av/cmds/stagefright/Android.mk
.
System-CFI implementieren
CFI ist standardmäßig aktiviert, wenn Sie Clang und das Android-Build-System verwenden. Da CFI zum Schutz von Android-Nutzern beiträgt, sollten Sie es nicht deaktivieren.
Wir empfehlen Ihnen dringend, CFI für zusätzliche Komponenten zu aktivieren. Idealerweise bieten wir privilegierten nativen Code oder nativen Code, der die Eingabe eines nicht vertrauenswürdigen Nutzers. Wenn Sie Clang und das Android-Build-System verwenden, können Sie CFI in neuen Komponenten aktivieren, indem Sie Ihren Makefiles ein paar Zeilen hinzufügen oder Blueprint-Dateien.
CFI in Makefiles unterstützen
So aktivieren Sie CFI in einer Erstellungsdatei wie /platform/frameworks/av/cmds/stagefright/Android.mk
:
Hinzufügen:
LOCAL_SANITIZE := cfi # Optional features LOCAL_SANITIZE_DIAG := cfi LOCAL_SANITIZE_BLACKLIST := cfi_blacklist.txt
LOCAL_SANITIZE
gibt CFI als Desinfektionsmittel während des folgenden Zeitraums an: erstellen.LOCAL_SANITIZE_DIAG
aktiviert den Diagnosemodus für CFI. Der Diagnosemodus gibt während des Vorgangs zusätzliche Debug-Informationen in Logcat aus Abstürze. Dies ist nützlich, wenn Sie Builds entwickeln und testen. Marke Allerdings solltest du den Diagnosemodus bei Produktions-Builds entfernen.- Mit
LOCAL_SANITIZE_BLACKLIST
können Komponenten selektiv CFI-Instrumentierung für einzelne Funktionen oder Quelldateien deaktivieren Ich können Sie die schwarze Liste als letzte Möglichkeit verwenden, die sonst existieren könnten. Weitere Informationen finden Sie unter CFI deaktivieren
CFI in Blueprint-Dateien unterstützen
So aktivieren Sie CFI in einer Blueprint-Datei wie /platform/frameworks/av/media/libmedia/Android.bp
:
Hinzufügen:
sanitize: { cfi: true, diag: { cfi: true, }, blacklist: "cfi_blacklist.txt", },
Fehlerbehebung
Wenn Sie CFI in neuen Komponenten aktivieren, können unter Umständen Probleme mit Fehler bei nicht übereinstimmenden Funktionstypen und Abweichung beim Assembly-Codetyp Fehler.
Fehler mit nicht übereinstimmenden Funktionstypen treten auf, weil CFI indirekte Aufrufe auf zu Funktionen wechseln, die denselben dynamischen Typ haben wie der statische Typ, der im anrufen. CFI schränkt Funktionsaufrufe virtueller und nicht virtueller Mitglieder ein, sodass nur der Wechsel zu Objekten, bei denen es sich um eine abgeleitete Klasse des statischen Typs des Objekts handelt, das für den Anruf zu starten. Wenn Sie also Code haben, der gegen eines dieser Annahmen getroffen haben, wird die von CFI hinzugefügte Instrumentierung abbrechen. Beispiel: Der Parameter Der Stacktrace zeigt einen SIGABRT und Logcat enthält eine Zeile zum Kontrollfluss eine Abweichung gefunden.
Um dieses Problem zu beheben, muss die aufgerufene Funktion denselben Typ haben, der statisch deklariert. Hier sind zwei Beispiel-CLs:
- Bluetooth: /c/platform/system/bt/+/532377
- NFC: /c/platform/system/nfc/+/527858
Ein weiteres mögliches Problem ist der Versuch, CFI in Code zu aktivieren, der indirekte für Assembly aufrufen. Da Assembly-Code nicht typisiert ist, führt dies zu einem Typ nicht übereinstimmend.
Um dieses Problem zu beheben, erstellen Sie native Code-Wrapper für jeden Assembly-Aufruf und geben Sie dem Wrapper für dieselbe Funktionssignatur wie der aufrufende Poiner. Der Wrapper kann dann Assembly-Code direkt aufrufen. Da direkte Zweige nicht durch CFI (sie können zur Laufzeit nicht geändert werden und stellen daher kein Sicherheitsrisiko dar) um das Problem zu beheben.
Wenn es zu viele Assembly-Funktionen gibt und nicht alle behoben werden können, können Sie Setzen Sie außerdem alle Funktionen auf die schwarze Liste, die indirekte Aufrufe an Assembly enthalten. Dies ist nicht empfohlen, da dadurch CFI-Prüfungen für diese Funktionen deaktiviert werden. Angriffsfläche.
CFI deaktivieren
Der Leistungsaufwand wurde nicht beobachtet. Daher sollten Sie die Funktion CFI. Sollten sich die Auswirkungen auf die Nutzer auswirken, können Sie das CFI jedoch selektiv deaktivieren. für einzelne Funktionen oder Quelldateien, indem Sie eine schwarze Liste mit Sanitizer-Dateien bereitstellen zur Kompilierungszeit. Die schwarze Liste weist den Compiler an, CFI zu deaktivieren. an bestimmten Orten.
Das Android-Build-System unterstützt komponentenspezifische schwarze Listen (sodass Sie können Quelldateien oder einzelne Funktionen auswählen, die kein CFI erhalten sollen. Instrumentierung) sowohl für Make als auch für Soong. Weitere Informationen zum Format eines schwarze Liste enthält, sehen Sie sich die vorgelagerten Clang-Dokumente
Zertifizierungsstufe
Derzeit gibt es keinen speziellen CTS-Test für CFI. Stellen Sie stattdessen sicher, CTS-Tests sind mit oder ohne aktiviertem CFI bestanden, um zu prüfen, ob CFI keine Auswirkungen hat auf dem Gerät.