O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

AddressSanitizer

AddressSanitizer (ASan) é uma ferramenta rápida baseada em compilador para detectar bugs de memória em código nativo.

ASan detecta:

  • Estouro / estouro de buffer de pilha e heap
  • Heap use after free
  • Uso da pilha fora do escopo
  • Double free / wild free

ASan é executado em ARM de 32 e 64 bits, além de x86 e x86-64. A sobrecarga da CPU do ASan é aproximadamente 2x, a sobrecarga do tamanho do código está entre 50% e 2x e uma grande sobrecarga de memória (dependente de seus padrões de alocação, mas da ordem de 2x).

Android 10 e o ramo principal AOSP em AArch64 apoio Asan hardware-acelerada (Hwasan) , uma ferramenta parecida com menor sobrecarga de RAM e uma maior gama de erros detectados. O HWASan detecta o uso da pilha após o retorno, além dos bugs detectados pelo ASan.

O HWASan tem CPU semelhante e sobrecarga de tamanho de código, mas uma sobrecarga de RAM muito menor (15%). HWASan não é determinístico. Existem apenas 256 valores de tag possíveis, portanto, há uma probabilidade fixa de 0,4% de perder algum bug. O HWASan não tem zonas vermelhas de tamanho limitado do ASan para detectar estouros e quarentena de capacidade limitada para detectar o uso pós-livre, então não importa para o HWASan quão grande é o estouro ou há quanto tempo a memória foi desalocada. Isso torna o HWASan melhor do que o ASan. Você pode ler mais sobre o projeto de Hwasan ou sobre o uso de Hwasan no Android .

O ASan detecta estouros de pilha / globais, além de estouros de heap, e é rápido com sobrecarga de memória mínima.

Este documento descreve como construir e executar partes / todo o Android com ASan. Se você está construindo um SDK / NDK aplicativo com Asan, consulte Endereço Sanitizer vez.

Sanitizando executáveis ​​individuais com ASan

Adicionar LOCAL_SANITIZE:=address ou sanitize: { address: true } à regra de compilação do executável. Você pode pesquisar o código em busca de exemplos existentes ou encontrar outros sanitizantes disponíveis.

Quando um erro é detectado, Asan imprime um relatório detalhado tanto para a saída de padrão e para logcat e, em seguida, cai o processo.

Sanitizando bibliotecas compartilhadas com ASan

Devido à forma como o ASan funciona, uma biblioteca construída com ASan só pode ser usada por um executável criado com ASan.

Para limpar uma biblioteca compartilhada que é usada em vários executáveis, nem todos construídos com ASan, você precisa de duas cópias da biblioteca. A maneira recomendada de fazer isso é adicionar o seguinte para Android.mk para o módulo em questão:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Isso coloca a biblioteca em /system/lib/asan , em vez de /system/lib . Em seguida, execute seu executável com:

LD_LIBRARY_PATH=/system/lib/asan

Para daemons do sistema, adicione o seguinte para a seção apropriada de /init.rc ou /init.$device$.rc .

setenv LD_LIBRARY_PATH /system/lib/asan

Verifique se o processo está usando bibliotecas de /system/lib/asan quando presente através da leitura /proc/$PID/maps . Se não estiver, pode ser necessário desativar o SELinux:

adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

Melhores rastreamentos de pilha

ASan usa um desenrolador rápido baseado em ponteiro de quadro para registrar um rastreamento de pilha para cada alocação de memória e evento de desalocação no programa. A maior parte do Android é construída sem ponteiros de quadro. Como resultado, você geralmente obtém apenas um ou dois frames significativos. Para corrigir isso, reconstrua a biblioteca com ASan (recomendado!) Ou com:

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

Ou definir ASAN_OPTIONS=fast_unwind_on_malloc=0 no ambiente de processo. Este último pode consumir muito a CPU, dependendo da carga.

Simbolização

