As seções de código executáveis dos binários do sistema AArch64 são marcadas por padrão somente execução (não legível) como uma mitigação de aumento da proteção contra o código just-in-time reutilização de ataques. Códigos que combinam dados e código e códigos que intencionalmente inspeciona essas seções (sem primeiro remapear os segmentos de memória como legíveis) não funcionam mais. Apps com um SDK desejado de 10 (nível 29 da API ou mais recente) serão afetadas se o app tentar ler seções de código com memória somente de execução (XOM, na sigla em inglês) com as bibliotecas do sistema ativadas na memória marcando a seção como legível.
Para se beneficiar plenamente dessa mitigação, o suporte a hardware e kernel é obrigatórios. Sem esse suporte, a mitigação pode ser aplicada apenas parcialmente. A O kernel comum do Android 4.9 contém os patches apropriados para fornecer suporte para isso em dispositivos ARMv8.2.
Implementação
Os binários AArch64 gerados pelo compilador presumem que o código e os dados não são misturadas. A ativação desse recurso não afeta negativamente o desempenho da o dispositivo.
Para um código que precisa realizar introspecção intencional da memória em seu
segmentos executáveis, é aconselhável chamar mprotect
no
segmentos de código que exigem inspeção para serem legíveis, então
e remover a legibilidade quando a inspeção for concluída.
Essa implementação faz com que leituras em segmentos de memória marcados como
somente execução para resultar em uma falha de segmentação (SEGFAULT
).
Isso pode ocorrer como resultado de um bug, vulnerabilidade, dados misturados com
(pooling literal) ou introspecção intencional da memória.
Compatibilidade e impacto do dispositivo
Dispositivos com hardware anterior ou kernels anteriores (anteriores à versão 4.9) sem a
os patches necessários talvez não ofereçam suporte ou se beneficiem totalmente desse recurso. Dispositivos
sem suporte ao kernel pode não impor acesso do usuário à memória somente de execução,
No entanto, o código do kernel que verifica explicitamente se uma página é legível ainda pode
aplicar essa propriedade, como process_vm_readv()
.
A flag CONFIG_ARM64_UAO
precisa ser definida no kernel para
certifique-se de que o kernel respeite as páginas do userland marcadas como somente execução. ARMv8 anterior
ou ARMv8.2 com a Substituição de acesso do usuário (UAO) desativada, não podem
aproveitar esse recurso e ler páginas somente de execução usando
chamadas do sistema.
Refatorar um código existente
O código que foi transferido do AArch32 pode conter dados misturados e
no código, causando problemas. Em muitos casos, corrigir esses problemas é tão simples
como mover as constantes para uma seção .data
no arquivo assembly.
A montagem escrita à mão pode precisar ser refatorada para separar os conjuntos locais constantes.
Exemplos:
Os binários gerados pelo compilador Clang não devem ter problemas com dados misturados no código. Se o código gerado da coleção do compilador GNU (GCC) for incluído (de uma biblioteca estática), inspecione o binário de saída para garantir que as constantes não sejam agrupadas em seções de código.
Se a introspecção do código for necessária em seções de código executável,
chame mprotect
para marcar o código como legível. Depois que a operação
for concluída, chame mprotect
novamente para marcá-la como ilegível.
Ativar XOM
Somente execução é ativado por padrão para todos os binários de 64 bits no build sistema.
Desativar XOM
Você pode desativar somente execução em um nível de módulo, por uma árvore de subdiretório inteira ou globalmente para um build inteiro.
O XOM pode ser desativado para módulos individuais que não podem ser refatorados ou que precisam ler
código executável, definindo a propriedade LOCAL_XOM
e variáveis xom
para false
.
// Android.mk LOCAL_XOM := false // Android.bp cc_binary { // or other module types ... xom: false, }
Se a memória somente de execução estiver desativada em uma biblioteca estática, o sistema de build aplicará
para todos os módulos dependentes dessa biblioteca estática. É possível modificar
isso usando xom: true,
.
Para desativar a memória somente de execução em um subdiretório específico (por exemplo,
foo/bar/), transmita o valor para XOM_EXCLUDE_PATHS
.
make -j XOM_EXCLUDE_PATHS=foo/bar
Como alternativa, defina o PRODUCT_XOM_EXCLUDE_PATHS
na configuração do produto.
É possível desativar os binários somente de execução globalmente transmitindo
ENABLE_XOM=false
ao comando make
.
make -j ENABLE_XOM=false
Validação
Não há testes de CTS ou de verificação disponíveis somente para execução
memória. Verifique os binários manualmente usando readelf
e checando
as sinalizações de segmento.