O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Desinfetantes LLVM

LLVM, a infraestrutura do compilador usada para construir o Android, contém vários componentes que realizam análises estáticas e dinâmicas. Desses componentes, os higienizadores - especificamente AddressSanitizer e UndefinedBehaviorSanitizer - podem ser usados ​​extensivamente para analisar o Android. Sanitizadores são componentes de instrumentação baseados em compilador contidos em external / compiler-rt que podem ser usados ​​durante o desenvolvimento e teste para eliminar bugs e tornar o Android melhor. O conjunto atual de desinfetantes do Android pode descobrir e diagnosticar muitos bugs de mau uso de memória e comportamento indefinido potencialmente perigoso.

É uma prática recomendada para compilações Android inicializar e executar com sanitizantes habilitados, como AddressSanitizer e UndefinedBehaviorSanitizer. Esta página apresenta AddressSanitizer, UndefinedBehaviorSanitizer e KernelAddressSanitizer, mostra como eles podem ser usados ​​no sistema de compilação do Android e fornece exemplos de arquivos Android.mk e Android.bp que criam componentes nativos com esses higienizadores ativados.

AddressSanitizer

AddressSanitizer (ASan) é um recurso de instrumentação baseado em compilador que detecta muitos tipos de erros de memória no código C / C ++ em tempo de execução. ASan pode detectar muitas classes de erros de memória, incluindo:

  • Acesso à memória fora dos limites
  • Duplo grátis
  • Use depois de grátis

O Android permite a instrumentação ASan no nível de compilação completa e no nível do aplicativo com asanwrapper.

AddressSanitizer combina a instrumentação de todas as chamadas de função relacionadas à memória - incluindo alloca, malloc e free - e preencher todas as variáveis ​​e regiões de memória alocadas com memória que dispara um retorno de chamada ASan quando é lida ou gravada.

A instrumentação permite que o ASan detecte bugs de uso de memória inválido, incluindo double-free e use-after scope, return e free, enquanto o preenchimento da região de memória detecta leituras ou gravações fora dos limites. Se ocorrer uma leitura ou gravação nesta região de preenchimento, ASan a captura e fornece informações para ajudar a diagnosticar a violação de memória, incluindo a pilha de chamadas, mapa de memória sombra, o tipo de violação de memória, o que foi lido ou escrito, a instrução que causou o violação e o conteúdo da memória.

pixel-xl:/ # sanitizer-status                                                                                            
=================================================================
==14164==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x0032000054b0 at pc 0x005df16ffc3c bp 0x007fc236fdf0 sp 0x007fc236fdd0
WRITE of size 1 at 0x0032000054b0 thread T0
    #0 0x5df16ffc3b in test_crash_malloc sanitizer-status/sanitizer-status.c:36:13
    #1 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7
    #2 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3)
    #3 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53)

0x0032000054b0 is located 0 bytes to the right of 32-byte region [0x003200005490,0x0032000054b0)
allocated by thread T0 here:
    #0 0x794d0bdc67 in malloc (/system/lib64/libclang_rt.asan-aarch64-android.so+0x74c67)
    #1 0x5df16ffb47 in test_crash_malloc sanitizer-status/sanitizer-status.c:34:25
    #2 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7
    #3 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3)
    #4 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53)
    #5 0x794df78893  (<unknown module>)

SUMMARY: AddressSanitizer: heap-buffer-overflow sanitizer-status/sanitizer-status.c:36:13 in test_crash_malloc

Às vezes, o processo de descoberta de bug pode parecer não determinístico, especialmente para bugs que requerem configuração especial ou técnicas mais avançadas, como preparação de heap ou exploração de condição de corrida. Muitos desses bugs não são imediatamente aparentes e podem revelar milhares de instruções da violação de memória que foi a causa raiz real. O ASan instrumenta todas as funções relacionadas à memória e dados de pads com áreas que não podem ser acessadas sem acionar um retorno de chamada do ASan. Isso significa que as violações de memória são detectadas no instante em que ocorrem, em vez de esperar por uma corrupção que induza ao travamento. Isso é extremamente útil na descoberta de bugs e no diagnóstico da causa raiz.

Para verificar se o ASAN está funcional em um dispositivo de destino, o Android incluiu o executável asan_test. O executável asan_test testa e valida a funcionalidade ASAN em um dispositivo de destino, fornecendo mensagens de diagnóstico com o status de cada teste. Ao usar um ASAN Android build, ele está localizado em /data/nativetest/asan_test/asan_test ou /data/nativetest64/asan_test/asan_test por padrão.

UndefinedBehaviorSanitizer

