Consulte Noções básicas sobre os relatórios do HWASan para saber como ler falhas do HWASan.
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 sanitização de todo o sistema. O HWASan só está disponível no Android 10 e versões mais recentes, e apenas em hardware AArch64.
Embora seja útil principalmente para código C/C++, o HWASan também pode ajudar a depurar código Java que causa falhas em C/C++ usado para implementar interfaces Java. Isso é útil porque detecta erros de memória quando eles ocorrem, apontando diretamente para o código responsável.
Em comparação com o ASan clássico, o HWASan tem:
- Sobrecarga de CPU semelhante (~2x)
- Sobrecarga de tamanho de código semelhante (40 a 50%)
- Sobrecarga de RAM muito menor (10% a 35%)
O HWASan detecta o mesmo conjunto de bugs do ASan:
- Overflow/underflow do buffer de heap e pilha
- Uso de heap depois da liberação de memória
- Uso de pilha fora do escopo
- Double free/wild free
Além disso, o HWASan detecta o uso da pilha após o retorno.
O HWASan (igual ao ASan) é compatível com o UBSan, e os dois podem ser ativados em um destino ao mesmo tempo.
Detalhes e limitações da implementação
O HWASan é baseado na abordagem de inclusão de tags na memória, em que um pequeno valor de tag aleatório é associado a ponteiros e intervalos de endereços de memória. Para que um acesso à memória seja válido, as tags de ponteiro e de memória precisam corresponder. O HWASan depende do recurso ARMv8 Top Byte Ignore (TBI), também chamado de inclusão de tags de endereço virtual, para armazenar a tag de ponteiro nos bits mais altos do endereço.
Leia mais sobre o design do HWASan no site de documentação do Clang.
Por design, o HWASan não tem as zonas vermelhas de tamanho limitado do ASan para detectar estouros nem a quarentena de capacidade limitada do ASan para detectar o uso após a liberação. Por isso, 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, o HWASan tem um número limitado de valores de tag possíveis (256), o que significa que há uma probabilidade de 0,4% de perder qualquer bug durante uma execução do programa.
Requisitos
As versões recentes (4.14 ou mais recentes) do kernel comum do Android oferecem suporte ao HWASan de imediato. As ramificações específicas do Android 10 não têm suporte para HWASan.
O suporte ao HWASan no espaço do usuário está disponível a partir do Android 11.
Se você estiver trabalhando com um kernel diferente, o HWASan vai exigir que o kernel do Linux aceite ponteiros marcados em argumentos de chamada do sistema. O suporte a isso foi implementado nos seguintes patchsets upstream:
- ABI de endereço com tag arm64
- arm64: remover tags de ponteiros de usuário transmitidos ao kernel
- mm: evite criar aliases de endereços virtuais em brk()/mmap()/mremap()
- arm64: validar endereços marcados em access_ok() chamados de linhas de execução do kernel
Se você estiver criando com um conjunto de ferramentas personalizado, verifique se ele inclui tudo até o commit do LLVM c336557f.
Usar o HWASan
Use os comandos a seguir para criar toda a plataforma usando o HWASan:
lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j
Para sua conveniência, adicione a configuração SANITIZE_TARGET a uma definição de produto, semelhante a aosp_coral_hwasan.
Para usuários familiarizados com o AddressSanitizer, grande parte da complexidade do build desapareceu:
- Não é necessário executar "make" duas vezes.
- Os builds incrementais funcionam imediatamente.
- Não é necessário atualizar userdata.
Algumas restrições do AddressSanitizer também foram removidas:
- Executáveis estáticos são compatíveis.
- Não há problema em pular a higienização de qualquer destino que não seja libc. Ao contrário do ASan, não há exigência de que, se uma biblioteca for higienizada, qualquer executável vinculado a ela também precise ser.
É possível alternar entre imagens HWASan e regulares com o mesmo número de build (ou um maior). Não é necessário limpar o dispositivo.
Para ignorar a sanitização de um módulo, use
LOCAL_NOSANITIZE := hwaddress
(Android.mk) ou
sanitize: { hwaddress: false }
(Android.bp).
Limpar destinos individuais
O HWASan pode ser ativado por destino em um build regular (sem limpeza), desde que libc.so
também seja limpo. Adicione hwaddress: true
ao bloco de limpeza em "libc_defaults"
em bionic/libc/Android.bp. Em seguida, faça o mesmo no destino em que você está trabalhando.
A sanitização da libc permite a inclusão de tags em alocações de memória de heap em todo o sistema, além da verificação das tags para operações de memória dentro de libc.so
. Isso pode detectar bugs mesmo em binários
em que o HWASan não estava ativado se o acesso incorreto à memória estiver em libc.so
(por exemplo, pthread_mutex_unlock()
em um mutex delete()
ed).
Não é necessário mudar nenhum arquivo de build se toda a plataforma for criada usando o HWASan.
Stack traces melhores
O HWASan usa um unwinder rápido baseado em ponteiro de frames para registrar um stack
trace para cada evento de alocação e desalocação de memória no
programa. O Android ativa os ponteiros de frame no código AArch64 por padrão,
o que 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 incorreto usam o unwinder "lento" por padrão. Essa configuração afeta apenas os rastreamentos de alocação e desalocação. Essa opção pode exigir muito da CPU, dependendo da carga.
Simbolização
Consulte Simbolização em "Noções básicas sobre os relatórios do HWASan".
HWASan em apps
Assim como o AddressSanitizer, o HWASan não consegue acessar o código Java, mas pode detectar bugs nas bibliotecas JNI. Até o Android 14, a execução de apps HWASan em um dispositivo sem HWASan não era compatível.
Em um dispositivo HWASan, os apps podem ser verificados com HWASan criando o código deles com SANITIZE_TARGET:=hwaddress
em Make ou -fsanitize=hwaddress
em flags do compilador.
Em um dispositivo sem HWASan (com Android 14 ou mais recente), é necessário adicionar uma configuração de arquivo wrap.sh
LD_HWASAN=1
.
Consulte a
documentação para desenvolvedores de apps
para mais detalhes.