Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Desinfectantes LLVM

LLVM, la infraestructura del compilador utilizada para construir Android, contiene múltiples componentes que realizan análisis estáticos y dinámicos. De estos componentes, los desinfectantes, específicamente AddressSanitizer y UndefinedBehaviorSanitizer, se pueden usar ampliamente para analizar Android. Los desinfectantes son componentes de instrumentación basados ​​en compiladores contenidos en external / compiler-rt que se pueden usar durante el desarrollo y las pruebas para eliminar errores y mejorar Android. El conjunto actual de desinfectantes de Android puede descubrir y diagnosticar muchos errores de uso incorrecto de la memoria y comportamientos indefinidos potencialmente peligrosos.

Es una buena práctica que las compilaciones de Android se inicien y se ejecuten con desinfectantes habilitados, como AddressSanitizer y UndefinedBehaviorSanitizer. Esta página presenta AddressSanitizer, UndefinedBehaviorSanitizer y KernelAddressSanitizer, muestra cómo se pueden usar dentro del sistema de compilación de Android y brinda ejemplos de archivos Android.mk y Android.bp que compilan componentes nativos con estos desinfectantes habilitados.

DirecciónSanitizer

AddressSanitizer (Asan) es una capacidad instrumentación basada en compilador que detecta muchos tipos de errores de memoria en código C / C ++ en tiempo de ejecución. ASan puede detectar muchas clases de errores de memoria, que incluyen:

  • Acceso a la memoria fuera de los límites
  • Doble gratis
  • Use-after-free

Android permite la instrumentación de ASan en el nivel de compilación completo y el nivel de aplicación con asanwrapper.

AddressSanitizer combina la instrumentación de todas las llamadas a funciones relacionadas con la memoria, incluidas alloca, malloc y free, y rellena todas las variables y regiones de memoria asignadas con memoria que activa una devolución de llamada ASan cuando se lee o se escribe.

La instrumentación permite que ASan detecte errores de uso de memoria no válidos, incluido el alcance doble libre, uso posterior, retorno y libre, mientras que el relleno de la región de memoria detecta lecturas o escrituras fuera de los límites. Si se produce una lectura o escritura en esta región de relleno, ASan la detecta y emite información para ayudar a diagnosticar la violación de la memoria, incluida la pila de llamadas, el mapa de memoria oculta, el tipo de violación de la memoria, lo que se leyó o escribió, la instrucción que causó la violación y el contenido de la memoria.

pixel-xl:/ # sanitizer-status                                                                                            
=================================================================
==14164==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x0032000054b0 at pc 0x005df16ffc3c bp 0x007fc236fdf0 sp 0x007fc236fdd0
WRITE of size 1 at 0x0032000054b0 thread T0
    #0 0x5df16ffc3b in test_crash_malloc sanitizer-status/sanitizer-status.c:36:13
    #1 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7
    #2 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3)
    #3 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53)

0x0032000054b0 is located 0 bytes to the right of 32-byte region [0x003200005490,0x0032000054b0)
allocated by thread T0 here:
    #0 0x794d0bdc67 in malloc (/system/lib64/libclang_rt.asan-aarch64-android.so+0x74c67)
    #1 0x5df16ffb47 in test_crash_malloc sanitizer-status/sanitizer-status.c:34:25
    #2 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7
    #3 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3)
    #4 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53)
    #5 0x794df78893  (<unknown module>)

SUMMARY: AddressSanitizer: heap-buffer-overflow sanitizer-status/sanitizer-status.c:36:13 in test_crash_malloc

A veces, el proceso de descubrimiento de errores puede parecer no determinista, especialmente para los errores que requieren una configuración especial o técnicas más avanzadas, como la preparación del montón o la explotación de condiciones de carrera. Muchos de estos errores no son evidentes de inmediato y podrían surgir miles de instrucciones lejos de la violación de memoria que fue la causa raíz real. ASan instrumenta todas las funciones relacionadas con la memoria y los datos de los pads con áreas a las que no se puede acceder sin activar una devolución de llamada ASan. Esto significa que las infracciones de la memoria se detectan en el instante en que ocurren, en lugar de esperar a que se produzcan daños que provoquen fallos. Esto es extremadamente útil en el descubrimiento de errores y el diagnóstico de la causa raíz.

Para verificar que ASAN es funcional en un dispositivo de destino, Android ha incluido el ejecutable asan_test. El ejecutable asan_test prueba y valida la funcionalidad ASAN en un dispositivo de destino, dando mensajes de diagnóstico con el estado de cada prueba. Cuando se utiliza una compilación de Android ASAN, se encuentra en /data/nativetest/asan_test/asan_test o /data/nativetest64/asan_test/asan_test de forma predeterminada.

