Runtime addressSanitizer

La libreria di runtime AddressSanitizer intercetta le funzioni e le operazioni comuni di allocazione della memoria per consentire l'ispezione degli accessi alla memoria. Esistono diverse librerie di runtime che supportano i vari tipi di eseguibili che il compilatore può generare. Il compilatore e il linker collegano automaticamente le librerie di runtime appropriate, purché passi l'opzione /fsanitize=address in fase di compilazione. È possibile eseguire l'override del comportamento predefinito usando l'opzione /NODEFAULTLIB in fase di collegamento. Per altre informazioni, vedere la sezione sul collegamento nel linguaggio AddressSanitizer, nella compilazione e nel debug di riferimento.

Durante la compilazione con cl /fsanitize=address, il compilatore genera istruzioni per gestire e controllare i byte shadow. Il programma usa questa strumentazione per controllare gli accessi alla memoria nello stack, nell'heap o nell'ambito globale. Il compilatore produce anche metadati che descrivono lo stack e le variabili globali. Questi metadati consentono al runtime di generare una diagnostica degli errori precisa: nomi di funzione, righe e colonne nel codice sorgente. In combinazione, i controlli del compilatore e le librerie di runtime possono diagnosticare con precisione molti tipi di bug di sicurezza della memoria se vengono rilevati in fase di esecuzione.

Di seguito è riportato l'elenco delle librerie di runtime per il collegamento al runtime AddressSanitizer, a partire da Visual Studio 17.7 Preview 3. Per altre informazioni sulle /MT opzioni (collegare in modo statico il runtime) e /MD (collegare dinamicamente le opzioni redist in fase di esecuzione), vedere /MD, /MT, /LD (Use Run-Time Library).

Nota

Nella tabella seguente è {arch} i386 o x86_64. Queste librerie usano convenzioni Clang per i nomi di architettura. Le convenzioni MSVC sono in genere x86 e anziché i386 e x86_64x64 , ma fanno riferimento alle stesse architetture.

Opzione CRT Libreria di runtime AddressSanitizer (.lib) File binario di runtime degli indirizzi (.dll)
/MT oppure /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD oppure /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

Il diagramma seguente mostra come le librerie di runtime del linguaggio sono collegate per le opzioni del /MTcompilatore , /MTd, /MDe /MDd :

Diagramma del modo in cui le librerie di runtime sono collegate per varie opzioni del compilatore.

L'immagine mostra tre scenari per il collegamento della libreria di runtime. Il primo è /MT o /MTd. My_exe.exe e my_dll.dll vengono entrambi visualizzati con le proprie copie dei runtime VCRuntime, Universal CRT e C++ collegati staticamente. Gli scenari mostrano /MD in cui my_exe.exe e my_dll.dll condividono vcruntime140.dll, ucrtbase.dll e msvcp140.dll. L'ultimo scenario mostra /MDd in cui sia my_exe.exe che my_dll.dll condividono le versioni di debug dei runtime: vcruntime140d.dll, ucrtbased.dll e msvcp140d.dll

Il diagramma seguente mostra come la libreria ASan è collegata per varie opzioni del compilatore:

Diagramma della modalità di collegamento della DLL di runtime ASan.

L'immagine mostra quattro scenari per il collegamento della libreria di runtime ASan. Gli scenari sono per /MT (collegare in modo statico il runtime), /MTd (collegare in modo statico il runtime di debug), /MD (collegare dinamicamente il redist in fase di esecuzione), /MDd (collegare dinamicamente il debug redist in fase di esecuzione). In tutti i casi, my_exe.exe collegamenti e i relativi associati my_dll.dll collegamento a una singola istanza di clang-rt.asan-dynamix-x86_64.dll.

Anche quando si esegue il collegamento statico, la DLL di runtime ASan deve essere presente in fase di esecuzione, a differenza di altri componenti di runtime C.

Versioni precedenti

