Entendendo os relatórios HWASan

Quando a ferramenta HWASan detecta um bug de memória, o processo é encerrado com abort() e um relatório é impresso em stderr e logcat. Como todas as falhas nativas no Android, os erros HWASan podem ser encontrados em /data/tombstones .

Comparado às falhas nativas regulares, o HWASan carrega informações extras no campo “Mensagem de aborto” próximo ao topo da lápide. Veja abaixo um exemplo de falha baseada em heap (para bugs de pilha, consulte a nota abaixo para as seções específicas da pilha).

Relatório de exemplo

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys'
Revision: 'DVT1.0'
ABI: 'arm64'
Timestamp: 2019-04-24 01:13:22+0000
pid: 11154, tid: 11154, name: sensors@1.0-ser  >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<<
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … regular crash dump follows …]

Isso é muito semelhante a um relatório AddressSanitizer . Ao contrário desses, quase todos os bugs do HWASan são “tag-mismatch”, ou seja, um acesso à memória onde uma tag de ponteiro não corresponde à tag de memória correspondente. Este poderia ser um dos

  • acesso fora dos limites na pilha ou heap
  • use depois de liberar na pilha
  • use após retornar na pilha

Seções

Uma explicação de cada uma das seções do relatório HWASan está abaixo:

Erro de acesso

Contém informações sobre o acesso incorreto à memória, incluindo:

  • Tipo de acesso ("READ" vs. "WRITE")
  • Tamanho do acesso (quantos bytes foram tentados para serem acessados)
  • Número do thread do acesso
  • Tags de ponteiro e memória (para depuração avançada)

Acessar rastreamento de pilha

Rastreamento de pilha do acesso incorreto à memória. Veja a seção Simbolização para simbolizar.

Causa

A causa potencial do mau acesso. Se houver vários candidatos, eles serão listados em ordem decrescente de probabilidade. Precede as informações detalhadas sobre a causa potencial. HWASan pode diagnosticar as seguintes causas:

  • use-após-livre
  • incompatibilidade de tag de pilha: pode ser uso após retorno/uso pós-escopo da pilha ou fora dos limites
  • estouro de buffer de heap
  • estouro global

Informações de memória

Descreve o que o HWASan sabe sobre a memória que está sendo acessada e pode diferir dependendo do tipo de bug.

Tipo de bug Causa Formato do relatório
incompatibilidade de tags use-após-livre
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
estouro de buffer de heap Observe que isso também pode ser um underflow.
<address> is located N bytes to the right of M-byte region [<start>, <end>)
  allocated here:
incompatibilidade de tags de pilha Os relatórios de pilha não diferenciam entre bugs de estouro/underflow e de uso após retorno. Além disso, para encontrar a alocação de pilha que é a origem do erro, é necessária uma etapa de simbolização offline. Consulte a seção Noções básicas sobre relatórios de pilha abaixo.
livre de invalidez use-após-livre Este é um bug duplo gratuito. Se isso acontecer no encerramento do processo, pode significar uma violação do ODR .
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
não é possível descrever o endereço Uma liberação selvagem (livre de memória que não havia sido alocada antes) ou uma liberação dupla após a memória alocada ter sido removida do buffer livre do HWASan.
0x… é memória sombra HWAsan. Esta é definitivamente uma grande liberdade, pois o aplicativo estava tentando liberar memória interna do HWASan.

Rastreamento de pilha de desalocação

Rastreamento de pilha de onde a memória foi desalocada. Presente apenas para bugs de uso após liberação ou sem invalidez. Consulte a seção Simbolização para simbolizar.

Rastreamento de pilha de alocação

Rastreamento de pilha de onde a memória foi alocada. Consulte a seção Simbolização para simbolizar.

Informações avançadas de depuração

O relatório HWASan também apresenta algumas informações avançadas de depuração, incluindo (em ordem):

  1. A lista de threads no processo
  2. A lista de threads no processo
  3. O valor dos tags de memória próximos à memória com falha
  4. O dump dos registradores no ponto de acesso à memória

Despejo de etiqueta de memória

O despejo de memória de tags pode ser usado para procurar alocações de memória próximas com a mesma tag que a tag de ponteiro. Isso pode apontar para um acesso fora dos limites com um grande deslocamento. Uma tag corresponde a 16 bytes de memória; a tag ponteiro são os 8 bits superiores do endereço. O despejo de memória da tag pode dar dicas, por exemplo, o seguinte é um buffer overflow à direita:

tags: ad/5c (ptr/mem)
[...]
Memory tags around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: 0e  0e  0e  57  20  20  20  20  20  2e  5e  5e  5e  5e  5e  b5
=>0x006f33ae2000: f6  f6  f6  f6  f6  4c  ad  ad  ad  ad  ad  ad [5c] 5c  5c  5c
  0x006f33ae2010: 5c  04  2e  2e  2e  2e  2e  2f  66  66  66  66  66  80  6a  6a
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: ab  52  eb  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
=>0x006f33ae2000: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. [..] ..  ..  ..
  0x006f33ae2010: ..  5c  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
