Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Dirección Sanitizador

AddressSanitizer (ASan) es una herramienta rápida basada en un compilador para detectar errores de memoria en código nativo.

ASan detecta:

  • Desbordamiento / subdesbordamiento del búfer de pila y montón
  • Uso del montón después de gratis
  • Uso de la pila fuera del alcance
  • Doble libre / salvaje libre

ASan se ejecuta en ARM de 32 y 64 bits, además de x86 y x86-64. La sobrecarga de la CPU de ASan es aproximadamente 2x, la sobrecarga del tamaño del código está entre 50% y 2x, y una sobrecarga de memoria grande (depende de sus patrones de asignación, pero del orden de 2x).

Android 10 y la rama principal AOSP en apoyo AArch64 ASAN acelerado en hardware (Hwasan) , una herramienta similar con una menor sobrecarga de RAM y una mayor gama de errores detectados. HWASan detecta el uso de la pila después de la devolución, además de los errores detectados por ASan.

HWASan tiene una sobrecarga de CPU y tamaño de código similar, pero una sobrecarga de RAM mucho menor (15%). HWASan no es determinista. Solo hay 256 valores de etiqueta posibles, por lo que hay una probabilidad plana del 0,4% de perder algún error. HWASan no tiene zonas rojas de tamaño limitado de ASan para detectar desbordamientos y cuarentena de capacidad limitada para detectar uso después de la ausencia, por lo que no le importa a HWASan cuán grande sea el desbordamiento o cuánto tiempo hace que se desasignó la memoria. Esto hace que HWASan sea mejor que ASan. Puede leer más sobre el diseño de Hwasan o sobre el uso de Hwasan en Android .

ASan detecta desbordamientos de pila / globales además de desbordamientos de pila, y es rápido con una sobrecarga de memoria mínima.

Este documento describe cómo construir y ejecutar partes / todo Android con ASan. Si usted está construyendo un SDK / NDK aplicación con Asan, consulte Dirección desinfectante en su lugar.

Desinfectar ejecutables individuales con ASan

Añadir LOCAL_SANITIZE:=address o sanitize: { address: true } a la regla de construcción para el ejecutable. Puede buscar en el código ejemplos existentes o encontrar otros desinfectantes disponibles.

Cuando se detecta un error, Asan imprime un informe detallado tanto en la salida estándar y para logcat y luego se bloquea el proceso.

Desinfectar bibliotecas compartidas con ASan

Debido a la forma en que funciona ASan, una biblioteca construida con ASan solo puede ser utilizada por un ejecutable construido con ASan.

Para desinfectar una biblioteca compartida que se usa en varios ejecutables, no todos los cuales están construidos con ASan, necesita dos copias de la biblioteca. La forma recomendada de hacer esto es añadir lo siguiente a Android.mk para el módulo en cuestión:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Esto pone a la biblioteca en /system/lib/asan en lugar de /system/lib . Luego, ejecute su ejecutable con:

LD_LIBRARY_PATH=/system/lib/asan

Para los demonios del sistema, añada lo siguiente a la sección correspondiente de /init.rc o /init.$device$.rc .

setenv LD_LIBRARY_PATH /system/lib/asan

Compruebe que el proceso está utilizando bibliotecas de /system/lib/asan cuando está presente por la lectura /proc/$PID/maps . Si no es así, es posible que deba deshabilitar SELinux:

adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

Mejores trazas de pila

ASan utiliza un desbobinador rápido basado en puntero de cuadro para registrar un seguimiento de la pila para cada evento de asignación y desasignación de memoria en el programa. La mayor parte de Android está construido sin punteros de marco. Como resultado, a menudo obtiene solo uno o dos marcos significativos. Para solucionar esto, reconstruya la biblioteca con ASan (¡recomendado!), O con:

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

O conjunto ASAN_OPTIONS=fast_unwind_on_malloc=0 en el entorno del proceso. Este último puede ser muy intensivo en la CPU, dependiendo de la carga.

Simbolización

