AddressSanitizer Runtime

Die AddressSanitizer-Laufzeitbibliothek fängt allgemeine Speicherbelegungsfunktionen und -vorgänge ab, um die Überprüfung von Speicherzugriffen zu ermöglichen. Es gibt mehrere verschiedene Laufzeitbibliotheken, die die verschiedenen Typen von ausführbaren Dateien unterstützen, die der Compiler möglicherweise generiert. Compiler und Linker verknüpfen automatisch die entsprechenden Laufzeitbibliotheken, solange Sie die /fsanitize=address Option zur Kompilierzeit übergeben. Sie können das Standardverhalten überschreiben, indem Sie die /NODEFAULTLIB Option zur Linkzeit verwenden. Weitere Informationen finden Sie im Abschnitt zum Verknüpfen in der Referenz zur Sprache AddressSanitizer, zum Erstellen und Debuggen.

Im Folgenden finden Sie eine Inventur der Laufzeitbibliotheken zum Verknüpfen mit der AddressSanitizer-Runtime, wobei {arch} entweder i386 oder x86_64ist.

Hinweis

Diese Bibliotheken behalten die Clang-Konventionen für Architekturnamen bei. Die MSVC-Konventionen sind normalerweise x86 und x64 statt i386 und x86_64. Sie beziehen sich auf die gleichen Architekturen.

CRT-Option DLL oder EXE DEBUGGEN? Binärbibliotheken der AddressSanitizer-Runtime
MT EXE Nein clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch}
MT DLL Nein clang_rt.asan_dll_thunk-{arch}
MD ENTWEDER Nein clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch}
MT EXE YES clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch}
MT DLL YES clang_rt.asan_dbg_dll_thunk-{arch}
MD ENTWEDER YES clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch}

Beim Kompilieren mit cl /fsanitize=addressgeneriert der Compiler Anweisungen zum Verwalten und Überprüfen der Schattenbytes. Ihr Programm verwendet diese Instrumentierung, um Speicherzugriffe auf dem Stapel, im Heap oder im globalen Bereich zu überprüfen. Der Compiler erstellt auch Metadaten, die Stapel- und globale Variablen beschreiben. Mit diesen Metadaten kann die Runtime präzise Fehlerdiagnosen generieren: Funktionsnamen, Zeilen und Spalten im Quellcode. In Kombination können die Compilerüberprüfungen und Laufzeitbibliotheken viele Arten von Speichersicherheitsfehlern präzise diagnostizieren, wenn sie zur Laufzeit auftreten.

Funktionsüberwachung

Der AddressSanitizer erreicht das Abfangen von Funktionen durch viele Hot-Patching-Techniken. Diese Techniken werden am besten im Quellcode selbst dokumentiert.

Die Laufzeitbibliotheken fangen viele gängige Speicherverwaltungs- und Speicherbearbeitungsfunktionen ab. Eine Liste finden Sie unter AddressSanitizer-Liste der abgefangenen Funktionen. Die Zuordnungs-Interceptors verwalten Metadaten und Schattenbytes im Zusammenhang mit jedem Zuordnungsaufruf. Jedes Mal, wenn eine CRT-Funktion wie malloc oder delete aufgerufen wird, legen die Interceptors bestimmte Werte im Schattenspeicherbereich von AddressSanitizer fest, um anzugeben, ob auf diese Heapstandorte derzeit zugegriffen werden kann und welche Grenzen die Zuordnung aufweist. Mit diesen Schattenbytes können die vom Compiler generierten Überprüfungen der Schattenbytes bestimmen, ob eine Last oder ein Speicher gültig ist.

Es ist nicht garantiert, dass die Überwachung erfolgreich ist. Wenn ein Funktionsprolog zu kurz ist, um geschrieben jmp zu werden, kann das Abfangen fehlschlagen. Wenn ein Abfangfehler auftritt, löst das Programm ein aus debugbreak und wird angehalten. Wenn Sie einen Debugger anfügen, wird die Ursache des Abhörproblems behoben. Wenn sie dieses Problem haben, melden Sie einen Fehler.

Hinweis

