Scudo

Scudo ist ein dynamischer Speicherallokator im Nutzermodus oder Heap-Allokator, der für eine hohe Widerstandsfähigkeit gegen heapbezogene Sicherheitslücken (z. B. heapbasierten Pufferüberlauf, Nutzung nach Freigabe und Doppelfreigabe) entwickelt wurde und gleichzeitig eine hohe Leistung bietet. Es bietet die standardmäßigen C-Primitive zur Speicherzuweisung und ‑entfernung (z. B. malloc und free) sowie die C++-Primitive (z. B. new und delete).

Scudo dient eher zur Entschärfung als ein vollwertiger Speicherfehlerdetektor wie AddressSanitizer (ASan).

Seit der Veröffentlichung von Android 11 wird scudo für den gesamten nativen Code verwendet, mit Ausnahme von Geräten mit wenig Arbeitsspeicher, auf denen weiterhin jemalloc verwendet wird. Zur Laufzeit werden alle nativen Heap-Zuweisungen und Deallocations von Scudo für alle ausführbaren Dateien und ihre Bibliotheksabhängigkeiten bereitgestellt. Der Prozess wird abgebrochen, wenn eine Beschädigung oder ein verdächtiges Verhalten im Heap erkannt wird.

Scudo ist Open Source und Teil des LLVM-Compiler-RT-Projekts. Die Dokumentation steht unter https://llvm.org/docs/ScudoHardenedAllocator.html zur Verfügung. Die Scudo-Laufzeit wird als Teil der Android-Toolchain ausgeliefert. Soong und Make wurden unterstützt, um den Allocator in einem Binärprogramm einfach aktivieren zu können.

Mit den unten beschriebenen Optionen können Sie zusätzliche Maßnahmen zur Risikominderung im Allocator aktivieren oder deaktivieren.

Personalisierung

Einige Parameter des Allocators können auf prozessspezifische Weise definiert werden:

  • Statisch:Definieren Sie im Programm eine __scudo_default_options-Funktion, die den zu analysierenden Optionsstring zurückgibt. Diese Funktion muss den folgenden Prototyp haben: extern "C" const char *__scudo_default_options().
  • Dynamisch:Verwenden Sie die Umgebungsvariable SCUDO_OPTIONS mit dem zu parsenden Optionsstring. So definierte Optionen überschreiben alle Definitionen, die über __scudo_default_options vorgenommen wurden.

Folgende Optionen sind verfügbar.

Option 64-Bit-Standard 32-Bit-Standard Beschreibung
QuarantineSizeKb 256 64 Die Größe (in KB) der Quarantäne, mit der die tatsächliche Deaktivierung von Chunks verzögert wird. Ein niedrigerer Wert kann die Arbeitsspeichernutzung reduzieren, aber die Wirksamkeit der Abschwächung verringern. Bei einem negativen Wert werden die Standardeinstellungen verwendet. Wenn Sie sowohl diesen Wert als auch ThreadLocalQuarantineSizeKb auf null setzen, wird die Quarantäne vollständig deaktiviert.
QuarantineChunksUpToSize 2048 512 Die Größe (in Byte), bis zu der Blöcke unter Quarantäne gestellt werden können.
ThreadLocalQuarantineSizeKb 64 16 Die Größe (in KB) des pro Thread verwendeten Caches, um die globale Quarantäne zu entlasten. Ein niedrigerer Wert kann die Arbeitsspeichernutzung reduzieren, aber die Zugriffskonflikte in der globalen Quarantäne erhöhen. Wenn Sie sowohl diesen Wert als auch QuarantineSizeKb auf null setzen, wird die Quarantäne vollständig deaktiviert.
DeallocationTypeMismatch false false Aktiviert die Fehlerberichte für malloc/delete, new/free und new/delete[].
DeleteSizeMismatch true true Aktiviert Fehlerberichte zu Abweichungen zwischen neuen und gelöschten Größen.
ZeroContents false false Ermöglicht Null-Chunk-Inhalte bei der Zuweisung und Deaktivierung.
allocator_may_return_null false false Gibt an, dass der Allocator null zurückgeben kann, wenn ein wiederherstellbarer Fehler auftritt, anstatt den Prozess zu beenden.
hard_rss_limit_mb 0 0 Wenn die RSS-Feeds des Prozesses diesen Grenzwert erreichen, wird der Prozess beendet.
soft_rss_limit_mb 0 0 Wenn der RSS des Prozesses dieses Limit erreicht, schlagen weitere Zuweisungen fehl oder geben null zurück (je nach Wert von allocator_may_return_null), bis der RSS wieder sinkt und neue Zuweisungen möglich sind.
allocator_release_to_os_interval_ms 5000 Betrifft nur einen 64‑Bit-Allocator. Wenn diese Option festgelegt ist, wird versucht, nicht verwendeten Arbeitsspeicher an das Betriebssystem freizugeben, jedoch nicht häufiger als in diesem Intervall (in Millisekunden). Wenn der Wert negativ ist, wird kein Arbeitsspeicher für das Betriebssystem freigegeben.
abort_on_error true true Wenn diese Option festgelegt ist, ruft das Tool nach dem Drucken der Fehlermeldung abort() anstelle von _exit() auf.