Inicialmente, os relatórios ASan contêm referências a deslocamentos em binários e bibliotecas compartilhadas. Existem duas maneiras de obter o arquivo de origem e as informações de linha:

  • Certifique-se de que o llvm-symbolizer binário está presente em /system/bin . llvm-symbolizer é construído a partir de fontes em third_party/llvm/tools/llvm-symbolizer .
  • Filtrar o relatório por meio do external/compiler-rt/lib/asan/scripts/symbolize.py script.

A segunda abordagem pode fornecer mais dados (isto é, file:line localidades) por causa da disponibilidade de bibliotecas simbolizados no host.

ASan em aplicativos

ASan não consegue ver o código Java, mas pode detectar bugs nas bibliotecas JNI. Para isso, você precisa para construir o executável com Asan, que neste caso é /system/bin/app_process( 32|64 ) . Isso ativa o ASan em todos os aplicativos do dispositivo ao mesmo tempo, o que é uma carga pesada, mas um dispositivo com 2 GB de RAM deve ser capaz de lidar com isso.

Adicionar LOCAL_SANITIZE:=address ao app_process regra de construção em frameworks/base/cmds/app_process . Ignore o app_process__asan alvo no mesmo arquivo por enquanto (se ele ainda está lá no momento que você lê este).

Edite o service zygote seção do apropriada system/core/rootdir/init.zygote( 32|64 ).rc arquivo para adicionar as seguintes linhas ao bloco de linhas recuadas contendo class main , também recuado pela mesma quantidade:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

Build, adb sync, fastboot flash boot e reboot.

Usando a propriedade wrap

A abordagem na seção anterior coloca o ASan em todos os aplicativos do sistema (na verdade, em todos os descendentes do processo Zygote). É possível executar apenas um (ou vários) aplicativos com ASan, trocando alguma sobrecarga de memória por inicialização mais lenta do aplicativo.

Isto pode ser feito iniciando seu aplicativo com o wrap. propriedade. O exemplo a seguir executa o aplicativo Gmail em ASan:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

Neste contexto, asanwrapper reescreve /system/bin/app_process ao /system/bin/asan/app_process , que é construído com Asan. Ele também adiciona /system/lib/asan no início do caminho dinâmico de pesquisa da biblioteca. Desta forma, as bibliotecas Asan-instrumentada de /system/lib/asan são preferidos para bibliotecas normais em /system/lib quando executado com asanwrapper .

Se um bug for encontrado, o aplicativo trava e o relatório é impresso no log.

SANITIZE_TARGET

O Android 7.0 e superior inclui suporte para construir toda a plataforma Android com ASan de uma só vez. (Se você estiver criando uma versão superior ao Android 9, o HWASan é uma escolha melhor.)

Execute os seguintes comandos na mesma árvore de construção.

make -j42
SANITIZE_TARGET=address make -j42

Neste modo, userdata.img contém bibliotecas extras e deve ser atualizada para o dispositivo também. Use a seguinte linha de comando:

fastboot flash userdata && fastboot flashall

Isso cria dois conjuntos de bibliotecas compartilhadas: normal em /system/lib (a primeira composição de invocação), e Asan-instrumentado em /data/asan/lib (a segunda marca de invocação). Os executáveis ​​da segunda compilação substituem os da primeira compilação. Executáveis Asan instrumentados obter um caminho de busca da biblioteca diferente que inclui /data/asan/lib antes /system/lib através do uso de /system/bin/linker_asan em PT_INTERP .

Os clobbers sistema de construção intermediários diretórios objeto quando o $SANITIZE_TARGET valor foi alterado. Este forças uma reconstrução de todos os alvos, preservando os binários instalados sob /system/lib .

Alguns alvos não podem ser construídos com ASan:

  • Executáveis ​​estaticamente vinculados
  • LOCAL_CLANG:=false alvos
  • LOCAL_SANITIZE:=false não são ASan'd para SANITIZE_TARGET=address

Executáveis como estes são ignorados na SANITIZE_TARGET compilação e a versão do primeiro make invocação é deixado em /system/bin .

Bibliotecas como essa são construídas sem ASan. Eles podem conter algum código ASan das bibliotecas estáticas das quais dependem.

Documentação de suporte