IndefinidoBehaviorSanitizer

UndefinedBehaviorSanitizer (UBSan) realiza instrumentación en tiempo de compilación para verificar varios tipos de comportamiento indefinido. Si bien UBSan es capaz de detectar muchos comportamientos indefinidos , Android admite alineación, bool, límites, enum, float-cast-overflow, float-divide-by-zero, integer-divide-by-zero, nonnull-attribute, null, return, devuelve atributo no nulo, base de desplazamiento, exponente de desplazamiento, desbordamiento de entero con signo, inalcanzable, desbordamiento de entero sin signo y enlazado a vla. unsigned-integer-overflow, aunque técnicamente no es un comportamiento indefinido, se incluye en el desinfectante y se utiliza en muchos módulos de Android, incluidos los componentes mediaserver, para eliminar cualquier vulnerabilidad latente de desbordamiento de enteros.

Implementación

En el sistema de compilación de Android, puede habilitar UBSan de forma global o local. Para habilitar UBSan globalmente, configure SANITIZE_TARGET en Android.mk. Para habilitar UBSan a nivel de módulo, configure LOCAL_SANITIZE y especifique los comportamientos indefinidos que desea buscar en Android.mk. Por ejemplo:

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)

El sistema de compilación de Android aún no admite diagnósticos tan detallados en archivos de planos como los archivos make. Aquí está el equivalente más cercano escrito como plano (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: {
            undefined : true
        },
    },

}

Atajos de UBSan

Android también tiene dos atajos, integer y default-ub , para habilitar un conjunto de desinfectantes al mismo tiempo. integer habilita el signed-integer-overflow integer-divide-by-zero , el signed-integer-overflow unsigned-integer-overflow . default-ub habilita las comprobaciones que tienen problemas mínimos de rendimiento del compilador: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable y vla-bound. La clase de desinfectante de enteros se puede usar con SANITIZE_TARGET y LOCAL_SANITIZE, mientras que default-ub solo se puede usar con SANITIZE_TARGET.

Mejor informe de errores

La implementación UBSan predeterminada de Android invoca una función específica cuando se encuentra un comportamiento indefinido. De forma predeterminada, esta función se cancela. Sin embargo, a partir de octubre de 2016, UBSan en Android tiene una biblioteca de tiempo de ejecución opcional que brinda informes de errores más detallados, incluido el tipo de comportamiento indefinido encontrado, información de línea de código fuente y archivo. Para habilitar este informe de errores con comprobaciones de números enteros, agregue lo siguiente a un archivo Android.mk:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

El valor LOCAL_SANITIZE habilita el desinfectante durante la construcción. LOCAL_SANITIZE_DIAG activa el modo de diagnóstico para el desinfectante especificado. Es posible establecer LOCAL_SANITIZE y LOCAL_SANITIZE_DIAG en valores diferentes, pero solo se habilitan las comprobaciones en LOCAL_SANITIZE. Si no se especifica una verificación en LOCAL_SANITIZE, pero se especifica en LOCAL_SANITIZE_DIAG, la verificación no está habilitada y no se proporcionan mensajes de diagnóstico.

A continuación, se muestra un ejemplo de la información proporcionada por la biblioteca de tiempo de ejecución de 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')

Desinfectante de direcciones de granos

De forma similar a los desinfectantes basados ​​en LLVM para los componentes del espacio de usuario, Android incluye el desinfectante de direcciones del núcleo (KASAN). KASAN es una combinación de kernel y modificaciones en el tiempo de compilación que dan como resultado un sistema instrumentado que permite un descubrimiento de errores y un análisis de la causa raíz más sencillos.

KASAN puede detectar muchos tipos de violaciones de memoria en el kernel. También puede detectar lecturas y escrituras fuera del límite en la pila, montón y variables globales, y puede detectar uso después de libre y doble libre.

Similar a ASAN, KASAN usa una combinación de instrumentación de función de memoria en tiempo de compilación y memoria de sombra para rastrear accesos a memoria en tiempo de ejecución. En KASAN, una octava parte del espacio de la memoria del kernel se dedica a la memoria oculta, que determina si un acceso a la memoria es válido o no.

KASAN es compatible con arquitecturas x86_64 y arm64. Ha sido parte del kernel ascendente desde 4.0 y se ha actualizado a kernels basados ​​en Android 3.18. KASAN se ha probado en kernels de Android compilados con gcc basados ​​en 4.9.2.

