Extensión de etiquetado de memoria de Arm (MTE)

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

¿Por qué usar MTE?

Los errores de seguridad de la memoria, que son errores en el manejo de la memoria en lenguajes de programación nativos, son problemas de código comunes. Estos generan vulnerabilidades de seguridad y problemas de estabilidad.

Armv9 introdujo la extensión de etiquetado de memoria (MTE) de Arm, una extensión de hardware que te permite detectar errores de uso luego de la liberación y del desbordamiento de búfer en tu código nativo.

Verifica la compatibilidad

A partir de Android 13, ciertos dispositivos son compatibles con MTE. Para verificar si tu dispositivo es compatible con MTE, ejecuta el siguiente comando:

adb shell grep mte /proc/cpuinfo

Si el resultado es Features : [...] mte, tu dispositivo se ejecuta con MTE habilitada.

Algunos dispositivos no habilitan MTE de forma predeterminada, pero permiten que los desarrolladores los reinicien con MTE habilitada. Esta es una configuración experimental que no se recomienda para el uso normal, ya que puede disminuir el rendimiento o la estabilidad del dispositivo, pero que puede ser útil para el desarrollo de apps. Para acceder a este modo, ve a Opciones para desarrolladores > Extensión de etiquetado de mem. en la app de Configuración. Si esta opción no está presente, el dispositivo no admite la habilitación de MTE de esta manera.

Modos de operación de MTE

MTE admite dos modos: SYNC y ASYNC. El modo SYNC proporciona mejor información de diagnóstico y, por lo tanto, es más adecuado para fines de desarrollo, mientras que el modo ASYNC tiene un alto rendimiento que le permite habilitarse para apps que ya se hayan lanzado.

Modo síncrono (SYNC)

Este modo está optimizado para la depuración por sobre el rendimiento y se puede usar como una herramienta de detección de errores precisa, cuando se acepta una sobrecarga de rendimiento mayor. Cuando MTE SYNC está habilitada, también actúa como mitigación de seguridad.

En una discrepancia de etiqueta, el procesador finaliza el proceso en la carga o la instrucción de almacenamiento incorrecta con SIGSEGV (con si_code SEGV_MTESERR) y la información completa sobre el acceso a la memoria y la dirección con errores.

Este modo resulta útil durante las pruebas como una alternativa más rápida a HWASan que no requiere volver a compilar el código, o bien durante la producción cuando la app representa una superficie vulnerable a ataques. Además, cuando el modo ASYNC (descrito a continuación) encuentra un error, se puede obtener un informe de errores preciso con el uso de las APIs de entorno de ejecución para cambiar la ejecución al modo SYNC.

Por otra parte, cuando se ejecuta en modo SYNC, el asignador de Android registra el seguimiento de pila de cada asignación y desasignación, y los usa para proporcionar mejores informes de errores que incluyen una explicación de un error de memoria, como usar después de liberar y de desbordamiento de búfer, y los seguimientos de pila de los eventos de memoria relevantes (consulta Información sobre los informes de MTE para obtener más detalles). Esos informes proporcionan más información contextual y hacen que los errores sean más fáciles de rastrear y corregir que en el modo ASYNC.

Modo asíncrono (ASYNC)

Este modo está optimizado para el rendimiento por sobre la exactitud de los informes de errores y se puede usar para detectar errores de seguridad de memoria de baja sobrecarga. En una discrepancia de etiqueta, el procesador continúa la ejecución hasta la entrada de kernel más cercana (como una llamada de sistema o interrupción del temporizador), donde finaliza el proceso con SIGSEGV (código SEGV_MTEAERR) sin registrar la dirección o el acceso a la memoria con errores.

Este modo es útil para mitigar las vulnerabilidades de seguridad de la memoria durante la producción en bases de código probadas donde se sabe que la densidad de errores de seguridad de la memoria es baja, lo que se logra mediante el uso del modo SYNC durante las pruebas.

Cómo habilitar MTE para la experimentación

Durante la experimentación, los cambios de compatibilidad de la app se pueden usar para establecer el valor predeterminado del atributo memtagMode (ver a continuación) para una aplicación que no especifica ningún valor en el manifiesto (o especifica "default").

Puedes encontrarlas en Sistema > Avanzado > Opciones para desarrolladores > Cambios de compatibilidad con apps en el menú de configuración global. La configuración de NATIVE_MEMTAG_ASYNC o NATIVE_MEMTAG_SYNC habilita MTE para una aplicación en particular.

Como alternativa, esto se puede configurar mediante el comando am de la siguiente manera:

$ adb shell am compat enable NATIVE_MEMTAG_[A]SYNC my.app.name

Ejecuta tu app

