Google is committed to advancing racial equity for Black communities. See how.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

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 gran sobrecarga de memoria (depende de sus patrones de asignación, pero del orden de 2x).

Android 10 y la rama maestra de AOSP en AArch64 admiten ASan acelerado por hardware (HWASan) , una herramienta similar con una sobrecarga de RAM más baja y una mayor variedad 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 similar de CPU y tamaño de código, 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 el uso después de la ausencia, por lo que no le importa a HWASan qué tan 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 compilar y ejecutar partes o todo Android con ASan. Si está creando una aplicación SDK / NDK con ASan, consulte Address Sanitizer en su lugar.

Desinfectar ejecutables individuales con ASan

Agregue LOCAL_SANITIZE:=address o sanitize: { address: true } a la regla de compilación del 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 como en logcat y luego 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 agregar lo siguiente a Android.mk para el módulo en cuestión:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

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

LD_LIBRARY_PATH=/system/lib/asan

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

setenv LD_LIBRARY_PATH /system/lib/asan

Verifique que el proceso esté usando bibliotecas de /system/lib/asan cuando /system/lib/asan presente leyendo /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 seguimientos 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 se crea sin punteros de marco. Como resultado, a menudo obtiene solo uno o dos marcos significativos. Para solucionar este problema, reconstruya la biblioteca con ASan (¡recomendado!), O con:

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

O configure ASAN_OPTIONS=fast_unwind_on_malloc=0 en el entorno del proceso. Este último puede consumir mucho 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 el binario llvm-symbolizer esté presente en /system/bin . llvm-symbolizer se llvm-symbolizer partir de fuentes en third_party/llvm/tools/llvm-symbolizer .
  • Filtre el informe a través del script external/compiler-rt/lib/asan/scripts/symbolize.py .

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

ASan en aplicaciones

ASan no puede ver el código Java, pero puede detectar errores en las bibliotecas JNI. Para eso, necesita compilar 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.

Agregue LOCAL_SANITIZE:=address a la app_process compilación app_process en frameworks/base/cmds/app_process . Ignore el destino app_process__asan en el mismo archivo por ahora (si todavía está allí en el momento de leer esto).

Edite la sección de service zygote system/core/rootdir/init.zygote( 32|64 ).rc archivo apropiado system/core/rootdir/init.zygote( 32|64 ).rc para agregar las siguientes líneas al bloque de líneas sangradas que contienen la class main , también sangradas por 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 todas las aplicaciones del sistema (en realidad, en todos los descendientes del proceso Zygote). Es posible ejecutar solo una (o varias) aplicaciones con ASan, intercambiando algo de memoria por un inicio más lento de la aplicación.

Esto se puede hacer iniciando 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 reescribe /system/bin/app_process en /system/bin/asan/app_process , que está construido con ASan. También agrega /system/lib/asan al comienzo de la ruta de búsqueda de la biblioteca dinámica. De esta manera, las bibliotecas instrumentadas en ASan de /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 incluyen 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 también debe actualizarse al dispositivo. Utilice la siguiente línea de comando:

fastboot flash userdata && fastboot flashall

Esto crea dos conjuntos de bibliotecas compartidas: normal en /system/lib (la primera invocación de make) y ASan instrumentado en /data/asan/lib (la segunda invocación de make). Los ejecutables de la segunda compilación sobrescriben a los de la primera compilación. Los ejecutables instrumentados en ASan obtienen una ruta de búsqueda de biblioteca diferente que incluye /data/asan/lib antes de /system/lib mediante el uso de /system/bin/linker_asan en PT_INTERP .

El sistema de compilación golpea los directorios de objetos intermedios cuando el valor de $SANITIZE_TARGET ha cambiado. Esto fuerza una reconstrucción de todos los destinos conservando los binarios instalados en /system/lib .

Algunos objetivos no se pueden construir con ASan:

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

Los ejecutables como estos se omiten en la compilación SANITIZE_TARGET , y la versión de la primera invocación de make se deja en /system/bin .

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

Documentación de apoyo