Scudo ist ein dynamischer Arbeitsspeicherzuweiser im Nutzermodus oder Heap-Zuweiser, der so konzipiert ist, dass er widerstandsfähig gegen Heap-bezogene Schwachstellen (z. B. Heap-basierte Puffer überläufe, Use-After-Free-, und Double-Free-Fehler) ist und gleichzeitig die Leistung beibehält. Er bietet die Standard-C-Zuweisungs- und Freigabeprimitive (z. B. malloc und free) sowie die C++-Primitive (z. B. new und delete).
Scudo ist eher eine Mitigation als ein vollwertiger Arbeitsspeicherfehler Detektor wie AddressSanitizer (ASan).
Seit der Veröffentlichung von Android 11 wird Scudo für den gesamten nativen Code verwendet (außer auf Geräten mit wenig Arbeitsspeicher, auf denen weiterhin jemalloc verwendet wird). Zur Laufzeit werden alle nativen Heap-Zuweisungen und -Freigaben von Scudo für alle ausführbaren Dateien und ihre Bibliotheksabhängigkeiten verarbeitet. Der Prozess wird abgebrochen, wenn eine Beschädigung oder ein verdächtiges Verhalten im Heap erkannt wird.
Scudo ist Open Source und Teil des Compiler-rt-Projekts von LLVM. Die Dokumentation ist unter https://llvm.org/docs/ScudoHardenedAllocator.html verfügbar. Die Scudo-Laufzeit wird als Teil der Android-Toolchain ausgeliefert. Soong und Make wurden um Unterstützung erweitert, um die einfache Aktivierung des Zuweisers in einer Binärdatei zu ermöglichen.
Sie können zusätzliche Mitigationen im Zuweiser mit den unten beschriebenen Optionen aktivieren oder deaktivieren.
Anpassung
Einige Parameter des Zuweisers können pro Prozess auf verschiedene Arten definiert werden:
- Statisch:Definieren Sie im Programm eine Funktion
__scudo_default_options, die die zu parsende Optionszeichenfolge zurückgibt. Diese Funktion muss den folgenden Prototyp haben:extern "C" const char *__scudo_default_options(). - Dynamisch:Verwenden Sie die Umgebungsvariable
SCUDO_OPTIONSmit der zu parsende Optionszeichenfolge. Auf diese Weise definierte Optionen überschreiben alle Definitionen, die über__scudo_default_optionsvorgenommen wurden.
Die folgenden Optionen sind verfügbar.
| Option | Standardwert für 64-Bit | Standardwert für 32-Bit | Beschreibung |
|---|---|---|---|
QuarantineSizeKb |
256 |
64 |
Die Größe (in KB) der Quarantäne, mit der die tatsächliche Freigabe von Chunks verzögert wird. Ein niedrigerer Wert kann die Arbeitsspeichernutzung reduzieren, aber die Wirksamkeit der Mitigation verringern. Bei einem negativen Wert werden die Standardwerte verwendet. Wenn Sie sowohl diese als auch ThreadLocalQuarantineSizeKb auf null setzen, wird die Quarantäne vollständig deaktiviert. |
QuarantineChunksUpToSize |
2048 |
512 |
Die Größe (in Byte), bis zu der Chunks in Quarantäne gestellt werden können. |
ThreadLocalQuarantineSizeKb |
64 |
16 |
Die Größe (in KB) des Cache pro Thread, mit dem die globale Quarantäne ausgelagert wird.
Ein niedrigerer Wert kann die Arbeitsspeichernutzung reduzieren, aber die Konflikte in der globalen Quarantäne erhöhen. Wenn Sie sowohl diese als auch QuarantineSizeKb auf null setzen, wird die Quarantäne vollständig deaktiviert. |
DeallocationTypeMismatch |
false |
false |
Aktiviert die Fehlerberichterstattung für malloc/delete, new/free, new/delete[] |
DeleteSizeMismatch |
true |
true |
Aktiviert die Fehlerberichterstattung bei Abweichungen zwischen den Größen von „new“ und „delete“. |
ZeroContents |
false |
false |
Aktiviert das Löschen von Chunk-Inhalten bei der Zuweisung und Freigabe. |
allocator_may_return_null |
false |
false |
Gibt an, dass der Zuweiser bei einem behebbaren Fehler „null“ zurückgeben kann, anstatt den Prozess zu beenden. |
hard_rss_limit_mb |
0 |
0 |
Wenn der RSS des Prozesses dieses Limit erreicht, 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-Zuweiser. 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 an 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. |
Validierung
Derzeit gibt es keine CTS-Tests speziell für Scudo. Achten Sie stattdessen darauf, dass die CTS-Tests mit oder ohne aktiviertem Scudo für eine bestimmte Binärdatei bestanden werden, um zu prüfen, ob dies Auswirkungen auf das Gerät hat.
Fehlerbehebung
Wenn ein nicht behebbares Problem erkannt wird, zeigt der Zuweiser eine Fehlermeldung für den Standardfehlerdeskriptor an und beendet dann den Prozess.
Stacktraces, die zur Beendigung führen, werden im Systemlog hinzugefügt.
Die Ausgabe beginnt in der Regel mit Scudo ERROR: gefolgt von einer kurzen Zusammenfassung des Problems und allen Hinweisen.
Hier ist 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 folgenden Gründe: Der Header wurde überschrieben (teilweise oder vollständig) oder der an die Funktion übergebene Pointer ist kein Chunk.race on chunk header: Zwei verschiedene Threads versuchen gleichzeitig, denselben Header zu bearbeiten. Dies ist in der Regel ein Symptom für eine Race-Condition oder einen allgemeinen Mangel an Sperren bei der Ausführung von Vorgängen für diesen Chunk.invalid chunk state: Der Chunk befindet sich für einen bestimmten Vorgang nicht im erwarteten Zustand. Er ist beispielsweise nicht zugewiesen, wenn versucht wird, ihn freizugeben, oder er befindet sich nicht in Quarantäne, wenn versucht wird, ihn wiederzuverwenden. Ein Double-Free-Fehler ist die typische Ursache für diesen Fehler.misaligned pointer: Die grundlegenden Ausrichtungsanforderungen werden streng durchgesetzt: 8 Byte auf 32-Bit-Plattformen und 16 Byte auf 64-Bit-Plattformen. Wenn ein an unsere Funktionen übergebener Pointer nicht diesen Anforderungen entspricht, ist der an eine der Funktionen übergebene Pointer nicht ausgerichtet.allocation type mismatch: Wenn diese Option aktiviert ist, muss eine Freigabefunktion, die für einen Chunk aufgerufen wird, mit dem Typ der Funktion übereinstimmen, die zum Zuweisen des Chunks aufgerufen wurde. Diese Art von Abweichung kann Sicherheitsprobleme verursachen.invalid sized delete: Wenn der C++14-Operator „sized delete“ verwendet wird und die optionale Prüfung aktiviert ist, gibt es eine Abweichung zwischen der Größe, die beim Freigeben eines Chunks übergeben wurde, und der Größe, die beim Zuweisen angefordert wurde. Dies ist in der Regel ein Compilerproblem oder eine Typverwechslung für das freigegebene Objekt.RSS limit exhausted: Das optional angegebene maximale RSS wurde überschritten.
Wenn Sie einen Absturz im Betriebssystem selbst debuggen, können Sie einen HWASan-OS-Build verwenden. Wenn Sie einen Absturz in einer App debuggen, können Sie auch einen HWASan-App-Build verwenden.