Benutzer können optional versuchen, nach einem fehlgeschlagenen Abfangen fortzufahren, indem sie die Umgebungsvariable ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE auf einen beliebigen Wert festlegen. Wenn Sie nach einem Abhörfehler fortfahren, können Fehlerberichte für diese Funktion verpasst werden.

Benutzerdefinierte Zuweisungen und die AddressSanitizer-Runtime

Die AddressSanitizer-Runtime bietet Interceptors für allgemeine Zuordnungsschnittstellen, malloc/free, new/delete,/HeapFreeHeapAlloc(über ).RtlAllocateHeap/RtlFreeHeap Viele Programme verwenden benutzerdefinierte Zuweisungen aus dem einen oder anderen Grund, ein Beispiel wäre jedes Programm, dlmalloc das oder eine Lösung verwendet, die die std::allocator Schnittstelle und verwendet VirtualAlloc(). Der Compiler kann einem benutzerdefinierten Zuweisungsgeber keine automatischen Aufrufe zur Schattenspeicherverwaltung hinzufügen. Es liegt in der Verantwortung des Benutzers, die bereitgestellte manuelle Vergiftungsschnittstelle zu verwenden. Diese API ermöglicht es diesen Zuweisungen, ordnungsgemäß mit den vorhandenen AddressSanitizer-Runtime- und Schattenbytekonventionen zu funktionieren.

Manuelle AddressSanitizer-Vergiftungsschnittstelle

Die Benutzeroberfläche zum Aufklären ist einfach, erzwingt dem Benutzer jedoch Ausrichtungseinschränkungen. Benutzer können diese Prototypen importieren, indem sie importieren sanitizer/asan_interface.h. Hier sind die Prototypen der Schnittstellenfunktion:

void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);

Der Einfachheit halber stellt die Headerdatei der AddressSanitizer-Schnittstelle Wrappermakros bereit. Diese Makros überprüfen, ob die AddressSanitizer-Funktionalität während der Kompilierung aktiviert ist. Sie ermöglichen es Ihrem Quellcode, die Aufrufe der Vergiftungsfunktion auszulassen, wenn sie nicht benötigt werden. Diese Makros sollten gegenüber dem direkten Aufrufen der oben genannten Funktionen bevorzugt werden:

#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)

Ausrichtungsanforderungen für AddressSanitizer-Vergiftung

Bei jeder manuellen Vergiftung von Schattenbytes müssen die Ausrichtungsanforderungen berücksichtigt werden. Der Benutzer muss bei Bedarf Auffüllungen hinzufügen, damit die Schattenbytes auf einer Bytegrenze im Schattenspeicher enden. Jedes Bit im AddressSanitizer-Schattenspeicher codiert den Zustand eines einzelnen Byte im Arbeitsspeicher der Anwendung. Diese Codierung bedeutet, dass die Gesamtgröße jeder Zuordnung, einschließlich aller Auffüllungen, an einer 8-Byte-Grenze ausgerichtet sein muss. Wenn die Ausrichtungsanforderung nicht erfüllt ist, kann dies zu einer falschen Fehlerberichterstattung führen. Die falsche Berichterstellung kann sich als fehlende Berichte (false negatives) oder Berichte über Nichtfehler (false-positives) manifestieren.

Eine Veranschaulichung der Ausrichtungsanforderungen und potenzieller Probleme finden Sie in den bereitgestellten ASan-Ausrichtungsbeispielen. Eines ist ein kleines Programm, um zu zeigen, was bei einer manuellen Schattenspeichervergiftung schief gehen kann. Die zweite ist eine Beispielimplementierung der manuellen Vergiftung mithilfe der std::allocator Schnittstelle.

Laufzeitoptionen

Microsoft C/C++ (MSVC) verwendet eine Laufzeit, die auf der Clang AddressSanitizer-Runtime aus dem llvm-project-Repository basiert. Aus diesem Gründen werden die meisten Laufzeitoptionen zwischen den beiden Versionen gemeinsam genutzt. Eine vollständige Liste der öffentlichen Clang-Laufzeitoptionen finden Sie hier. Wir dokumentieren einige Unterschiede in den folgenden Abschnitten. Wenn Sie Optionen ermitteln, die nicht wie erwartet funktionieren, melden Sie einen Fehler.