Zertifizierungsstufe

Derzeit gibt es keine speziellen CTS-Tests für Scudo. Achten Sie stattdessen darauf, dass die CTS-Tests für ein bestimmtes Binärprogramm mit oder ohne aktiviertem Scudo bestehen, um sicherzustellen, dass es keine Auswirkungen auf das Gerät hat.

Fehlerbehebung

Wenn ein nicht wiederherstellbares Problem erkannt wird, zeigt der Allocator eine Fehlermeldung im Standardfehler-Descriptor an und beendet dann den Prozess. Stack-Traces, die zur Beendigung führen, werden dem Systemprotokoll hinzugefügt. Die Ausgabe beginnt in der Regel mit Scudo ERROR:, gefolgt von einer kurzen Zusammenfassung des Problems und gegebenenfalls Hinweisen.

Hier finden Sie eine Liste der aktuellen Fehlermeldungen und ihrer möglichen Ursachen:

  • corrupted chunk header: Die Prüfsummenüberprüfung des Chunk-Headers ist fehlgeschlagen. Das liegt wahrscheinlich an einem der beiden folgenden Gründe: Der Header wurde (teilweise oder vollständig) überschrieben oder der an die Funktion übergebene Zeiger ist kein Chunk.
  • race on chunk header: Zwei verschiedene Threads versuchen, dieselbe Überschrift gleichzeitig zu manipulieren. Dies ist in der Regel ein Symptom für einen Race-Condition oder einen allgemeinen Mangel an Sperren bei Vorgängen auf diesem Chunk.
  • invalid chunk state: Der Chunk befindet sich nicht im erwarteten Status für einen bestimmten Vorgang. Beispiel: Er wird nicht zugewiesen, wenn versucht wird, ihn freizugeben, oder er wird nicht unter Quarantäne gestellt, wenn versucht wird, ihn zu recyceln. Eine doppelte Freigabe ist der typische Grund für diesen Fehler.
  • misaligned pointer: Die Anforderungen an die Grundausrichtung werden streng erzwungen: 8 Byte auf 32-Bit-Plattformen und 16 Byte auf 64-Bit-Plattformen. Wenn ein an unsere Funktionen übergebener Zeiger nicht zu diesen passt, ist der an eine der Funktionen übergebene Zeiger nicht ausgerichtet.
  • allocation type mismatch: Wenn diese Option aktiviert ist, muss die Dealokationsfunktion, die für einen Block aufgerufen wird, mit der Funktion übereinstimmen, die zum Zuweisen des Blocks aufgerufen wurde. Diese Art von Abweichung kann zu Sicherheitsproblemen führen.
  • invalid sized delete: Wenn der C++14-Operator „delete“ mit Größe verwendet wird und die optionale Prüfung aktiviert ist, stimmt die Größe, die beim Freigeben eines Chunks übergeben wurde, nicht mit der Größe überein, die beim Zuweisen angefordert wurde. Dies ist in der Regel ein Compilerproblem oder eine Typverwechslung beim Objekt, das deallociert wird.
  • RSS limit exhausted: Der optional angegebene maximale RSS wurde überschritten.

Wenn Sie einen Absturz im Betriebssystem selbst beheben möchten, können Sie einen HWASan-Betriebssystem-Build verwenden. Wenn Sie einen Absturz in einer App debuggen, können Sie auch einen HWASan-Anwendungs-Build verwenden.