Sanitizer UndefinedBehavior

UndefinedBehaviorSanitizer (UBSan) esegue la strumentazione in fase di compilazione per verificare la presenza di vari tipi di comportamenti indefiniti. Sebbene UBSan sia in grado di rilevamento in corso... molti bug di comportamento non definiti, Android supporta:

  • allineamento
  • bool
  • limiti
  • enum
  • overflow-cast-float
  • divisione-mobile-per-zero
  • divisione-intero-per-zero
  • attributo non nullo
  • null
  • invio
  • restituisce-attributo-nonnull
  • turno-base
  • esponente di spostamento
  • overflow-integer-integro
  • non raggiungibile
  • overflow-integer-non firmato
  • vla-bound

unSign-integer-overflow, anche se tecnicamente non definito comportamento, sia inclusa nel disinfettante e usata in molti moduli Android, inclusi i componenti mediaserver, per eliminare l'eventuale overflow di valori interi latenti le vulnerabilità.

Implementazione

Nel sistema di build Android, puoi attivare UBSan a livello globale o locale. Per attivare UBSan a livello globale, imposta SANITIZE_TARGET in Android.mk. Per attivare UBSan a un a livello di modulo, imposta LOCAL_SANITIZE e specifica i comportamenti non definiti che vuoi cercare in Android.mk. Ad 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 base 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 attivare contemporaneamente un insieme di disinfettanti. numero intero abilita integer-divide-by-zero, signed-integer-overflow e unsigned-integer-overflow. default-ub abilita i controlli con un compilatore minimo problemi di prestazioni: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound. La classe sanitizer con numeri interi con SANITIZE_TARGET e LOCAL_SANITIZE, mentre il valore default-ub può essere usato solo con SANITIZE_TARGET.

Segnalazione degli errori migliorata

L'implementazione UBSan predefinita di Android richiama una funzione specificata quando si è riscontrato un comportamento non definito. Per impostazione predefinita, questa funzione è interrotta. Tuttavia, a partire da ottobre 2016, UBSan su Android ha una libreria di runtime facoltativa fornisce report sugli errori più dettagliati, tra cui il tipo di comportamento non definito informazioni trovate, sul file e sulla riga del codice sorgente. Per attivare questo errore i report con controlli di numeri interi aggiungono quanto segue a un file Android.mk:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

Il valore LOCAL_SANITIZE abilita il sanitizer durante la creazione. LOCAL_SANITIZE_DIAG attiva la modalità diagnostica per il sanitizer specificato. È è possibile impostare LOCAL_SANITIZE e LOCAL_SANITIZE_DIAG su valori diversi, ma sono abilitati solo i controlli in LOCAL_SANITIZE. Se un controllo non è specificato in LOCAL_SANITIZE, ma è specificato in LOCAL_SANITIZE_DIAG, il controllo non è abilitato e messaggi di diagnostica.

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')

Sanificazione dell'overflow del numero intero

Gli overflow di numeri interi involontari possono causare il danneggiamento della memoria o delle informazioni vulnerabilità di divulgazione nelle variabili associate agli accessi alla memoria alla distribuzione della memoria. Per contrastare questa tendenza, abbiamo aggiunto UndefinedBehaviorSanitizer (UBSan) sanitizer di overflow di numeri interi firmati e non firmati a intensificare il framework multimediale in Android 7.0. In Android 9, espanso UBSan per coprire più componenti e migliorare il supporto del sistema di compilazione.

È progettato per aggiungere controlli aritmetici operazioni / istruzioni, che potrebbero overflow: per interrompere in sicurezza un processo se si verifica un overflow. Questi sanitizzatori possono mitigare un'intera classe di danneggiamento della memoria e vulnerabilità di divulgazione di informazioni in cui la causa principale è un numero intero come la vulnerabilità originale di Stagefright.

Esempi e fonte

La sanificazione dell'overflow intero (IntSan) è fornita dal compilatore e aggiunge la strumentazione nel programma binario durante il tempo di compilazione per rilevare le operazioni aritmetiche overflow. È attivata per impostazione predefinita in vari componenti durante una piattaforma Google, ad esempio /platform/external/libnl/Android.bp

Implementazione

IntSan utilizza sanitizer di overflow di interi senza firma e con segno di UBSan. Questo la mitigazione è abilitata a livello di modulo. Aiuta a mantenere i componenti critici di Android sicuro e non deve essere disattivato.

Ti consigliamo vivamente di abilitare la sanificazione dell'overflow intero per componenti. I candidati ideali sono un codice nativo privilegiato che analizza l'input utente non attendibile. Esiste un piccolo overhead di rendimento associato con il disinfettante che dipende dall'uso del codice e dalla prevalenza di operazioni aritmetiche. Aspettati una piccola percentuale di overhead 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 dove integer_overflow è un insieme predefinito di opzioni per i singoli sanitizzatori di overflow di numeri interi firmati e non firmati con un predefinita ELENCO BLOCCO
  • LOCAL_SANITIZE_DIAG attiva la modalità diagnostica per disinfettanti. Utilizza la modalità diagnostica solo durante i test perché interrompere gli overflow, annullando completamente il vantaggio in termini di sicurezza mitigazione dei rischi. Consulta la sezione Risoluzione dei problemi. per ulteriori dettagli.
  • LOCAL_SANITIZE_BLOCKLIST ti consente di specificare una LISTA BLOCCA per impedire la sanificazione di funzioni e file di origine. Consulta Risoluzione dei problemi per ulteriori i dettagli.

