A partir do Android 11, para processos de 64 bits, todas as alocações de heap têm uma tag definida pela implementação definida no byte superior do ponteiro em dispositivos com suporte de kernel para ARM Top-byte Ignore (TBI). Qualquer app que modifique essa tag é encerrado quando ela é verificada durante a dealocação. Isso é necessário para hardwares futuros com suporte à ARM Memory Tagging Extension (MTE).
Ignorar o byte superior
O recurso Top-byte Ignore do ARM está disponível para códigos de 64 bits em todos os hardwares Armv8 AArch64. Esse recurso significa que o hardware ignora o byte superior de um ponteiro ao acessar a memória.
O TBI exige um kernel compatível que processe corretamente os ponteiros marcados transmitidos do espaço do usuário. Os kernels comuns do Android a partir da versão 4.14 (Pixel 4) têm os patches TBI necessários.
Dispositivos com suporte ao TBI no kernel são detectados de forma dinâmica no início do processo, e uma tag dependente da implementação é inserida no byte superior do ponteiro para todas as alocações de heap. Depois disso, uma verificação é executada para garantir que a tag não foi truncada ao desalocar a memória.
Prontidão da Memory Tagging Extension
A Memory Tagging Extension (MTE) do ARM ajuda a resolver problemas de segurança na memória. A MTE funciona marcando os bits de endereço 56 a 59 de cada alocação de memória na pilha, no heap e nas variáveis globais. O hardware e o conjunto de instruções verificam automaticamente se a tag correta é usada em cada acesso à memória.
Os apps Android que armazenam informações incorretamente no byte superior do ponteiro vão falhar em um dispositivo com MTE. Os ponteiros marcados facilitam a detecção e o descarte de usos incorretos do byte superior do ponteiro antes que os dispositivos MTE estejam disponíveis.
Suporte para desenvolvedores
Se o app travou e você recebeu este link, isso pode significar uma das seguintes situações:
- O app tentou liberar um ponteiro que não foi alocado pelo alocador de heap do sistema.
- Algo no app modificou o byte superior de um ponteiro. O byte superior do ponteiro não pode ser modificado, e seu código precisa ser alterado para corrigir esse problema.
Exemplos de uso ou modificação incorretos do ponteiro do byte principal.
- Os ponteiros para um tipo específico têm metadados específicos do app armazenados nos 16 primeiros bits de endereço.
- Um ponteiro convertido em duplo e depois de volta, perdendo os bits de endereço mais baixos.
- Código que calcula a diferença entre os endereços de variáveis locais de diferentes frames de pilha como uma maneira de medir a profundidade da recursão.
Alguns apps podem depender de bibliotecas que se comportam incorretamente quando o
byte superior do ponteiro é definido. Sabemos que pode ser
difícil corrigir esses problemas subjacentes nas bibliotecas rapidamente. Assim,
os apps que usam targetSdkLevel < 30
não terão a inclusão de tags de ponteiro ativada por padrão. Também oferecemos uma saída
para apps criados com targetSdkLevel >= 30
para facilitar o período de transição.
A saída de emergência é usada adicionando o seguinte ao
arquivo AndroidManifest.xml
:
<application android:allowNativeHeapPointerTagging="false"> ... </application>
Isso desativa o recurso de inclusão de marcadores de ponteiro no seu app. Isso não resolve o problema de integridade do código. Essa saída de emergência vai desaparecer nas versões futuras do Android, porque problemas dessa natureza serão incompatíveis com o MTE.