Nicht unterstützte AddressSanitizer-Optionen

  • detect_container_overflow
  • unmap_shadow_on_exit

Hinweis

Die Laufzeitoption halt_on_error AddressSanitizer funktioniert nicht wie erwartet. Sowohl in den Clang- als auch in den MSVC-Laufzeitbibliotheken gelten viele Fehlertypen als nicht kontinuierlich, einschließlich der meisten Fehler bei Speicherbeschädigungen.

Weitere Informationen finden Sie im Abschnitt Unterschiede mit Clang 12.0 .

MSVC-spezifische AddressSanitizer-Laufzeitoptionen

  • windows_hook_legacy_allocatorsBoolesch, legen Sie auf festtrue, um das Abfangen von und LocalAlloc Zuteilungen GlobalAlloc zu ermöglichen.

Hinweis

Die Option windows_hook_legacy_allocators war in der öffentlichen llvm-project-Runtime nicht verfügbar, als dieser Artikel geschrieben wurde. Die Option kann schließlich in das öffentliche Projekt zurückgebracht werden; Dies hängt jedoch von der Codeüberprüfung und der Akzeptanz der Community ab.

Die Option windows_hook_rtl_allocators, die zuvor ein Opt-In-Feature war, während AddressSanitizer experimentell war, ist jetzt standardmäßig aktiviert.

  • iat_overwrite Zeichenfolge, standardmäßig auf "error" festgelegt. Weitere mögliche Werte sind "protect" und "ignore". Einige Module können andere import address table Module überschreiben, um Implementierungen bestimmter Funktionen anzupassen. Treiber bieten beispielsweise häufig benutzerdefinierte Implementierungen für bestimmte Hardware. Die iat_overwrite Option verwaltet den Schutz der AddressSanitizer-Runtime vor Überschreibungen für bestimmte memoryapi.h Funktionen. Die Runtime verfolgt derzeit die VirtualAllocFunktionen , VirtualProtectund VirtualQuery zum Schutz nach. Diese Option ist in Visual Studio 2022, Version 17.5 Preview 1 und höher verfügbar. Die folgenden iat_overwrite Werte steuern, wie die Runtime reagiert, wenn geschützte Funktionen überschrieben werden:

    • Wenn auf "error" (Standard) festgelegt ist, meldet die Runtime einen Fehler, wenn ein Überschreiben erkannt wird.
    • Wenn auf "protect"festgelegt ist, versucht die Laufzeit, die Verwendung der überschriebenen Definition zu vermeiden, und fährt fort. Effektiv wird die ursprüngliche memoryapi Definition der Funktion innerhalb der Laufzeit verwendet, um unendliche Rekursionen zu vermeiden. Andere Module im Prozess verwenden weiterhin die überschriebene Definition.
    • Wenn auf "ignore"festgelegt ist, versucht die Runtime nicht, überschriebene Funktionen zu korrigieren, und fährt mit der Ausführung fort.

AddressSanitizer-Liste der abgefangenen Funktionen (Windows)

Die AddressSanitizer-Runtime stellt viele Funktionen zur Aktivierung von Speichersicherheitsprüfungen zur Laufzeit bereit. Im Folgenden finden Sie eine nicht vollständige Liste der Funktionen, die die AddressSanitizer-Runtime überwacht.

Standard-Interceptors

Optionale Interceptors

Die hier aufgeführten Interceptors werden nur installiert, wenn eine AddressSanitizer-Laufzeitoption aktiviert ist. Legen Sie auf fest windows_hook_legacy_allocatorstrue , um das Abfangen von Legacyzuteilungen zu aktivieren. set ASAN_OPTIONS=windows_hook_legacy_allocators=true

Weitere Informationen

Übersicht über AddressSanitizer
Bekannte Probleme von AddressSanitizer
Kompilierungs- und Sprachreferenz für AddressSanitizer
AddressSanitizer-Schattenbytes
AddressSanitizer-Tests in der Cloud oder verteilten Umgebungen
Integration des AddressSanitizer-Debuggers
AddressSanitizer-Fehlerbeispiele