Inicialmente, los informes de ASan contienen referencias a compensaciones en binarios y bibliotecas compartidas. Hay dos formas de obtener información de línea y archivo de origen:

  • Asegúrese de que la llvm-symbolizer binario está presente en /system/bin . llvm-symbolizer se construye a partir de fuentes de third_party/llvm/tools/llvm-symbolizer .
  • Filtrar el informe a través de la external/compiler-rt/lib/asan/scripts/symbolize.py guión.

El segundo enfoque puede proporcionar más datos (es decir, file:line ubicaciones) debido a la disponibilidad de las bibliotecas simbolizados en el host.

ASan en aplicaciones

ASan no puede ver el código Java, pero puede detectar errores en las bibliotecas JNI. Por eso, es necesario para construir el ejecutable con Asan, que en este caso es /system/bin/app_process( 32|64 ) . Esto habilita ASan en todas las aplicaciones del dispositivo al mismo tiempo, lo cual es una carga pesada, pero un dispositivo con 2 GB de RAM debería poder manejar esto.

Añadir LOCAL_SANITIZE:=address a la app_process regla de generación de frameworks/base/cmds/app_process . Ignorar el app_process__asan de destino en el mismo archivo, por ahora (si todavía está allí en el momento de leer esto).

Editar el service zygote sección del apropiado system/core/rootdir/init.zygote( 32|64 ).rc archivo para agregar las líneas siguientes al bloque de líneas indentadas que contienen class main , también con sangría en la misma cantidad:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

Compile, adb sync, fastboot flash boot y reinicie.

Usando la propiedad wrap

El enfoque de la sección anterior coloca ASan en cada aplicación del sistema (en realidad, en cada descendiente del proceso Zygote). Es posible ejecutar solo una (o varias) aplicaciones con ASan, intercambiando un poco de sobrecarga de memoria por un inicio más lento de la aplicación.

Esto se puede hacer por iniciar su aplicación con la wrap. propiedad. El siguiente ejemplo ejecuta la aplicación Gmail en ASan:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

En este contexto, asanwrapper vuelve a escribir /system/bin/app_process al /system/bin/asan/app_process , que se construye con Asan. También agrega /system/lib/asan en el inicio de la ruta de búsqueda de biblioteca dinámica. De esta manera las bibliotecas ASAN-instrumentado desde /system/lib/asan se prefieren a las bibliotecas normales en /system/lib cuando se ejecuta con asanwrapper .

Si se encuentra un error, la aplicación se bloquea y el informe se imprime en el registro.

SANITIZE_TARGET

Android 7.0 y superior incluye soporte para construir toda la plataforma Android con ASan a la vez. (Si está creando una versión superior a Android 9, HWASan es una mejor opción).

Ejecute los siguientes comandos en el mismo árbol de compilación.

make -j42
SANITIZE_TARGET=address make -j42

En este modo, userdata.img contiene bibliotecas adicionales y deben ser trasladadas a las que el dispositivo también. Utilice la siguiente línea de comando:

fastboot flash userdata && fastboot flashall

Esto crea dos conjuntos de bibliotecas compartidas: normal /system/lib (la primera marca de invocación), y Asan-instrumentada en /data/asan/lib (la segunda marca de invocación). Los ejecutables de la segunda compilación sobrescriben a los de la primera compilación. Ejecutables instrumentados Asan obtener una ruta de búsqueda de biblioteca diferente que incluye /data/asan/lib antes /system/lib a través del uso de /system/bin/linker_asan en PT_INTERP .

Los clobbers sistema de acumulación directorios de objetos intermedios cuando el $SANITIZE_TARGET valor ha cambiado. Esto obliga a una reconstrucción de todos los objetivos preservando al mismo tiempo los binarios instalados en /system/lib .

Algunos objetivos no se pueden construir con ASan:

  • Ejecutables vinculados estáticamente
  • LOCAL_CLANG:=false objetivos
  • LOCAL_SANITIZE:=false no se ASan'd para SANITIZE_TARGET=address

Ejecutables como estos se omiten en el SANITIZE_TARGET acumulación, y la versión de la primera invocación maquillaje se deja en /system/bin .

Las bibliotecas como esta se crean sin ASan. Pueden contener algo de código ASan de las bibliotecas estáticas de las que dependen.

Documentación de apoyo