UndefinedBehaviorSanitizer (UBSan) executa a instrumentação em tempo de compilação para verificar vários tipos de comportamento indefinido. Embora o UBSan seja capaz de detectar muitos comportamentos indefinidos , o Android suporta alinhamento, bool, limites, enum, float-cast-overflow, float-divide-by-zero, integer-divide-by-zero, nonnull-attribute, null, return, return-nonnull-attribute, shift-base, shift-exponent, estouro de inteiro com sinal, inacessível, estouro de inteiro sem sinal e limite de vla. unsigned-integer-overflow, embora não seja tecnicamente um comportamento indefinido, está incluído no sanitizer e é usado em muitos módulos Android, incluindo os componentes do mediaserver, para eliminar quaisquer vulnerabilidades latentes de estouro de inteiros.

Implementação

No sistema de compilação do Android, você pode habilitar UBSan global ou localmente. Para habilitar UBSan globalmente, defina SANITIZE_TARGET em Android.mk. Para habilitar o UBSan em um nível por módulo, defina LOCAL_SANITIZE e especifique os comportamentos indefinidos que você deseja procurar em Android.mk. Por exemplo:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0

LOCAL_SRC_FILES:= sanitizer-status.c

LOCAL_MODULE:= sanitizer-status

LOCAL_SANITIZE := alignment bounds null unreachable integer
LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer

include $(BUILD_EXECUTABLE)

O sistema de compilação do Android ainda não oferece suporte a diagnósticos detalhados em arquivos de blueprint como faz com makefiles. Aqui está o equivalente mais próximo escrito como um blueprint (Android.bp):

cc_binary {

    cflags: [
        "-std=c11",
        "-Wall",
        "-Werror",
        "-O0",
    ],

    srcs: ["sanitizer-status.c"],

    name: "sanitizer-status",

    sanitize: {
        misc_undefined: [
            "alignment",
            "bounds",
            "null",
            "unreachable",
            "integer",
        ],
        diag: {
            undefined : true
        },
    },

}

Atalhos UBSan

O Android também possui dois atalhos, integer e default-ub , para habilitar um conjunto de higienizadores ao mesmo tempo. integer ativa integer-divide-by-zero , signed-integer-overflow unsigned-integer-overflow e signed-integer-overflow unsigned-integer-overflow . default-ub ativa as verificações que têm problemas mínimos de desempenho do compilador: bool, número inteiro dividido por zero, retorno, atributo retorna não nulo, expoente de deslocamento, inacessível e vinculado a vla. A classe sanitizer inteira pode ser usada com SANITIZE_TARGET e LOCAL_SANITIZE, enquanto default-ub só pode ser usada com SANITIZE_TARGET.

Melhor relatório de erros

A implementação UBSan padrão do Android invoca uma função especificada quando um comportamento indefinido é encontrado. Por padrão, esta função é abortar. No entanto, a partir de outubro de 2016, UBSan no Android tem uma biblioteca de tempo de execução opcional que fornece relatórios de erros mais detalhados, incluindo tipo de comportamento indefinido encontrado, arquivo e informações de linha de código-fonte. Para ativar esse relatório de erros com verificações de inteiros, adicione o seguinte a um arquivo Android.mk:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

O valor LOCAL_SANITIZE ativa o higienizador durante a construção. LOCAL_SANITIZE_DIAG ativa o modo de diagnóstico para o sanitizador especificado. É possível definir LOCAL_SANITIZE e LOCAL_SANITIZE_DIAG com valores diferentes, mas apenas as verificações em LOCAL_SANITIZE são habilitadas. Se uma verificação não for especificada em LOCAL_SANITIZE, mas for especificada em LOCAL_SANITIZE_DIAG, a verificação não será habilitada e as mensagens de diagnóstico não serão fornecidas.

Aqui está um exemplo das informações fornecidas pela biblioteca de tempo de execução UBSan:

pixel-xl:/ # sanitizer-status ubsan
sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')

Sanitizer de endereço de kernel

Semelhante aos sanitizadores baseados em LLVM para componentes do espaço do usuário, o Android inclui o Kernel Address Sanitizer (KASAN). KASAN é uma combinação de kernel e modificações em tempo de compilação que resultam em um sistema instrumentado que permite uma descoberta de bug mais simples e análise de causa raiz.

O KASAN pode detectar muitos tipos de violações de memória no kernel. Ele também pode detectar leituras e gravações fora do limite na pilha, heap e variáveis ​​globais e pode detectar o uso após a liberação e liberações duplas.

Semelhante ao ASAN, o KASAN usa uma combinação de instrumentação de função de memória em tempo de compilação e memória sombra para rastrear acessos à memória em tempo de execução. No KASAN, um oitavo do espaço da memória do kernel é dedicado à memória shadow, que determina se um acesso à memória é válido ou não.