(observe a execução de 6 × 16 = 96 bytes de tags “anúncio” à esquerda que correspondem à tag do ponteiro).

Se o tamanho de uma alocação não for múltiplo de 16, o restante do tamanho será armazenado como tag de memória e o tag será armazenado como um tag de grânulo curto . No exemplo acima, logo após o anúncio marcado com alocação em negrito, temos uma alocação de 5 × 16 + 4 = 84 bytes da tag 5c.

Uma tag de memória zero (ex. tags: ad/ 00 (ptr/mem) ) geralmente indica um bug de uso de pilha após retorno.

Registrar despejo

O dump de registro nos relatórios HWASan corresponde à instrução real que executou o acesso inválido à memória. Ele é seguido por outro despejo de registro do manipulador de sinal normal do Android - ignore o segundo , ele é obtido quando o HWASan chama abort() e não é relevante para o bug.

Simbolização

Para obter nomes de funções e números de linha em rastreamentos de pilha (e obter nomes de variáveis ​​para bugs de uso após escopo), é necessária uma etapa de simbolização offline.

Configuração inicial: instale o llvm-symbolizer

Para simbolizar, seu sistema deve ter o llvm-symbolizer instalado e acessível a partir de $PATH. No Debian, você pode instalá-lo usando sudo apt install llvm .

Obtenha arquivos de símbolos

Para simbolização, exigimos binários simples contendo símbolos. Onde eles podem ser encontrados depende do tipo de construção:

Para compilações locais , os arquivos de símbolos podem ser encontrados em out/target/product/<product>/symbols/ .

Para compilações AOSP (por exemplo, atualizadas do Flashstation ), as compilações podem ser encontradas no Android CI . Nos "Artefatos" da compilação, haverá um arquivo `${PRODUCT}-symbols-${BUILDID}.zip`.

Para compilações internas da sua organização, verifique a documentação da sua organização para obter ajuda na obtenção de arquivos de símbolos.

Simbolizar

hwasan_symbolize –-symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash

Compreendendo os relatórios de pilha

Para bugs que ocorrem com variáveis ​​de pilha, o relatório HWASan conterá detalhes como este:

Cause: stack tag-mismatch
Address 0x007d4d251e80 is located in stack of thread T64
Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000)
Previously allocated frames:
  record_addr:0x7df7300c98 record:0x51ef007df3f70fb0  (/apex/com.android.art/lib64/libart.so+0x570fb0)
  record_addr:0x7df7300c90 record:0x5200007df3cdab74  (/apex/com.android.art/lib64/libart.so+0x2dab74)
  [...]
	

Para permitir que os erros de pilha sejam compreendidos, o HWASan monitora os quadros de pilha que aconteceram no passado. Atualmente, o HWASan não transforma isso em conteúdo compreensível para humanos no relatório de bug e requer uma etapa adicional de simbolização .

Violações de ODR

Alguns bugs de uso após liberação relatados pelo HWASan também podem indicar uma violação da Regra de Uma Definição (ODR). Uma violação do ODR ocorre quando a mesma variável é definida várias vezes no mesmo programa. Isso também significa que a variável é destruída várias vezes, o que pode levar ao erro use-after-free.

Após a simbolização, as violações do ODR mostram um uso após liberação com __cxa_finalize , tanto na pilha de acesso inválido quanto na pilha "liberado aqui". A pilha "previamente alocada aqui" contém __dl__ZN6soinfo17call_constructorsEv e deve apontar para o local do seu programa que define a variável mais alta na pilha.

Uma razão pela qual o ODR pode ser violado é quando bibliotecas estáticas são usadas. Se uma biblioteca estática que define um C++ global estiver vinculada a diversas bibliotecas ou executáveis ​​compartilhados, diversas definições do mesmo símbolo poderão acabar existindo no mesmo espaço de endereço, o que causará um erro de ODR.

Solução de problemas

"HWAddressSanitizer não consegue descrever o endereço com mais detalhes."

Às vezes, o HWASan pode ficar sem espaço para informações sobre alocações de memória anteriores. Nesse caso, o relatório conterá apenas um stack trace para acesso imediato à memória, seguido de uma nota:

  HWAddressSanitizer can not describe address in more detail.

Em alguns casos, isso pode ser resolvido executando o teste diversas vezes. Outra opção é aumentar o tamanho do histórico HWASan. Isso pode ser feito globalmente em build/soong/cc/sanitize.go (procure hwasanGlobalOptions ) ou em seu ambiente de processo (tente adb shell echo $HWASAN_OPTIONS para ver as configurações atuais).

Isso também pode acontecer se a memória acessada não for mapeada ou alocada por um alocador não compatível com HWASan. Nesse caso, a tag mem listada no cabeçalho da falha geralmente será 00 . Se você tiver acesso à marca de exclusão completa, pode ser útil consultar o dump dos mapas de memória para descobrir a qual mapeamento (se houver) o endereço pertence.

"bug aninhado no mesmo tópico"

Isso significa que houve um bug ao gerar o relatório de falha do HWASan. Isso geralmente ocorre devido a um bug no tempo de execução do HWASan. Registre um bug e forneça instruções sobre como reproduzir o problema, se possível.