Prima di Visual Studio 17.7 Preview 3, le compilazioni collegate staticamente (/MT o /MTd) non usava una dipendenza DLL. Al contrario, il runtime AddressSanitizer è stato collegato staticamente al file EXE dell'utente. I progetti DLL caricano quindi le esportazioni dal file EXE dell'utente per accedere alla funzionalità ASan.

I progetti collegati dinamicamente (/MD o /MDd) usavano librerie e DLL diverse a seconda che il progetto sia stato configurato per il debug o la versione. Per altre informazioni su queste modifiche e sulle relative motivazioni, vedere MSVC Address Sanitizer – One DLL for all Runtime Configurations (Sanificatori indirizzi MSVC - Una DLL per tutte le configurazioni di runtime).

La tabella seguente descrive il comportamento precedente del collegamento della libreria di runtime AddressSanitizer prima di Visual Studio 17.7 Preview 3:

Opzione CRT DLL o EXE DEBUG? Libreria ASan (.lib) File binario di runtime ASan (.dll)
/MT EXE No clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} None
/MT DLL No clang_rt.asan_dll_thunk-{arch} None
/MD O No clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MT EXE clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} None
/MT DLL clang_rt.asan_dbg_dll_thunk-{arch} None
/MD Prima o dopo clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} clang_rt.asan_dbg_dynamic-{arch}

Il diagramma seguente mostra come la libreria ASan è stata collegata per varie opzioni del compilatore prima di Visual Studio 2022 17.7 Preview 3:

Diagramma del modo in cui la DLL di runtime ASan è stata collegata prima di Visual Studio 2022 Preview 3.

L'immagine mostra quattro scenari per il collegamento della libreria di runtime ASan. Gli scenari sono per /MT (collegare in modo statico il runtime), /MTd (collegare in modo statico il runtime di debug), /MD (collegare dinamicamente il redist in fase di esecuzione), /MDd (collegare dinamicamente il debug redist in fase di esecuzione). Per /MT, my_exe.exe ha una copia collegata staticamente del runtime ASan. my_dll.dll collegamenti al runtime ASan in my_exe.exe. Per /MTd, il diagramma è lo stesso, ad eccezione del fatto che usa il runtime ASan collegato staticamente al debug. Per /MD, sia my_exe.exe che my_dll.dll collegamento al runtime ASan collegato dinamicamente denominato clang_rt.asan_dynamic-x86_64.dll. Per /MDd, il diagramma è identico ad eccezione di my_exe.exe e my_dll.dll collegamento al runtime ASan di debug denominato clang_rt.asan_dbg_dynamic-x86_64.dll.

Intercettazione di funzioni

AddressSanitizer ottiene l'intercettazione delle funzioni tramite molte tecniche di hotpatching. Queste tecniche sono meglio documentate all'interno del codice sorgente stesso.

Le librerie di runtime intercettano molte funzioni comuni di gestione della memoria e manipolazione della memoria. Per un elenco, vedere l'elenco AddressSanitizer delle funzioni intercettate. Gli intercettori di allocazione gestiscono i metadati e i byte shadow correlati a ogni chiamata di allocazione. Ogni volta che viene chiamata una funzione CRT, malloc ad esempio o delete , gli intercettori impostano valori specifici nell'area shadow-memory AddressSanitizer per indicare se tali posizioni dell'heap sono attualmente accessibili e quali sono i limiti dell'allocazione. Questi byte shadow consentono ai controlli generati dal compilatore dei byte shadow di determinare se un carico o un archivio è valido.

L'intercettazione non garantisce l'esito positivo. Se un prologo di funzione è troppo breve per la scrittura di un oggetto jmp , l'intercettazione può non riuscire. Se si verifica un errore di intercettazione, il programma genera un'eccezione debugbreak e si interrompe. Se si collega un debugger, la causa del problema di intercettazione è chiara. In caso di problema, segnalare un bug.

