O AddressSanitizer assistido por hardware (HWASan) é uma ferramenta de detecção de erros de memória semelhante ao AddressSanitizer . O HWASan usa muito menos RAM em comparação com o ASan, o que o torna adequado para a higienização de todo o sistema. O HWASan está disponível apenas no Android 10 e superior e apenas no hardware AArch64.
Embora útil principalmente para código C/C++, o HWASan também pode ajudar a depurar código Java que causa travamentos em C/C++ usado para implementar interfaces Java. É útil porque detecta erros de memória quando eles acontecem, apontando você diretamente para o código responsável.
Você pode fazer o flash de imagens HWASan pré-construídas para dispositivos Pixel suportados em ci.android.com ( instruções detalhadas de configuração ).
Comparado ao ASan clássico, o HWASan tem:
- Sobrecarga de CPU semelhante (~2x)
- Sobrecarga de tamanho de código semelhante (40 – 50%)
- Sobrecarga de RAM muito menor (10% - 35%)
O HWASan detecta o mesmo conjunto de bugs que o ASan:
- Estouro/subfluxo de buffer de pilha e heap
- Uso de pilha depois de gratuito
- Uso de pilha fora do escopo
- Duplo livre/livre livre
Além disso, o HWASan detecta o uso da pilha após o retorno.
Detalhes e limitações da implementação
O HWASan é baseado na abordagem de marcação de memória , onde um pequeno valor de tag aleatório é associado a ponteiros e a intervalos de endereços de memória. Para que um acesso à memória seja válido, o ponteiro e as tags de memória devem corresponder. O HWASan conta com o recurso ARMv8 top byte ignore (TBI), também chamado de marcação de endereço virtual , para armazenar a marca de ponteiro nos bits mais altos do endereço.
Você pode ler mais sobre o design do HWASan no site de documentação do Clang.
Por design, o HWASan não possui redzones de tamanho limitado do ASan para detectar estouros ou a quarentena de capacidade limitada do ASan para detectar o uso após a liberação. Por esse motivo, o HWASan pode detectar um bug, não importa o tamanho do estouro ou há quanto tempo a memória foi desalocada. Isso dá ao HWASan uma grande vantagem sobre o ASan.
No entanto, HWASan tem um número limitado de valores de tags possíveis (256), o que significa que há uma probabilidade de 0,4% de perder algum bug durante uma execução do programa.
Requisitos
O HWASan requer que o kernel do Linux aceite ponteiros marcados em argumentos de chamada do sistema. O suporte para isso foi implementado nos seguintes conjuntos de patches upstream:
- endereço marcado arm64 ABI
- arm64: desmarca ponteiros de usuário passados para o kernel
- mm: Evite criar aliases de endereço virtual em brk()/mmap()/mremap()
- arm64: Valida endereços marcados em access_ok() chamados de threads do kernel
Esses patches estão disponíveis como backports no kernel Android comum em ramificações android-4.14 e superiores, mas não em ramificações específicas do Android 10, como android-4.14-q .
O suporte de espaço de usuário para HWASan está disponível a partir do Android 11 .
Se você estiver compilando com uma cadeia de ferramentas personalizada, certifique-se de que ela inclua tudo até LLVM commit c336557f .
Usando HWASan
Use os seguintes comandos para construir toda a plataforma usando HWASan:
lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j
Por conveniência, você pode adicionar a configuração SANITIZE_TARGET a uma definição de produto, semelhante a aosp_coral_hwasan .
Ao contrário do ASan, com o HWASan não há necessidade de construir duas vezes. As compilações incrementais simplesmente funcionam, não há instruções especiais de flash ou necessidade de limpeza, executáveis estáticos são suportados e não há problema em pular a sanitização de qualquer biblioteca que não seja libc
. Também não há exigência de que, se uma biblioteca for higienizada, qualquer executável vinculado a ela também deva ser higienizado.
Para pular a sanitização de um módulo, use LOCAL_NOSANITIZE := hwaddress
ou sanitize: { hwaddress: false }
.
Módulos individuais podem ser higienizados com HWASan, com a ressalva de que libc
também é HWASan-ified. Isso pode ser feito adicionando sanitize: { hwaddress: true }
à respectiva definição do módulo Android.bp
. Toda a plataforma Android é construída com HWASan ao usar uma compilação com _hwasan
_hwasan (incluindo libc
) e, como tal, a limpeza manual da libc
não é necessária para compilações HWASan.
Melhores rastreamentos de pilha
O HWASan usa um desbobinador rápido baseado em ponteiro de quadro para registrar um rastreamento de pilha para cada evento de alocação e desalocação de memória no programa. O Android habilita ponteiros de quadro no código AArch64 por padrão, então isso funciona muito bem na prática. Se você precisar desfazer o código gerenciado, defina HWASAN_OPTIONS=fast_unwind_on_malloc=0
no ambiente do processo. Observe que os rastreamentos de pilha de acesso à memória incorretos usam o desenrolador "lento" por padrão; essa configuração afeta apenas os rastreamentos de alocação e desalocação. Esta opção pode exigir muito da CPU, dependendo da carga.
Simbolização
Consulte Simbolização na documentação do ASan.
HWASan em aplicativos
Semelhante ao AddressSanitizer, o HWASan não pode ver o código Java, mas pode detectar bugs nas bibliotecas JNI. Ao contrário do ASan, a execução de aplicativos HWASan em um dispositivo não HWASan não é compatível.
Em um dispositivo HWASan, os aplicativos podem ser verificados com HWASan construindo seu código com SANITIZE_TARGET:=hwaddress
em Make ou -fsanitize=hwaddress
em sinalizadores do compilador. Consulte a documentação do desenvolvedor do aplicativo para obter mais detalhes.