KASAN é compatível com as arquiteturas x86_64 e arm64. Ele faz parte do kernel upstream desde 4.0, e foi feito backport para kernels baseados no Android 3.18. KASAN foi testado em kernels Android compilados com gcc baseado em 4.9.2.

Além do KASAN, o kcov é outra modificação do kernel útil para teste. O kcov foi desenvolvido para permitir o teste fuzz guiado por cobertura no kernel. Ele mede a cobertura em termos de entradas syscall e é útil com sistemas de difusão, como o syzkaller .

Implementação

Para compilar um kernel com KASAN e kcov habilitados, adicione os seguintes sinalizadores de compilação à configuração de compilação do kernel:

CONFIG_KASAN 
CONFIG_KASAN_INLINE 
CONFIG_TEST_KASAN 
CONFIG_KCOV 
CONFIG_SLUB 
CONFIG_SLUB_DEBUG 
CONFIG_CC_OPTIMIZE_FOR_SIZE

E removendo o seguinte:

CONFIG_SLUB_DEBUG_ON 
CONFIG_SLUB_DEBUG_PANIC_ON 
CONFIG_KASAN_OUTLINE 
CONFIG_KERNEL_LZ4

Em seguida, construa e atualize seu kernel normalmente. O kernel KASAN é consideravelmente maior que o original. Se aplicável, modifique quaisquer parâmetros de inicialização e configurações do carregador de inicialização para levar isso em consideração.

Depois de atualizar o kernel, verifique os logs de inicialização do kernel para ver se KASAN está ativado e em execução. O kernel irá iniciar com informações do mapa de memória para KASAN, como:

...
[    0.000000] c0      0 Virtual kernel memory layout:
[    0.000000] c0      0     kasan   : 0xffffff8000000000 - 0xffffff9000000000   (    64 GB)
[    0.000000] c0      0     vmalloc : 0xffffff9000010000 - 0xffffffbdbfff0000   (   182 GB)
[    0.000000] c0      0     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000] c0      0               0xffffffbdc0000000 - 0xffffffbdc3f95400   (    63 MB actual)
[    0.000000] c0      0     PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000   (    16 MB)
[    0.000000] c0      0     fixed   : 0xffffffbffbdfd000 - 0xffffffbffbdff000   (     8 KB)
[    0.000000] c0      0     modules : 0xffffffbffc000000 - 0xffffffc000000000   (    64 MB)
[    0.000000] c0      0     memory  : 0xffffffc000000000 - 0xffffffc0fe550000   (  4069 MB)
[    0.000000] c0      0       .init : 0xffffffc001d33000 - 0xffffffc001dce000   (   620 KB)
[    0.000000] c0      0       .text : 0xffffffc000080000 - 0xffffffc001d32284   ( 29385 KB)
...

E é assim que um bug será:

[   18.539668] c3      1 ==================================================================
[   18.547662] c3      1 BUG: KASAN: null-ptr-deref on address 0000000000000008
[   18.554689] c3      1 Read of size 8 by task swapper/0/1
[   18.559988] c3      1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G        W      3.18.24-xxx #1
[   18.569275] c3      1 Hardware name: Android Device
[   18.577433] c3      1 Call trace:
[   18.580739] c3      1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4
[   18.586985] c3      1 [<ffffffc00008b600>] show_stack+0x10/0x1c
[   18.592889] c3      1 [<ffffffc001481194>] dump_stack+0x74/0xc8
[   18.598792] c3      1 [<ffffffc000202ee0>] kasan_report+0x11c/0x4d0
[   18.605038] c3      1 [<ffffffc00020286c>] __asan_load8+0x20/0x80
[   18.611115] c3      1 [<ffffffc000bdefe8>] android_verity_ctr+0x8cc/0x1024
[   18.617976] c3      1 [<ffffffc000bcaa2c>] dm_table_add_target+0x3dc/0x50c
[   18.624832] c3      1 [<ffffffc001bdbe60>] dm_run_setup+0x50c/0x678
[   18.631082] c3      1 [<ffffffc001bda8c0>] prepare_namespace+0x44/0x1ac
[   18.637676] c3      1 [<ffffffc001bda170>] kernel_init_freeable+0x328/0x364
[   18.644625] c3      1 [<ffffffc001478e20>] kernel_init+0x10/0xd8
[   18.650613] c3      1 ==================================================================

Além disso, se os módulos estiverem habilitados em seu kernel, você pode carregar o módulo de kernel test_kasan para testes adicionais. O módulo tenta acessos de memória fora dos limites e uso após livre e é útil para testar KASAN em um dispositivo de destino.