Las secciones de código ejecutable para los objetos binarios del sistema AArch64 están marcadas de forma predeterminada de solo ejecución (no legible) como una mitigación más fortalecida contra el código justo a tiempo y reutilizar los ataques. Código que mezcle datos y código, y código que intencionalmente inspecciona estas secciones (sin volver a asignar primero los segmentos de la memoria como legibles) ya no funcionan. Apps con un SDK de destino de 10 (nivel de API 29 o versiones posteriores) se verán afectadas si la aplicación intenta leer secciones de código de bibliotecas de sistema habilitadas para memoria de solo ejecución (XOM) en la memoria sin antes y marca la sección como legible.
Para aprovechar al máximo esta mitigación, se requiere la compatibilidad con el hardware y el kernel como en los productos necesarios. Sin esta compatibilidad, la mitigación solo se podría aplicar de manera parcial. El El kernel común de Android 4.9 contiene los parches adecuados para brindar compatibilidad con esto en dispositivos ARMv8.2.
Implementación
Los objetos binarios AArch64 generados por el compilador suponen que el código y los datos entremezclados. Habilitar esta función no afecta negativamente el rendimiento de el dispositivo.
Para código que tiene que realizar una introspección intencional de la memoria en su
ejecutables, se recomienda llamar a mprotect
en el
o segmentos de código que se deben inspeccionar para que sean legibles y, luego,
para evitar la legibilidad cuando se complete la inspección.
Esta implementación genera lecturas en segmentos de memoria marcados como
solo de ejecución para provocar una falla de segmentación (SEGFAULT
).
Esto puede ocurrir como resultado de un error, una vulnerabilidad, una mezcla de datos
código (reducción literal) o introspección intencional de la memoria.
Impacto y compatibilidad de los dispositivos
Dispositivos con hardware o kernels anteriores (anteriores a la versión 4.9) sin el dispositivo
es posible que los parches necesarios no sean totalmente compatibles con esta función o que no se beneficien de ella. Dispositivos
sin compatibilidad con kernel puede no imponer el acceso de usuarios a memoria de solo ejecución
Sin embargo, el código del kernel que verifica explícitamente si una página es legible podría igualmente
aplicar esta propiedad, como process_vm_readv()
.
La marca CONFIG_ARM64_UAO
del kernel debe configurarse en el kernel para
asegúrate de que el kernel respete las páginas de userland marcadas como de solo ejecución. ARMv8 anterior
o los dispositivos ARMv8.2 con anulación de acceso del usuario (UAO) inhabilitada, no pueden
aprovechar esto y es posible que aún puedan leer páginas de solo ejecución con
llamadas de sistema.
Cómo refactorizar código existente
El código que ha sido transferido de AArch32 puede contener datos entrelazados y
código, lo que causa que surjan problemas. En muchos casos, solucionar estos problemas es tan simple
como mover las constantes a una sección .data
en el archivo de ensamblado.
Es posible que el ensamblaje escrito a mano deba refactorizarse para separar las agrupaciones locales constantes.
Ejemplos:
Los objetos binarios que genera el compilador Clang no deberían tener problemas con los datos. que se entremezclan en el código. Si el código generado por la colección del compilador GNU (GCC) se incluido (de una biblioteca estática), inspeccionarás el objeto binario de salida para asegurarse de que las constantes no se hayan agrupado en secciones de código.
Si es necesaria la introspección de código en secciones de código ejecutable,
primero, llama a mprotect
para marcar el código como legible. Luego, después de la operación
se completó, llama nuevamente a mprotect
para marcarlo como ilegible.
Habilitar XOM
La opción de solo ejecución está habilitada de forma predeterminada para todos los objetos binarios de 64 bits de la compilación en un sistema de archivos.
Inhabilitar XOM
Puedes inhabilitar el modo de solo ejecución a nivel de módulo, mediante un árbol de subdirectorios completo, o de forma global para una compilación completa.
XOM se puede inhabilitar para módulos individuales que no se pueden refactorizar o que deben leer su
ejecutable, estableciendo LOCAL_XOM
y las variables xom
a false
.
// Android.mk LOCAL_XOM := false // Android.bp cc_binary { // or other module types ... xom: false, }
Si la memoria de solo ejecución está inhabilitada en una biblioteca estática, se aplica el sistema de compilación
esto a todos los módulos dependientes de esa biblioteca estática. Puedes anular
usando xom: true,
.
Para inhabilitar la memoria de solo ejecución en un subdirectorio en particular (por ejemplo,
foo/bar/), pasa el valor a XOM_EXCLUDE_PATHS
.
make -j XOM_EXCLUDE_PATHS=foo/bar
También puedes establecer el PRODUCT_XOM_EXCLUDE_PATHS
variable en la configuración del producto.
Puedes inhabilitar los objetos binarios de solo ejecución globalmente si pasas
ENABLE_XOM=false
al comando make
.
make -j ENABLE_XOM=false
Validación
No hay pruebas de CTS ni de verificación disponibles para pruebas de solo ejecución
memoria. Puedes verificar los objetos binarios de forma manual con readelf
y comprobando
las marcas de segmento.