AddressSanitizer (ASan) es una herramienta rápida basada en compiladores para detectar errores de memoria en código nativo.
ASan detecta:
- Desabastecimiento de búfer de pila
- Uso de pila después de liberación
- Uso de pila fuera del alcance
- Cierre doble o cierre wild
ASan se ejecuta en ARM de 32 y 64 bits, además de x86 y x86-64. Sobrecarga de la CPU de ASan es aproximadamente el doble, la sobrecarga del tamaño del código es entre el 50% y el doble, y una sobrecarga de memoria grande (depende de tus patrones de asignación, pero en el orden de 2x).
Android 10 y la rama principal de AOSP en AArch64 Ser compatible con AddressSanitizer asistido por hardware (HWASan) una herramienta similar con menor sobrecarga de RAM y un una variedad de errores detectados. HWASan detecta el uso de la pila después de la devolución, además de los errores. detectada 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 el valor es fijo en 0.4%. probabilidad de pasar por alto algún error. HWASan no tiene las zonas rojas de tamaño limitado de ASan para para detectar desbordamientos y cuarentenas de capacidad limitada para detectar por lo que no importa HWASan el tamaño del desbordamiento o cuánto tiempo hace se haya desasignado. Esto hace que HWASan sea mejor que ASan. Puedes leer más sobre el el diseño de HWASan o sobre el uso de HWASan en Android.
ASan detecta los desbordamientos globales o de pila además de los desbordamientos de montón, y es rápida con una sobrecarga mínima de memoria.
En este documento, se describe cómo compilar y ejecutar partes o todo el contenido de Android con San. Si estás compilando una app de SDK/NDK con ASan, consulta Address Sanitizer en su lugar.
Limpia ejecutables individuales con ASan
Agregar LOCAL_SANITIZE:=address
o sanitize: { address: true }
a
la regla de compilación del ejecutable. Puedes buscar en el código ejemplos existentes o encontrar
los demás desinfectantes disponibles.
Cuando se detecta un error, ASan imprime un informe detallado al
y a logcat
, y provoca una falla en el proceso.
Limpia las bibliotecas compartidas con ASan
Debido al funcionamiento de ASan, una biblioteca creada con ASan solo puede ser utilizada por una ejecutable de la aplicación que se compiló con ASan.
Para limpiar una biblioteca compartida que se usa en varios ejecutables, no todas
que se compilan con ASan, necesitas dos copias de la biblioteca. El
La forma recomendada de hacerlo 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
en lugar de
/system/lib
Luego, ejecuta el ejecutable con lo siguiente:
LD_LIBRARY_PATH=/system/lib/asan
Para daemons del sistema, agrega lo siguiente a la sección correspondiente de
/init.rc
o /init.$device$.rc
.
setenv LD_LIBRARY_PATH /system/lib/asan
Verifica que el proceso use bibliotecas de /system/lib/asan
cuando está presente leyendo /proc/$PID/maps
. Si no es así, tal vez debas
para inhabilitar 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 usa un desenredador rápido basado en punteros de marco para grabar una pila hacer un seguimiento de cada evento de asignación y desasignación de memoria en el programa. Más probable de Android se compila sin punteros de marco. Como resultado, a menudo obtienes solo uno o dos fotogramas significativos. Para solucionar este problema, vuelve a compilar la biblioteca con ASan (recomendado) o con:
LOCAL_CFLAGS:=-fno-omit-frame-pointer LOCAL_ARM_MODE:=arm
O bien, establece ASAN_OPTIONS=fast_unwind_on_malloc=0
en el proceso
en un entorno de nube. Estos últimos pueden consumir
muchos recursos de CPU, según
la carga.
Simbolización
Inicialmente, los informes de ASan contienen referencias a desplazamientos en objetos binarios y compartidos bibliotecas. Hay dos maneras de obtener información del archivo fuente y de la línea:
- Asegúrate de que el objeto binario
llvm-symbolizer
esté presente en/system/bin
.llvm-symbolizer
se compila a partir de fuentes dethird_party/llvm/tools/llvm-symbolizer
- Filtra el informe a través de
external/compiler-rt/lib/asan/scripts/symbolize.py
secuencia de comandos.
El segundo enfoque puede proporcionar más datos (es decir, file:line
ubicaciones) debido a
la disponibilidad de bibliotecas simbolizadas en el host.
ASan en apps
ASan no puede ver el código Java, pero puede detectar errores en la JNI
bibliotecas. Para eso, debes compilar el ejecutable con ASan, que en
este caso es /system/bin/app_process(32|64)
. Esta
habilita ASan en todas las apps del dispositivo al mismo tiempo, que es una
una carga pesada, pero un dispositivo con 2 GB de RAM debería poder admitirla.
Agregar LOCAL_SANITIZE:=address
a
la regla de compilación app_process
en frameworks/base/cmds/app_process
. Ignorar
el destino app_process__asan
en el mismo archivo por ahora (si es
que seguimos ahí en el momento en que leíste esto).
Edita la sección service zygote
de
archivo system/core/rootdir/init.zygote(32|64).rc
apropiado para agregar
las siguientes líneas al bloque de líneas con sangría que contienen class main
, también
con sangría de la misma cantidad:
setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib setenv ASAN_OPTIONS allow_user_segv_handler=true
Compilación, sincronización de adb, inicio rápido de flash y reinicio.
Cómo usar la propiedad de unión
El enfoque de la sección anterior coloca a ASan en cada en el sistema (de hecho, en cada descendiente del proceso). Es posible ejecutar solo una (o varias) apps con ASan, y cambiar algo de sobrecarga de memoria por un inicio más lento de la app.
Para ello, inicia la app con la propiedad wrap.
.
En el siguiente ejemplo, se ejecuta la app de 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
.
a /system/bin/asan/app_process
, que se compila con
San. También agrega /system/lib/asan
al comienzo de
la ruta de búsqueda dinámica de bibliotecas. De esta manera, ASan utilizó
se prefieren las bibliotecas de /system/lib/asan
en lugar de las bibliotecas normales
en /system/lib
cuando se ejecuta con asanwrapper
.
Si se encuentra un error, la aplicación falla y se imprime el informe en el registro.
SANITIZE_TARGET
Android 7.0 y las versiones posteriores permiten compilar toda la plataforma de Android con ASan de una vez. (Si estás compilando una versión posterior a Android 9, HWASan es una mejor opción).
Ejecuta 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 se debe
en la memoria flash del dispositivo. Usa la siguiente línea de comandos:
fastboot flash userdata && fastboot flashall
Esto compila dos conjuntos de bibliotecas compartidas: normal en
/system/lib
(la primera invocación de Make) y ASan instrumentada en
/data/asan/lib
(la segunda invocación de Make). Se pueden ejecutar desde
la segunda compilación reemplazará a los de la primera. Instrumentado por ASan
obtienen una ruta de búsqueda de biblioteca diferente que incluye
/data/asan/lib
antes del /system/lib
mediante el uso de
/system/bin/linker_asan
en PT_INTERP
El sistema de compilación bloquea los directorios de objetos intermedios cuando
Cambió el valor de $SANITIZE_TARGET
. Esto fuerza una reconstrucción de todos
objetivos y, al mismo tiempo, preserva los objetos binarios instalados en /system/lib
.
Algunos destinos no pueden crearse con ASan:
- Archivos ejecutables vinculados de forma estática
LOCAL_CLANG:=false
objetivos- No se aceptan
LOCAL_SANITIZE:=false
enSANITIZE_TARGET=address
Los ejecutables como estos se omiten en la compilación SANITIZE_TARGET
, y el
versión de la primera invocación de Make se conserva en /system/bin
.
Las bibliotecas de este tipo se compilan sin ASan. Pueden contener un poco de ASan de las bibliotecas estáticas de las que dependen.