Nota

Facoltativamente, gli utenti possono tentare di continuare oltre un'intercettazione non riuscita impostando la variabile ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE di ambiente su qualsiasi valore. Se si continua a superare un errore di intercettazione, è possibile che i report di bug per tale funzione non siano stati rilevati.

Allocatori personalizzati e runtime AddressSanitizer

Il runtime AddressSanitizer fornisce intercettori per interfacce di allocatore comuni, malloc/free, new/delete,/HeapFree HeapAlloc(tramite ).RtlAllocateHeap/RtlFreeHeap Molti programmi usano allocatori personalizzati per un motivo o un altro, un esempio è qualsiasi programma che usa dlmalloc o una soluzione usando l'interfaccia std::allocator e VirtualAlloc(). Il compilatore non è in grado di aggiungere automaticamente chiamate di gestione della memoria shadow a un allocatore personalizzato. È responsabilità dell'utente usare l'interfaccia di avvelenamento manuale fornita. Questa API consente a questi allocatori di funzionare correttamente con il runtime AddressSanitizer esistente e le convenzioni dei byte shadow.

Interfaccia di avvelenamento manuale AddressSanitizer

L'interfaccia per il riconoscimento dei dati è semplice, ma impone restrizioni di allineamento all'utente. Gli utenti possono importare questi prototipi importando sanitizer/asan_interface.h. Ecco i prototipi di funzione di interfaccia:

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

Per praticità, il file di intestazione dell'interfaccia AddressSanitizer fornisce macro wrapper. Queste macro controllano se la funzionalità AddressSanitizer è abilitata durante la compilazione. Consentono al codice sorgente di omettere le chiamate di funzione di avvelenamento quando non sono necessarie. Queste macro devono essere preferite rispetto alla chiamata diretta delle funzioni precedenti:

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

Requisiti di allineamento per l'avvelenamento addressSanitizer

Qualsiasi avvelenamento manuale dei byte di ombreggiatura deve considerare i requisiti di allineamento. Se necessario, l'utente deve aggiungere spaziatura interna, in modo che i byte shadow finisno su un limite di byte nella memoria shadow. Ogni bit nella memoria shadow AddressSanitizer codifica lo stato di un singolo byte nella memoria dell'applicazione. Questa codifica indica la dimensione totale di ogni allocazione, inclusa qualsiasi spaziatura interna, deve essere allineata a un limite di 8 byte. Se il requisito di allineamento non è soddisfatto, può causare segnalazioni di bug non corrette. La segnalazione errata potrebbe manifestarsi come report mancanti (falsi negativi) o report su errori (falsi positivi).

Per un'illustrazione dei requisiti di allineamento e dei potenziali problemi, vedere gli esempi di allineamento di ASan forniti. Uno è un piccolo programma per mostrare cosa può andare storto con l'avvelenamento manuale della memoria shadow. Il secondo è un esempio di implementazione dell'avvelenamento manuale usando l'interfaccia std::allocator .

Opzioni di runtime

Microsoft C/C++ (MSVC) usa un runtime basato sul runtime Clang AddressSanitizer dal repository llvm-project. Per questo motivo, la maggior parte delle opzioni di runtime viene condivisa tra le due versioni. Un elenco completo delle opzioni di runtime Clang pubbliche è disponibile qui. Vengono illustrate alcune differenze nelle sezioni che seguono. Se si individuano opzioni che non funzionano come previsto, segnalare un bug.

Opzioni AddressSanitizer non supportate

  • detect_container_overflow
  • unmap_shadow_on_exit

Nota

L'opzione halt_on_error di runtime AddressSanitizer non funziona nel modo previsto. Sia in Clang che nelle librerie di runtime MSVC, molti tipi di errore sono considerati non continuabili, tra cui la maggior parte degli errori di danneggiamento della memoria.

