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: '==9569==ERROR: HWAddressSanitizer: tag-mismatch on address 0x00433ae20045 at pc 0x00623ae2a9cc READ of size 1 at 0x00433ae20045 tags: 5b/83 (ptr/mem) in thread T0 #0 0x7240450c68 (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) #1 0x723dffd490 (/vendor/lib64/sensors.ssc.so+0x34490) #2 0x723e0126e0 (/vendor/lib64/sensors.ssc.so+0x496e0) [...] [0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5 Cause: use-after-free 0x00433ae20045 is located 5 bytes inside of 10-byte region [0x00433ae20040,0x00433ae2004a) freed by thread T0 here: #0 0x72404d1b18 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x10b18) #1 0x723af23040 (/vendor/lib64/libgralloccore.so+0x5040) #2 0x723af23fa4 (/vendor/lib64/libgralloccore.so+0x5fa4) [...] previously allocated here: #0 0x72404ce554 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0xd554) #1 0x7240115654 (/apex/com.android.runtime/lib64/bionic/libc.so+0x43654) #2 0x7240450ac8 (/system/lib64/vndk-sp-R/libcutils.so+0x8ac8) [...] hwasan_dev_note_heap_rb_distance: 1 1023 hwasan_dev_note_num_matching_addrs: 0 hwasan_dev_note_num_matching_addrs_4b: 0 Thread: T0 0x006a00002000 stack: [0x007fc1064000,0x007fc1864000) sz: 8388608 tls: [0x00737702ffc0,0x007377033000) Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x006f33ae2000: 08 00 08 00 [83] 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: 72 .. d0 .. [..] .. .. .. .. .. .. .. .. .. .. .. 0x006f33ae2010: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags Registers where the failure occurred (pc 0x00623ae2a9cc): x0 0000007fc18623ec x1 5b0000433ae20045 x2 0000000000000013 x3 ffffffffffffffff x4 ffffffffffffffff x5 0000007fc1861da3 x6 6f7420676e696f47 x7 45522061206f6420 x8 0000000000000000 x9 0200006b00000000 x10 00000007fc18623f x11 5b0000433ae20040 x12 6f64206f7420676e x13 0a44414552206120 x14 0000000000000010 x15 ffffffffffffffff x16 000000737169ac94 x17 0000000000000007 x18 0000007377bd8000 x19 0000007fc1862498 x20 0200006b00000000 x21 0000007fc18624a8 x22 0000000000000001 x23 0000000000000000 x24 0000000000000000 x25 0000000000000000 x26 0000000000000000 x27 0000000000000000 x28 0000000000000000 x29 0000007fc1862410 x30 000000623ae2a9d0 sp 0000007fc18623d0 SUMMARY: HWAddressSanitizer: tag-mismatch (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) [ … 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):
- A lista de threads no processo
- A lista de threads no processo
- O valor dos tags de memória próximos à memória com falha
- 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.