Scudo ist ein dynamischer Arbeitsspeicher-Allocator im Nutzermodus oder Heap-Allocator, der so konzipiert ist, dass er widerstandsfähig gegen Heap-bezogene Sicherheitslücken wie Heap-basierte Pufferüberläufe, Use-After-Free und Double-Free ist und gleichzeitig die Leistung beibehält. Sie bietet die standardmäßigen C-Primitive für die Zuweisung und Freigabe (z. B. malloc und free) sowie die C++-Primitive (z. B. new und delete).
Scudo ist eher eine Maßnahme zur Risikominderung 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 für die einfache Aktivierung des Allocators in einem Binärprogramm erweitert.
Mit den unten beschriebenen Optionen können Sie zusätzliche Maßnahmen zur Risikominderung im Zuweisungstool aktivieren oder deaktivieren.
Personalisierung
Einige Parameter des Allocators können pro Prozess auf verschiedene Arten definiert werden:
- Statisch:Definieren Sie im Programm eine
__scudo_default_options
-Funktion, die den zu parsenden Optionsstring zurückgibt. Diese Funktion muss den folgenden Prototyp haben:extern "C" const char *__scudo_default_options()
. - Dynamisch:Verwenden Sie die Umgebungsvariable
SCUDO_OPTIONS
, die den zu parsenden Optionsstring enthält. Auf diese Weise 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, die verwendet wird, um die tatsächliche Freigabe von Chunks zu verzögern. Ein niedrigerer Wert kann die Arbeitsspeichernutzung verringern, aber die Wirksamkeit der Maßnahme beeinträchtigen. Bei einem negativen Wert werden die Standardeinstellungen verwendet. Wenn Sie sowohl diesen 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 unter Quarantäne gestellt werden können. |
ThreadLocalQuarantineSizeKb |
64 |
16 |
Die Größe (in KB) der Cache-Nutzung pro Thread zum Auslagern der globalen Quarantäne.
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 und new/delete[] |
DeleteSizeMismatch |
true |
true |
Aktiviert die Fehlerberichterstattung bei Größenabweichungen zwischen neuen und gelöschten Elementen. |
ZeroContents |
false |
false |
Ermöglicht das Löschen von Chunk-Inhalten bei der Zuweisung und Freigabe. |
allocator_may_return_null |
false |
false |
Gibt an, dass der Zuweisungsoperator „null“ zurückgeben kann, wenn ein behebbarer Fehler auftritt, 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-Allocator. Wenn festgelegt, wird versucht, ungenutzten Speicher an das Betriebssystem freizugeben, jedoch nicht häufiger als in diesem Intervall (in Millisekunden). Wenn der Wert negativ ist, wird kein Speicher für das Betriebssystem freigegeben. |
abort_on_error |
true |
true |
Wenn festgelegt, ruft das Tool nach dem Ausgeben der Fehlermeldung abort() anstelle von _exit() auf. |
Zertifizierungsstufe
Derzeit gibt es keine CTS-Tests speziell für Scudo. Stellen Sie stattdessen sicher, dass CTS-Tests mit oder ohne aktiviertes Scudo für ein bestimmtes Binärprogramm bestanden werden, um zu prüfen, ob es sich auf das Gerät auswirkt.
Fehlerbehebung
Wenn ein nicht behebbares Problem erkannt wird, gibt der Allocator eine Fehlermeldung an den Standardfehlerdeskriptor aus und beendet dann den Prozess.
Stacktraces, die zum Beenden führen, werden dem Systemprotokoll hinzugefügt.
Die Ausgabe beginnt in der Regel mit Scudo ERROR:
, gefolgt von einer kurzen Zusammenfassung des Problems und allen 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 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, denselben Header gleichzeitig zu bearbeiten. Dies ist in der Regel ein Symptom für eine Race Condition oder einen allgemeinen Mangel an Sperren beim Ausführen von Vorgängen für diesen Chunk.invalid chunk state
: Der Chunk befindet sich für einen bestimmten Vorgang nicht im erwarteten Status. Er ist beispielsweise nicht zugewiesen, wenn versucht wird, ihn freizugeben, oder er befindet sich nicht in Quarantäne, wenn versucht wird, ihn wiederzuverwenden. Eine doppelte Freigabe ist die typische Ursache für diesen Fehler.misaligned pointer
: Die grundlegenden Anforderungen an die Ausrichtung werden streng durchgesetzt: 8 Byte auf 32-Bit-Plattformen und 16 Byte auf 64-Bit-Plattformen. Wenn ein an unsere Funktionen übergebener Zeiger nicht diesen Anforderungen entspricht, ist der an eine der Funktionen übergebene Zeiger nicht ausgerichtet.allocation type mismatch
: Wenn diese Option aktiviert ist, muss eine für einen Chunk aufgerufene Deallocation-Funktion dem Typ der Funktion entsprechen, die zum Zuweisen des Chunks aufgerufen wurde. Diese Art von Abweichung kann zu Sicherheitsproblemen führen.invalid sized delete
: Wenn der C++14-Operator „sized delete“ 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 für das freigegebene Objekt.RSS limit exhausted
: Der 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.