UndefinedBehaviorSanitizer (UBSan) esegue la strumentazione in fase di compilazione per verificare la presenza di vari tipi di comportamento non definito. Sebbene UBSan sia in grado di rilevare molti bug comportamentali non definiti , Android supporta:
- allineamento
- bool
- limiti
- enum
- float-cast-troppopieno
- float-dividi-per-zero
- intero-dividi-per-zero
- attributo non nullo
- nullo
- ritorno
- restituisce l'attributo non nullo
- base a spostamento
- esponente di spostamento
- overflow di interi con segno
- irraggiungibile
- overflow di numeri interi senza segno
- legato a vla
unsigned-integer-overflow, pur non essendo un comportamento tecnicamente indefinito, è incluso nel disinfettante e utilizzato in molti moduli Android, inclusi i componenti mediaserver, per eliminare eventuali vulnerabilità latenti di integer-overflow.
Implementazione
Nel sistema di build Android, puoi abilitare UBSan a livello globale o locale. Per abilitare UBSan a livello globale, imposta SANITIZE_TARGET in Android.mk. Per abilitare UBSan a livello di modulo, imposta LOCAL_SANITIZE e specifica i comportamenti non definiti che vuoi cercare in Android.mk. Per esempio:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0 LOCAL_SRC_FILES:= sanitizer-status.c LOCAL_MODULE:= sanitizer-status LOCAL_SANITIZE := alignment bounds null unreachable integer LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer include $(BUILD_EXECUTABLE)
E la configurazione del progetto equivalente (Android.bp):
cc_binary { cflags: [ "-std=c11", "-Wall", "-Werror", "-O0", ], srcs: ["sanitizer-status.c"], name: "sanitizer-status", sanitize: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], diag: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], }, }, }
Scorciatoie UBSan
Android ha anche due scorciatoie, integer
e default-ub
, per abilitare una serie di disinfettanti contemporaneamente. integer abilita integer-divide-by-zero
, signed-integer-overflow
e unsigned-integer-overflow
. default-ub
abilita i controlli che presentano problemi minimi di prestazioni del compilatore: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound
La classe integer sanitizer può essere utilizzata con SANITIZE_TARGET e LOCAL_SANITIZE, mentre default-ub può essere utilizzata solo con SANITIZE_TARGET.
Migliore segnalazione degli errori
L'implementazione UBSan predefinita di Android richiama una funzione specificata quando viene rilevato un comportamento non definito. Per impostazione predefinita, questa funzione è abort. Tuttavia, a partire da ottobre 2016, UBSan su Android dispone di una libreria di runtime facoltativa che fornisce segnalazioni di errori più dettagliate, incluso il tipo di comportamento non definito riscontrato, file e informazioni sulla riga del codice sorgente. Per abilitare questa segnalazione degli errori con i controlli dei numeri interi, aggiungi quanto segue a un file Android.mk:
LOCAL_SANITIZE:=integer LOCAL_SANITIZE_DIAG:=integer
Il valore LOCAL_SANITIZE abilita il disinfettante durante la compilazione. LOCAL_SANITIZE_DIAG attiva la modalità diagnostica per il disinfettante specificato. È possibile impostare LOCAL_SANITIZE e LOCAL_SANITIZE_DIAG su valori diversi, ma solo i controlli in LOCAL_SANITIZE sono abilitati. Se un controllo non è specificato in LOCAL_SANITIZE, ma è specificato in LOCAL_SANITIZE_DIAG, il controllo non è abilitato ei messaggi diagnostici non vengono forniti.
Ecco un esempio delle informazioni fornite dalla libreria di runtime UBSan:
pixel-xl:/ # sanitizer-status ubsan sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Intero Overflow Sanificazione
Integer overflow non intenzionali possono causare il danneggiamento della memoria o vulnerabilità di divulgazione di informazioni nelle variabili associate agli accessi alla memoria o alle allocazioni di memoria. Per contrastare questo problema, abbiamo aggiunto i disinfettanti per overflow di interi firmati e non firmati UndefinedBehaviorSanitizer (UBSan) di Clang per rafforzare il framework multimediale in Android 7.0. In Android 9, abbiamo ampliato UBSan per coprire più componenti e migliorato il supporto del sistema di compilazione.
Questo è progettato per aggiungere controlli sulle operazioni/istruzioni aritmetiche, che potrebbero causare un overflow, per interrompere in modo sicuro un processo se si verifica un overflow. Questi disinfettanti possono mitigare un'intera classe di vulnerabilità di danneggiamento della memoria e divulgazione di informazioni in cui la causa principale è un overflow di numeri interi, come la vulnerabilità Stagefright originale.
Esempi e fonte
Integer Overflow Sanitization (IntSan) è fornito dal compilatore e aggiunge strumentazione nel file binario durante la fase di compilazione per rilevare gli overflow aritmetici. È abilitato per impostazione predefinita in vari componenti della piattaforma, ad esempio /platform/external/libnl/Android.bp
.
Implementazione
IntSan utilizza i disinfettanti di overflow di numeri interi firmati e non firmati di UBSan. Questa mitigazione è abilitata a livello di modulo. Aiuta a proteggere i componenti critici di Android e non deve essere disabilitato.
Ti consigliamo vivamente di abilitare la sanitizzazione dell'overflow di numeri interi per componenti aggiuntivi. I candidati ideali sono codice nativo privilegiato o codice nativo che analizza l'input utente non attendibile. Esiste un piccolo sovraccarico di prestazioni associato al disinfettante che dipende dall'utilizzo del codice e dalla prevalenza delle operazioni aritmetiche. Aspettati una piccola percentuale di sovraccarico e verifica se le prestazioni sono un problema.
Supporto di IntSan nei makefile
Per abilitare IntSan in un makefile, aggiungi:
LOCAL_SANITIZE := integer_overflow # Optional features LOCAL_SANITIZE_DIAG := integer_overflow LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
-
LOCAL_SANITIZE
accetta un elenco separato da virgole di disinfettanti, coninteger_overflow
che è un set preconfezionato di opzioni per i singoli disinfettanti di overflow di interi firmati e non firmati con un BLOCKLIST predefinito . -
LOCAL_SANITIZE_DIAG
attiva la modalità diagnostica per i disinfettanti. Utilizzare la modalità diagnostica solo durante il test perché non si interromperà in caso di overflow, annullando completamente il vantaggio in termini di sicurezza della mitigazione. Vedere Risoluzione dei problemi per ulteriori dettagli. -
LOCAL_SANITIZE_BLOCKLIST
consente di specificare un file BLOCKLIST per impedire che funzioni e file di origine vengano ripuliti. Vedere Risoluzione dei problemi per ulteriori dettagli.
Se desideri un controllo più granulare, abilita i disinfettanti singolarmente utilizzando uno o entrambi i flag:
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Supportare IntSan nei file di progetto
Per abilitare la sanificazione dell'overflow di numeri interi in un file blueprint, ad esempio /platform/external/libnl/Android.bp
, aggiungi:
sanitize: { integer_overflow: true, diag: { integer_overflow: true, }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Come con make files, la proprietà integer_overflow
è un set preconfezionato di opzioni per i singoli disinfettanti di overflow di interi firmati e non firmati con un BLOCKLIST predefinito .
Il set di proprietà diag
abilita la modalità diagnostica per i disinfettanti. Utilizzare la modalità diagnostica solo durante i test. La modalità di diagnostica non si interrompe in caso di overflow, il che annulla completamente il vantaggio in termini di sicurezza della mitigazione nelle build degli utenti. Vedere Risoluzione dei problemi per ulteriori dettagli.
La proprietà BLOCKLIST
consente di specificare un file BLOCKLIST che consente agli sviluppatori di impedire la sanificazione delle funzioni e dei file di origine. Vedere Risoluzione dei problemi per ulteriori dettagli.
Per abilitare i disinfettanti singolarmente, utilizzare:
sanitize: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"], diag: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow",], }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Risoluzione dei problemi
Se si abilita la sanitizzazione dell'overflow di numeri interi in nuovi componenti o si fa affidamento su librerie di piattaforma che hanno avuto la sanitizzazione dell'overflow di numeri interi, è possibile che si verifichino alcuni problemi con overflow di numeri interi benigni che causano interruzioni. È necessario testare i componenti con la sanitizzazione abilitata per garantire che gli overflow benigni possano essere rilevati.
Per trovare interruzioni causate dalla sanitizzazione nelle build degli utenti, cercare arresti anomali SIGABRT
con messaggi di interruzione che indicano un overflow rilevato da UBSan, ad esempio:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/surfaceflinger <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: sub-overflow'
L'analisi dello stack dovrebbe includere la funzione che causa l'interruzione, tuttavia, gli overflow che si verificano nelle funzioni inline potrebbero non essere evidenti nell'analisi dello stack.
Per determinare più facilmente la causa principale, abilitare la diagnostica nella libreria che attiva l'interruzione e tentare di riprodurre l'errore. Con la diagnostica abilitata, il processo non si interromperà e continuerà invece a essere eseguito. Non interrompere aiuta a massimizzare il numero di overflow benigni in un particolare percorso di esecuzione senza dover ricompilare dopo aver corretto ogni bug. La diagnostica produce un messaggio di errore che include il numero di riga e il file sorgente che causano l'interruzione:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Una volta individuata l'operazione aritmetica problematica, assicurarsi che l'overflow sia benigno e voluto (ad esempio non abbia implicazioni sulla sicurezza). È possibile indirizzare l'interruzione del disinfettante:
- Refactoring del codice per evitare l'overflow ( esempio )
- Overflow esplicito tramite le funzioni __builtin_*_overflow di Clang ( esempio )
- Disabilitare la sanificazione nella funzione specificando l'attributo
no_sanitize
( esempio ) - Disabilitazione della sanificazione di una funzione o di un file sorgente tramite un file BLOCKLIST ( esempio )
Dovresti usare la soluzione più granulare possibile. Ad esempio, una funzione di grandi dimensioni con molte operazioni aritmetiche e una singola operazione in overflow dovrebbe avere il refactoring della singola operazione anziché l'intera funzione BLOCKLISTed.
I modelli comuni che possono causare overflow benigni includono:
- Cast impliciti in cui si verifica un overflow senza segno prima di eseguire il cast su un tipo con segno ( esempio )
- Cancellazioni di elenchi collegati che decrementano l'indice del ciclo alla cancellazione ( esempio )
- Assegnare un tipo senza segno a -1 invece di specificare il valore massimo effettivo ( esempio )
- Cicli che decrementano un numero intero senza segno nella condizione ( esempio , esempio )
Si consiglia agli sviluppatori di assicurarsi che i casi in cui il disinfettante rileva un overflow sia effettivamente benigno senza effetti collaterali indesiderati o implicazioni per la sicurezza prima di disabilitare la sanificazione.
Disattivazione di IntSan
Puoi disabilitare IntSan con BLOCKLIST o attributi di funzione. Disabilita con parsimonia e solo quando il refactoring del codice è altrimenti irragionevole o se c'è un sovraccarico di prestazioni problematico.
Vedere la documentazione originale di Clang per ulteriori informazioni sulla disabilitazione di IntSan con gli attributi della funzione e la formattazione del file BLOCKLIST . Il BLOCKLISTing deve essere limitato al particolare disinfettante utilizzando i nomi delle sezioni che specificano il disinfettante di destinazione per evitare di influire su altri disinfettanti.
Convalida
Al momento, non esistono test CTS specifici per la sanitizzazione dell'overflow di numeri interi. Assicurati invece che i test CTS vengano superati con o senza IntSan abilitato per verificare che non abbia alcun impatto sul dispositivo.
Limiti Sanificazione
BoundsSanitizer (BoundSan) aggiunge la strumentazione ai file binari per inserire i controlli dei limiti attorno agli accessi agli array. Questi controlli vengono aggiunti se il compilatore non può dimostrare in fase di compilazione che l'accesso sarà sicuro e se la dimensione dell'array sarà nota in fase di esecuzione, in modo che possa essere verificata. Android 10 distribuisce BoundSan in Bluetooth e codec. BoundSan è fornito dal compilatore ed è abilitato per impostazione predefinita in vari componenti della piattaforma.
Implementazione
BoundSan utilizza il disinfettante per i limiti di UBSan . Questa mitigazione è abilitata a livello di modulo. Aiuta a proteggere i componenti critici di Android e non dovrebbe essere disabilitato.
Ti consigliamo vivamente di abilitare BoundSan per componenti aggiuntivi. I candidati ideali sono codice nativo privilegiato o codice nativo complesso che analizza l'input utente non attendibile. Il sovraccarico delle prestazioni associato all'abilitazione di BoundSan dipende dal numero di accessi all'array che non possono essere dimostrati sicuri. Aspettati in media una piccola percentuale di spese generali e verifica se le prestazioni sono un problema.
Abilitazione di BoundSan nei file blueprint
BoundSan può essere abilitato nei file blueprint aggiungendo "bounds"
alla proprietà misc_undefined
sanitize per i moduli binari e di libreria:
sanitize: { misc_undefined: ["bounds"], diag: { misc_undefined: ["bounds"], }, BLOCKLIST: "modulename_BLOCKLIST.txt",
diag
La proprietà diag
abilita la modalità diagnostica per i disinfettanti. Utilizzare la modalità diagnostica solo durante i test. La modalità di diagnostica non si interrompe in caso di overflow, il che annulla il vantaggio in termini di sicurezza della mitigazione e comporta un sovraccarico delle prestazioni più elevato, pertanto non è consigliata per le build di produzione.
LISTA DI BLOCCATI
La proprietà BLOCKLIST
consente la specifica di un file BLOCKLIST che gli sviluppatori possono utilizzare per impedire la sanificazione di funzioni e file di origine. Utilizzare questa proprietà solo se le prestazioni sono un problema e i file/funzioni mirati contribuiscono in modo sostanziale. Controlla manualmente questi file/funzioni per garantire che gli accessi all'array siano sicuri. Vedere Risoluzione dei problemi per ulteriori dettagli.
Abilitazione di BoundSan nei makefile
BoundSan può essere abilitato nei makefile aggiungendo "bounds"
alla variabile LOCAL_SANITIZE
per i moduli binari e di libreria:
LOCAL_SANITIZE := bounds # Optional features LOCAL_SANITIZE_DIAG := bounds LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZE
accetta un elenco di disinfettanti separati da una virgola.
LOCAL_SANITIZE_DIAG
attiva la modalità diagnostica. Utilizzare la modalità diagnostica solo durante i test. La modalità di diagnostica non si interrompe in caso di overflow, il che annulla il vantaggio in termini di sicurezza della mitigazione e comporta un sovraccarico delle prestazioni più elevato, pertanto non è consigliata per le build di produzione.
LOCAL_SANITIZE_BLOCKLIST
consente la specifica di un file BLOCKLIST che consente agli sviluppatori di impedire la sanificazione delle funzioni e dei file di origine. Utilizzare questa proprietà solo se le prestazioni sono un problema e i file/funzioni mirati contribuiscono in modo sostanziale. Controlla manualmente questi file/funzioni per garantire che gli accessi all'array siano sicuri. Vedere Risoluzione dei problemi per ulteriori dettagli.
Disabilitare BoundSan
Puoi disabilitare BoundSan nelle funzioni e nei file sorgente con BLOCKLIST o attributi di funzione. È meglio mantenere abilitato BoundSan, quindi disabilitarlo solo se la funzione o il file sta creando un sovraccarico di prestazioni elevato e la fonte è stata rivista manualmente.
Per ulteriori informazioni sulla disabilitazione di BoundSan con gli attributi di funzione e la formattazione del file BLOCKLIST , fare riferimento alla documentazione di Clang LLVM. Ambito BLOCKLISTing al disinfettante specifico utilizzando i nomi delle sezioni che specificano il disinfettante di destinazione per evitare di influire su altri disinfettanti.
Convalida
Non ci sono test CTS specifici per BoundSan. Assicurati invece che i test CTS vengano superati con o senza BoundSan abilitato per verificare che non abbia alcun impatto sul dispositivo.
Risoluzione dei problemi
Testare accuratamente i componenti dopo aver abilitato BoundSan per garantire che tutti gli accessi fuori limite non rilevati in precedenza vengano risolti.
Gli errori di BoundSan possono essere facilmente identificati in quanto includono il seguente messaggio di interruzione della rimozione definitiva:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/foobar <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: out-of-bounds'
Quando si esegue in modalità diagnostica, il file di origine, il numero di riga e il valore di indice vengono stampati su logcat
. Per impostazione predefinita, questa modalità non genera un messaggio di interruzione. Esamina logcat
per verificare la presenza di eventuali errori.
external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'