Per altre informazioni, vedere la sezione Differenze con Clang 12.0 .

Opzioni di runtime addresssanitizer specifiche di MSVC

  • windows_hook_legacy_allocators Valore booleano, impostato su false per disabilitare l'intercettazione di GlobalAlloc e LocalAlloc gli allocatori.

    Nota

    L'opzione windows_hook_legacy_allocators non era disponibile nel runtime llvm-project pubblico al momento della scrittura di questo articolo. Alla fine l'opzione può essere conserci al progetto pubblico; Tuttavia, dipende dalla revisione del codice e dall'accettazione della community.

    L'opzione windows_hook_rtl_allocators, in precedenza una funzionalità di consenso esplicito mentre AddressSanitizer era sperimentale, è ora abilitata per impostazione predefinita. Nelle versioni precedenti a Visual Studio 2022 versione 17.4.6, il valore predefinito dell'opzione è false. In Visual Studio 2022 versione 17.4.6 e versioni successive, l'opzione windows_hook_rtl_allocators predefinita è true.

  • iat_overwrite Stringa, impostata su per "error" impostazione predefinita. Altri valori possibili sono "protect" e "ignore". Alcuni moduli possono sovrascrivere gli import address table altri moduli per personalizzare le implementazioni di determinate funzioni. Ad esempio, i driver in genere forniscono implementazioni personalizzate per hardware specifico. L'opzione iat_overwrite gestisce la protezione del runtime AddressSanitizer da sovrascrizioni per funzioni specifiche memoryapi.h . Il runtime tiene attualmente traccia delle VirtualAllocfunzioni , VirtualProtecte VirtualQuery per la protezione. Questa opzione è disponibile in Visual Studio 2022 versione 17.5 Preview 1 e versioni successive. I valori seguenti iat_overwrite controllano la modalità di reazione del runtime quando le funzioni protette vengono sovrascritte:

    • Se impostato su "error" (impostazione predefinita), il runtime segnala un errore ogni volta che viene rilevata una sovrascrittura.
    • Se impostato su "protect", il runtime tenta di evitare di usare la definizione sovrascritta e procede. In effetti, la definizione originale memoryapi della funzione viene usata dall'interno del runtime per evitare ricorsioni infinite. Altri moduli del processo usano ancora la definizione sovrascritta.
    • Se impostato su "ignore", il runtime non tenta di correggere le funzioni sovrascritte e procede con l'esecuzione.
  • windows_fast_fail_on_error Boolean (false per impostazione predefinita), impostato su true per consentire al processo di terminare con un __fastfail(71) dopo la stampa del report degli errori.

Nota

Quando abort_on_error valore è impostato su true, in Windows il programma termina con un exit(3). Per non modificare il comportamento corrente, abbiamo deciso di introdurre questa nuova opzione. Se sia abort_on_error che windows_fast_fail_on_error sono true, il programma verrà chiuso con il __fastfail.

Elenco AddressSanitizer di funzioni intercettate (Windows)

Il runtime AddressSanitizer esegue l'hotpating di molte funzioni per abilitare i controlli di sicurezza della memoria in fase di esecuzione. Ecco un elenco non esaustivo delle funzioni monitorate dal runtime AddressSanitizer.

Intercettori predefiniti

Intercettori facoltativi

Gli intercettori elencati di seguito vengono installati solo quando è abilitata un'opzione di runtime AddressSanitizer. Impostare windows_hook_legacy_allocators su per false disabilitare l'intercettazione dell'allocatore legacy. set ASAN_OPTIONS=windows_hook_legacy_allocators=false

Vedi anche

Panoramica di AddressSanitizer
Problemi noti di AddressSanitizer
Riferimento alla compilazione e al linguaggio AddressSanitizer
Byte ombreggiatura AddressSanitizer
AddressSanitizer cloud o test distribuiti
Integrazione del debugger AddressSanitizer
Esempi di errore addressSanitizer