Además de KASAN, kcov es otra modificación del kernel que es útil para realizar pruebas. kcov fue desarrollado para permitir pruebas de fuzz guiadas por cobertura en el kernel. Mide la cobertura en términos de entradas de syscall y es útil con sistemas fuzzing, como syzkaller .

Implementación

Para compilar un kernel con KASAN y kcov habilitados, agregue los siguientes indicadores de compilación a la configuración de compilación de su kernel:

CONFIG_KASAN 
CONFIG_KASAN_INLINE 
CONFIG_TEST_KASAN 
CONFIG_KCOV 
CONFIG_SLUB 
CONFIG_SLUB_DEBUG 
CONFIG_CC_OPTIMIZE_FOR_SIZE

Y eliminando lo siguiente:

CONFIG_SLUB_DEBUG_ON 
CONFIG_SLUB_DEBUG_PANIC_ON 
CONFIG_KASAN_OUTLINE 
CONFIG_KERNEL_LZ4

Luego compile y actualice su kernel como de costumbre. El kernel de KASAN es considerablemente más grande que el original. Si corresponde, modifique los parámetros de arranque y la configuración del cargador de arranque para tener esto en cuenta.

Después de actualizar el kernel, verifique los registros de arranque del kernel para ver si KASAN está habilitado y en ejecución. El kernel se iniciará con información de mapa de memoria para KASAN, como por ejemplo:

...
[    0.000000] c0      0 Virtual kernel memory layout:
[    0.000000] c0      0     kasan   : 0xffffff8000000000 - 0xffffff9000000000   (    64 GB)
[    0.000000] c0      0     vmalloc : 0xffffff9000010000 - 0xffffffbdbfff0000   (   182 GB)
[    0.000000] c0      0     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000] c0      0               0xffffffbdc0000000 - 0xffffffbdc3f95400   (    63 MB actual)
[    0.000000] c0      0     PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000   (    16 MB)
[    0.000000] c0      0     fixed   : 0xffffffbffbdfd000 - 0xffffffbffbdff000   (     8 KB)
[    0.000000] c0      0     modules : 0xffffffbffc000000 - 0xffffffc000000000   (    64 MB)
[    0.000000] c0      0     memory  : 0xffffffc000000000 - 0xffffffc0fe550000   (  4069 MB)
[    0.000000] c0      0       .init : 0xffffffc001d33000 - 0xffffffc001dce000   (   620 KB)
[    0.000000] c0      0       .text : 0xffffffc000080000 - 0xffffffc001d32284   ( 29385 KB)
...

Y así es como se verá un error:

[   18.539668] c3      1 ==================================================================
[   18.547662] c3      1 BUG: KASAN: null-ptr-deref on address 0000000000000008
[   18.554689] c3      1 Read of size 8 by task swapper/0/1
[   18.559988] c3      1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G        W      3.18.24-xxx #1
[   18.569275] c3      1 Hardware name: Android Device
[   18.577433] c3      1 Call trace:
[   18.580739] c3      1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4
[   18.586985] c3      1 [<ffffffc00008b600>] show_stack+0x10/0x1c
[   18.592889] c3      1 [<ffffffc001481194>] dump_stack+0x74/0xc8
[   18.598792] c3      1 [<ffffffc000202ee0>] kasan_report+0x11c/0x4d0
[   18.605038] c3      1 [<ffffffc00020286c>] __asan_load8+0x20/0x80
[   18.611115] c3      1 [<ffffffc000bdefe8>] android_verity_ctr+0x8cc/0x1024
[   18.617976] c3      1 [<ffffffc000bcaa2c>] dm_table_add_target+0x3dc/0x50c
[   18.624832] c3      1 [<ffffffc001bdbe60>] dm_run_setup+0x50c/0x678
[   18.631082] c3      1 [<ffffffc001bda8c0>] prepare_namespace+0x44/0x1ac
[   18.637676] c3      1 [<ffffffc001bda170>] kernel_init_freeable+0x328/0x364
[   18.644625] c3      1 [<ffffffc001478e20>] kernel_init+0x10/0xd8
[   18.650613] c3      1 ==================================================================

Además, si los módulos están habilitados en su kernel, puede cargar el módulo de kernel test_kasan para realizar más pruebas. El módulo intenta accesos de memoria fuera de los límites y usa después de la liberación y es útil para probar KASAN en un dispositivo de destino.