Se vuoi un controllo più granulare, abilita i disinfettanti individualmente utilizzando uno o entrambi:

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 progetto, ad esempio /platform/external/libnl/Android.bp, aggiungi:

   sanitize: {
          integer_overflow: true,
          diag: {
              integer_overflow: true,
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

Come nel caso dei file "make", la proprietà integer_overflow è una proprietà insieme di opzioni per l'overflow dei singoli numeri interi con e senza segno disinfettanti con un'impostazione predefinita ELENCO BLOCCA

L'insieme di proprietà diag attiva la modalità diagnostica per disinfettanti. Utilizza la modalità diagnostica solo durante i test. La modalità Diagnostica non interrompere gli overflow, il che nega completamente il vantaggio in termini di sicurezza nella mitigazione delle build degli utenti. Per ulteriori dettagli, consulta la sezione Risoluzione dei problemi.

La proprietà BLOCKLIST consente di specificare un file BLOCKLIST che consente agli sviluppatori di impedire che le funzioni e i file di origine vengano sterilizzato. Consulta la sezione Risoluzione dei problemi per e ulteriori dettagli.

Per attivare singolarmente i disinfettanti, utilizza:

   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 attivi la sanificazione dell'overflow di valori interi nei nuovi componenti o fai affidamento delle librerie della piattaforma con sanitizzazione dell'overflow di numeri interi, alcuni problemi con overflow di numeri interi benigni che causano interruzioni. Dovresti verificare componenti con sanitizzazione abilitata per garantire overflow benigni.

Per trovare le interruzioni causate dalla sanificazione nelle build degli utenti, cerca SIGABRT ha un arresto anomalo 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 ha causato l'interruzione, tuttavia gli overflow che si verificano nelle funzioni in linea potrebbero non essere evidenti nell'analisi dello stack.

Per determinare più facilmente la causa principale, abilita la diagnostica nella libreria che attivano l'interruzione e prova a riprodurre l'errore. Con di diagnostica abilitata, la procedura non verrà interrotta continuano a essere eseguiti. La mancata interruzione aiuta a massimizzare il numero di overflow benigni in una un particolare percorso di esecuzione senza doverlo ricompilare dopo aver corretto ogni bug. La diagnostica genera un messaggio di errore che include il numero di riga e l'origine che causa 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, assicurati che l'overflow è benigno e intenzionale (ad es. non ha implicazioni per la sicurezza). Puoi risolvere il problema interruzione del disinfettante da:

  • Refactoring del codice per evitare l'overflow (esempio)
  • Esegui l'overflow in modo esplicito tramite __builtin_*_overflow (esempio)
  • Disabilita la sanitizzazione nella funzione specificando l'attributo no_sanitize (esempio)
  • Disabilitazione della sanificazione di una funzione o di un file di origine tramite un file BLOCKLIST (esempio)

Dovresti usare la soluzione più granulare possibile. Ad esempio, un grande funzione con molte operazioni aritmetiche e una singola operazione di overflow eseguire il refactoring della singola operazione anziché dell'intera funzione IN ELENCO BLOCCO.

Gli schemi comuni che possono causare overflow benigni includono:

  • Implicito Cast in cui si verifica un overflow non firmato prima di essere trasmesso a un tipo firmato (esempio)
  • Eliminazioni di elenchi collegati che riducono l'indice di loop al momento dell'eliminazione (esempio)
  • Assegnare un tipo senza segno a -1 anziché specificare il valore massimo effettivo (esempio)
  • Loop che riducono un numero intero senza segno nella condizione (esempio, esempio)

Consigliamo agli sviluppatori di garantire che nei casi in cui il disinfettante rilevi un overflow che è davvero benigno senza effetti collaterali involontari o le implicazioni prima di disabilitare la sanificazione.

Disabilita IntSan

Puoi disattivare IntSan con BLOCKLIST o attributi di funzione. Disabilita con parsimonia e solo nel caso in cui il refactoring del codice sia altrimenti irragionevole o se c'è un overhead di rendimento problematico.

Consulta la documentazione di Clang upstream per ulteriori informazioni sulla disattivazione di IntSan con funzione attributi e file BLOCKLIST formattazione. Le BLOCKLIST devono avere come ambito il particolare disinfettante usando nomi di sezioni che specifichino il sanitizer di destinazione per evitare di colpire disinfettanti.

Convalida

Al momento, non esistono test CTS specifici per la sanificazione degli overflow interi. Assicurati invece che i test CTS vengano superati con o senza IntSan abilitato per la verifica che questo non influisca sul dispositivo.

Sanificazione limiti

BoundsSanitizer (BoundSan) aggiunge la strumentazione ai file binari per inserire i limiti controlla gli accessi agli array. Questi controlli vengono aggiunti se il compilatore non può dimostrare al momento della compilazione che l'accesso sarà sicuro e che le dimensioni dell'array sarà nota in fase di runtime, in modo da poterla confrontare. Android 10 esegue il deployment di BoundSan Bluetooth e codec. BoundSan viene fornito dal compilatore ed è abilitato sono predefiniti in vari componenti della piattaforma.

Implementazione

BoundSan utilizza la tecnologia UBSan disinfettante. Questa mitigazione è abilitata a livello di modulo. Sono utili per mantenere al sicuro i componenti critici di Android e non deve essere disattivato.

Ti consigliamo vivamente di attivare BoundSan per componenti aggiuntivi. I candidati ideali sono un codice nativo con privilegi o un codice nativo complesso che analizza input utente non attendibile. L'overhead delle prestazioni associato all'attivazione di BoundSan dipende dal numero di accessi agli array che non possono essere dimostrati sicuri. È previsto un una piccola percentuale media di overhead e verifica se le prestazioni sono un problema.

Abilita BoundSan nei file di progetto

BoundSan può essere abilitato nei file di progetto aggiungendo "bounds" alla proprietà misc_undefined sanitize per file binari e librerie moduli:

    sanitize: {
       misc_undefined: ["bounds"],
       diag: {
          misc_undefined: ["bounds"],
       },
       BLOCKLIST: "modulename_BLOCKLIST.txt",
diagramma

La proprietà diag attiva la modalità diagnostica per i disinfettanti. Utilizza la modalità diagnostica solo durante i test. La modalità di diagnostica non si interrompe su overflow, il che nega il vantaggio per la sicurezza della mitigazione e comporta in termini di overhead delle prestazioni maggiore, perciò è sconsigliato per le build di produzione.

ELENCO BLOCCO

La proprietà BLOCKLIST consente la specifica di una LISTA BLOCCA che gli sviluppatori possono utilizzare per impedire che le funzioni e i file di origine sterilizzato. Utilizza questa proprietà solo se il rendimento è un problema e se il target i file/le funzioni contribuiscono in modo sostanziale. Controlla manualmente questi file/funzioni per garantire la sicurezza degli accessi agli array. Consulta la sezione Risoluzione dei problemi per ulteriori informazioni. i dettagli.

Attiva BoundSan nei makefile

BoundSan può essere abilitato nei makefile aggiungendo "bounds" alla variabile LOCAL_SANITIZE per i moduli binari e delle librerie:

    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. Utilizza la diagnostica solo durante il test. La modalità di diagnostica non si interrompe in caso di overflow, nega il vantaggio per la sicurezza della mitigazione e comporta un in termini di overhead delle prestazioni, perciò è sconsigliato per le build di produzione.

LOCAL_SANITIZE_BLOCKLIST consente di specificare una LISTA BLOCCA che consente agli sviluppatori di impedire che le funzioni e i file di origine sterilizzato. Utilizza questa proprietà solo se il rendimento è un problema e se il target i file/le funzioni contribuiscono in modo sostanziale. Controlla manualmente questi file/funzioni per garantire la sicurezza degli accessi agli array. Consulta la sezione Risoluzione dei problemi per ulteriori informazioni. i dettagli.

Disattiva BoundSan

Puoi disabilitare BoundSan nelle funzioni e nei file sorgente con BLOCKLIST o di funzione. È meglio mantenere BoundSan abilitato, quindi disattivalo solo se la funzione o il file sta creando una grande quantità di sovraccarico delle prestazioni sia stata esaminata manualmente.

Per ulteriori informazioni sulla disattivazione di BoundSan con la funzione attributi e file BLOCKLIST formattazione, consulta la documentazione su LLVM Clang. Definisci l'ambito BLOCKLIST al specifico disinfettante utilizzando nomi di sezioni che specifichino disinfettante per non incorrere in problemi su altri disinfettanti.

Convalida

Non esistono test CTS specifici per BoundSan. Assicurati invece che CTS test superati con o senza BoundSan abilitato per verificare che non del dispositivo.

Risoluzione dei problemi

Testa attentamente i componenti dopo aver attivato BoundSan per assicurarti che eventuali e non rilevati gli accessi fuori intervallo.

Gli errori di BoundSan possono essere facilmente identificati poiché includono quanto segue: messaggio di interruzione tombstone:

    pid: ###, tid: ###, name: Binder:###  >>> /system/bin/foobar <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: out-of-bounds'

Con l'esecuzione in modalità diagnostica, il file di origine, il numero di riga e l'indice vengono stampati in logcat. Per impostazione predefinita, questa modalità invia un messaggio di interruzione. Controlla 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]'