Una vez que habilites MTE, usa y prueba tu app con normalidad. Si se detecta un problema de seguridad de la memoria, tu app falla con una tombstone que se ve de la siguiente manera (ten en cuenta SIGSEGV con SEGV_MTESERR para SYNC o SEGV_MTEAERR para ASYNC):

pid: 13935, tid: 13935, name: sanitizer-statu  >>> sanitizer-status <<<
uid: 0
tagged_addr_ctrl: 000000000007fff3
signal 11 (SIGSEGV), code 9 (SEGV_MTESERR), fault addr 0x800007ae92853a0
Cause: [MTE]: Use After Free, 0 bytes into a 32-byte allocation at 0x7ae92853a0
x0  0000007cd94227cc  x1  0000007cd94227cc  x2  ffffffffffffffd0  x3  0000007fe81919c0
x4  0000007fe8191a10  x5  0000000000000004  x6  0000005400000051  x7  0000008700000021
x8  0800007ae92853a0  x9  0000000000000000  x10 0000007ae9285000  x11 0000000000000030
x12 000000000000000d  x13 0000007cd941c858  x14 0000000000000054  x15 0000000000000000
x16 0000007cd940c0c8  x17 0000007cd93a1030  x18 0000007cdcac6000  x19 0000007fe8191c78
x20 0000005800eee5c4  x21 0000007fe8191c90  x22 0000000000000002  x23 0000000000000000
x24 0000000000000000  x25 0000000000000000  x26 0000000000000000  x27 0000000000000000
x28 0000000000000000  x29 0000007fe8191b70
lr  0000005800eee0bc  sp  0000007fe8191b60  pc  0000005800eee0c0  pst 0000000060001000

backtrace:
      #00 pc 00000000000010c0  /system/bin/sanitizer-status (test_crash_malloc_uaf()+40) (BuildId: 953fc93301472d0b72709b2b9a9f6f30)
      #01 pc 00000000000014a4  /system/bin/sanitizer-status (test(void (*)())+132) (BuildId: 953fc93301472d0b72709b2b9a9f6f30)
      #02 pc 00000000000019cc  /system/bin/sanitizer-status (main+1032) (BuildId: 953fc93301472d0b72709b2b9a9f6f30)
      #03 pc 00000000000487d8  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+96) (BuildId: 6ab39e35a2fae7efbe9a04e9bbb14331)

deallocated by thread 13935:
      #00 pc 000000000004643c  /apex/com.android.runtime/lib64/bionic/libc.so (scudo::Allocator<scudo::AndroidConfig, &(scudo_malloc_postinit)>::quarantineOrDeallocateChunk(scudo::Options, void*, scudo::Chunk::UnpackedHeader*, unsigned long)+688) (BuildId: 6ab39e35a2fae7efbe9a04e9bbb14331)
      #01 pc 00000000000421e4  /apex/com.android.runtime/lib64/bionic/libc.so (scudo::Allocator<scudo::AndroidConfig, &(scudo_malloc_postinit)>::deallocate(void*, scudo::Chunk::Origin, unsigned long, unsigned long)+212) (BuildId: 6ab39e35a2fae7efbe9a04e9bbb14331)
      #02 pc 00000000000010b8  /system/bin/sanitizer-status (test_crash_malloc_uaf()+32) (BuildId: 953fc93301472d0b72709b2b9a9f6f30)
      #03 pc 00000000000014a4  /system/bin/sanitizer-status (test(void (*)())+132) (BuildId: 953fc93301472d0b72709b2b9a9f6f30)

allocated by thread 13935:
      #00 pc 0000000000042020  /apex/com.android.runtime/lib64/bionic/libc.so (scudo::Allocator<scudo::AndroidConfig, &(scudo_malloc_postinit)>::allocate(unsigned long, scudo::Chunk::Origin, unsigned long, bool)+1300) (BuildId: 6ab39e35a2fae7efbe9a04e9bbb14331)
      #01 pc 0000000000042394  /apex/com.android.runtime/lib64/bionic/libc.so (scudo_malloc+36) (BuildId: 6ab39e35a2fae7efbe9a04e9bbb14331)
      #02 pc 000000000003cc9c  /apex/com.android.runtime/lib64/bionic/libc.so (malloc+36) (BuildId: 6ab39e35a2fae7efbe9a04e9bbb14331)
      #03 pc 00000000000010ac  /system/bin/sanitizer-status (test_crash_malloc_uaf()+20) (BuildId: 953fc93301472d0b72709b2b9a9f6f30)
      #04 pc 00000000000014a4  /system/bin/sanitizer-status (test(void (*)())+132) (BuildId: 953fc93301472d0b72709b2b9a9f6f30)
Learn more about MTE reports: https://source.android.com/docs/security/test/memory-safety/mte-report

Consulta Información sobre los informes de MTE en la documentación de AOSP para obtener más detalles.