IndefinidoBehaviorSanitizer

O UndefineBehaviorSanitizer (UBSan) executa instrumentação durante a compilação para verifica vários tipos de comportamento indefinido. Embora o UBSan seja capaz de detectando muitos bugs de comportamento indefinido, o Android tem suporte para:

  • alinhamento
  • booleano
  • limites
  • enum
  • float-cast-overflow
  • flutuação-dividir-por-zero
  • divisão-por-número inteiro por zero
  • atributo não nulo
  • vazio
  • return
  • atributo não nulo retornado
  • deslocamento-base
  • shift-expoente
  • estouro de números inteiros assinados
  • não acessível
  • estouro de números inteiros não assinados
  • vinculado a vla

estouro de número inteiro não assinado, embora não seja tecnicamente indefinido incluído no sanitizer e usado em muitos módulos do Android, incluindo os componentes do mediaserver, para eliminar qualquer estouro latente de números inteiros vulnerabilidades.

Implementação

No sistema de build do Android, é possível ativar o UBSan globalmente ou localmente. Para ativar UBSan globalmente, defina SANITIZE_TARGET em Android.mk. Para ativar o UBSan em um por módulo, defina LOCAL_SANITIZE e especifique os comportamentos indefinidos que que você quer procurar em Android.mk. 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)

E a configuração de blueprint equivalente (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: {
            misc_undefined: [
                "alignment",
                "bounds",
                "null",
                "unreachable",
                "integer",
            ],
        },
    },

}

Atalhos do UBSan

O Android também tem dois atalhos, integer e default-ub, para ativar um conjunto de limpadores ao mesmo tempo. número inteiro ativa integer-divide-by-zero, signed-integer-overflow e unsigned-integer-overflow. default-ub ativa as verificações que têm compilador mínimo problemas de desempenho: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound. A A classe de limpeza de números inteiros pode ser usada com SANITIZE_TARGET e LOCAL_SANITIZE, enquanto default-ub só pode ser usado com SANITIZE_TARGET.

Relatórios de erros aprimorados

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

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

O valor LOCAL_SANITIZE ativa a limpeza durante o build. LOCAL_SANITIZE_DIAG ativa o modo de diagnóstico para o limpador especificado. É possível definir LOCAL_SANITIZE e LOCAL_SANITIZE_DIAG como valores diferentes, mas apenas essas verificações em LOCAL_SANITIZE estão ativadas. Se um cheque não for especificado LOCAL_SANITIZE, mas é especificado em LOCAL_SANITIZE_DIAG, a verificação não está ativada e as mensagens de diagnóstico não são fornecidas.

Confira um exemplo das informações fornecidas pela biblioteca de execução do 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')

Limpeza de estouro de números inteiros

Excessos de números inteiros não intencionais podem causar corrupção de memória ou informações de divulgação vulnerabilidades em variáveis associadas a acessos à memória ou alocações de memória. Para combater isso, adicionamos o código do Clang UndefinidaBehaviorSanitizer (link em inglês) (UBSan) de descarga de números inteiros assinados e não assinados para aumentar o framework de mídia no Android 7.0. No Android 9, expandido UBSan abarca mais componentes e melhoramos o suporte do sistema de build para ele.

Ele foi criado para adicionar verificações aritméticas instruções de operações e para cabelos overflow: para cancelar um processo com segurança caso ocorra um overflow. Esses limpadores podem mitigar uma classe inteira de corrupção de memória e divulgação de informações em que a causa raiz é um número inteiro sobrecarregado, como a vulnerabilidade Stagefright original.

Exemplos e origem

A limpeza de estouro de números inteiros (IntSan) é fornecida pelo compilador e adiciona instrumentação no binário durante o tempo de compilação para detectar operações aritméticas transborda. Ele é ativado por padrão em vários componentes ao longo plataforma, por exemplo /platform/external/libnl/Android.bp

Implementação

O IntSan usa limpadores de estouro de números inteiros assinados e não assinados do UBSan. Isso A mitigação é ativada por módulo. Ele ajuda a manter componentes críticos do Android com segurança e não podem ser desativados.

Recomendamos que você ative a limpeza de estouro de números inteiros para componentes de solução. Os candidatos ideais são código nativo privilegiado ou código nativo que analisa entradas de usuários não confiáveis. Há um pequeno overhead de desempenho associado com a limpeza que depende do uso do código e da prevalência de operações aritméticas. Espere uma pequena porcentagem de sobrecarga e teste se e o desempenho dele é uma preocupação.

Suporte ao IntSan em makefiles

Para ativar o IntSan em um makefile, adicione:

LOCAL_SANITIZE := integer_overflow
    # Optional features
    LOCAL_SANITIZE_DIAG := integer_overflow
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
  • LOCAL_SANITIZE usa uma lista de desinfetantes separados por vírgulas, com integer_overflow sendo um conjunto predefinido de opções para os limpadores de estouro de números inteiros, assinados e não assinados, com uma padrão LISTA DE BLOCOS.
  • LOCAL_SANITIZE_DIAG ativa o modo de diagnóstico do desinfetantes. Use o modo de diagnóstico somente durante os testes, porque isso não vai abortar em caso de estouro, invalidando completamente a vantagem de segurança da mitigação. Consulte Solução de problemas para mais detalhes.
  • LOCAL_SANITIZE_BLOCKLIST permite que você especifique uma BLOCKLIST para evitar que as funções e os arquivos de origem sejam limpos. Consulte Solução de problemas para detalhes.

Se quiser um controle mais granular, ative os limpadores individualmente usando um ou ambas:

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
    LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

Suporte para o IntSan em arquivos de blueprint

Para ativar a limpeza de estouro de números inteiros em um arquivo de blueprint, como /platform/external/libnl/Android.bp, adicionar:

   sanitize: {
          integer_overflow: true,
          diag: {
              integer_overflow: true,
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

Assim como nos arquivos do Make, a propriedade integer_overflow é um conjunto de opções para o estouro de números inteiros assinados e não assinados desinfetantes com um padrão LISTA DE BLOQUEIORES.

O conjunto de propriedades diag ativa o modo de diagnóstico da desinfetantes. Use o modo de diagnóstico apenas durante o teste. O modo diagnóstico não abortar em caso de estouro, o que anula completamente a vantagem de segurança da de mitigação de ameaças em builds de usuários. Consulte Solução de problemas para mais detalhes.

A propriedade BLOCKLIST permite a especificação de um arquivo BLOCKLIST que permite aos desenvolvedores impedir que funções e arquivos de origem sejam limpa. Consulte Solução de problemas para mais detalhes.

Para ativar os limpadores individualmente, use:

   sanitize: {
          misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
          diag: {
              misc_undefined: ["signed-integer-overflow",
                               "unsigned-integer-overflow",],
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

Solução de problemas

Se você ativar a limpeza de estouro de números inteiros em novos componentes ou depender de bibliotecas de plataforma que tiveram sanitização de estouro de números inteiros, talvez você se depare com alguns problemas com estouros benignos de números inteiros causando cancelamentos. Você deve testar componentes com sanitização ativada para garantir a ocorrência de estouros benignos.

Para encontrar cancelamentos causados pela limpeza nos builds do usuário, pesquise por SIGABRT falha com mensagens de cancelamento indicando um estouro detectado. pela UBSan, como:

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: sub-overflow'

O stack trace precisa incluir a função que causa o cancelamento. No entanto, os estouros que ocorrem em funções inline podem não ser evidentes no stack trace.

Para determinar a causa raiz com mais facilidade, ative o diagnóstico na biblioteca acionando o cancelamento e tenta reproduzir o erro. Com estiver ativado, o processo não será cancelado, mas sim em execução. Não cancelar ajuda a maximizar o número de overflows benignos em uma caminho de execução específico sem precisar recompilar após a correção de cada bug. O diagnóstico gera uma mensagem de erro que inclui o número da linha e a origem arquivo que causa o cancelamento:

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

Depois que a operação aritmética problemática for localizada, verifique se o overflow seja benigno e intencional (por exemplo, não tem implicações de segurança). Você pode resolver cancelamento do limpador por:

  • Refatoração do código para evitar estouro (exemplo)
  • Overflow explicitamente por meio de __builtin_*_overflow do Clang funções (exemplo)
  • Como desativar a limpeza na função especificando o atributo no_sanitize (exemplo)
  • Desativar a limpeza de uma função ou arquivo de origem por um arquivo BLOCKLIST (exemplo)

Você deve usar a solução mais granular possível. Por exemplo, um grande função com muitas operações aritméticas e uma única operação de transbordamento a operação única precisa ser refatorada em vez da função inteira BLOQUEIO COM LISTA.

Os padrões comuns que podem resultar em estouros benignos incluem:

  • Implícito transmite quando ocorre um estouro sem assinatura antes de ser convertido em um tipo com sinal (exemplo).
  • Exclusões de listas vinculadas que diminuem o índice de loop na exclusão (exemplo)
  • Como atribuir um tipo não assinado a -1 em vez de especificar o valor máximo real (exemplo)
  • Repetições que diminuem um número inteiro não assinado na condição (exemplo, exemplo)

É recomendável que os desenvolvedores garantam que os casos em que a limpeza detecta um estouro que é realmente benigno, sem efeitos colaterais não intencionais ou segurança antes de desativar a limpeza.

Desativar o IntSan

Você pode desativar o IntSan com BLOCKLISTs ou atributos de função. Desativar com moderação e somente quando a refatoração do código não for razoável ou se houver de desempenho problemático.

Consulte a documentação do Clang upstream para mais informações sobre como desativar o IntSan com a função atributos e BLOCKLIST de arquivo e a formatação. O escopo de BLOCKLISTing deve ser definido para o limpador específico ao usando nomes de seção especificando o limpador de destino para evitar impactar outros desinfetantes.

Validação

No momento, não há testes de CTS especificamente para a limpeza de estouro de números inteiros. Em vez disso, certifique-se de que os testes do CTS sejam aprovados com ou sem o IntSan ativado para verificar para que isso não afete o dispositivo.

Sanitização de limites

BoundsSanitizer (BoundSan) adiciona instrumentação a binários para inserir limites. de acessos à matriz. Essas verificações são adicionadas se o compilador não pode provar no momento da compilação que o acesso será seguro e se o tamanho da matriz serão conhecidos no ambiente de execução para que possam ser comparados. O Android 10 implanta o BoundSan em Bluetooth e codecs. O BoundSan é fornecido pelo compilador e é ativado pelo padrão em vários componentes em toda a plataforma.

Implementação

O BoundSan usa o UBSan limpador de limites. Essa mitigação é ativada por módulo. Ajuda proteger os componentes críticos do Android e não podem ser desativados.

Recomendamos que você ative o BoundSan para outros componentes. Os candidatos ideais são código nativo privilegiado ou código nativo complexo que analisa entradas de usuário não confiáveis. A sobrecarga de desempenho associada à ativação do BoundSan depende do número de acessos de matriz que não podem ser comprovadamente seguros. Espere um uma pequena porcentagem de sobrecarga, em média, e testar se o desempenho é uma preocupação.

Ativar BoundSan em arquivos de blueprint

O BoundSan pode ser ativado em arquivos de blueprint adicionando "bounds". à propriedade de limpeza misc_undefined para binário e biblioteca módulos:

    sanitize: {
       misc_undefined: ["bounds"],
       diag: {
          misc_undefined: ["bounds"],
       },
       BLOCKLIST: "modulename_BLOCKLIST.txt",
diagnóstico

A propriedade diag ativa o modo de diagnóstico para os limpadores. Use o modo de diagnóstico apenas durante o teste. O modo de diagnóstico não é cancelado em transbordamentos, que negam a vantagem de segurança da mitigação e têm de desempenho maior, por isso não é recomendado para builds de produção.

LISTA DE BLOCOS

A propriedade BLOCKLIST permite a especificação de uma BLOCKLIST que os desenvolvedores podem usar para evitar que funções e arquivos de origem sejam limpa. Use essa propriedade somente se a performance for uma preocupação e a segmentação arquivos/funções contribuem significativamente. Fazer auditoria manual destes arquivos/funções para garantir que os acessos à matriz sejam seguros. Consulte Solução de problemas detalhes.

Ativar BoundSan em makefiles

O BoundSan pode ser ativado em makefiles adicionando "bounds". à variável LOCAL_SANITIZE para módulos binários e de biblioteca:

    LOCAL_SANITIZE := bounds
    # Optional features
    LOCAL_SANITIZE_DIAG := bounds
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt

LOCAL_SANITIZE aceita uma lista de limpadores separados por uma vírgula.

LOCAL_SANITIZE_DIAG ativa o modo de diagnóstico. Usar o diagnóstico durante o teste. O modo diagnóstico não é cancelado em caso de estouro, o que nega a vantagem de segurança da mitigação e tem um impacto de desempenho. Por isso, não é recomendado para builds de produção.

LOCAL_SANITIZE_BLOCKLIST permite a especificação de uma BLOCKLIST que permite aos desenvolvedores impedir que funções e arquivos de origem sejam limpa. Use essa propriedade somente se a performance for uma preocupação e a segmentação arquivos/funções contribuem significativamente. Fazer auditoria manual destes arquivos/funções para garantir que os acessos à matriz sejam seguros. Consulte Solução de problemas detalhes.

Desativar BoundSan

Você pode desativar o BoundSan em funções e arquivos de origem com BLOCKLISTs ou atributos de função. É melhor manter o BoundSan ativado; portanto, só desativá-lo se a função ou o arquivo está criando uma grande sobrecarga de desempenho e foi revisado manualmente.

Para obter mais informações sobre como desativar o BoundSan com a função atributos e BLOCKLIST de arquivo consulte a documentação do LLVM do Clang. Definir o escopo Faça a inclusão de BLOCKLIST no limpador específico usando nomes de seção que especificam a higienizador para evitar o impacto em outros desinfetantes.

Validação

Não há teste CTS especificamente para o BoundSan. Em vez disso, verifique se o CTS os testes serão aprovados com ou sem o BoundSan ativado para verificar se ele não está afetando o dispositivo.

Solução de problemas

Teste os componentes minuciosamente depois de ativar o BoundSan para garantir que e não detectados fora dos limites.

Os erros de BoundSan podem ser facilmente identificados, pois incluem os seguintes mensagem de cancelamento da marca de exclusão:

    pid: ###, tid: ###, name: Binder:###  >>> /system/bin/foobar <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: out-of-bounds'

Quando executado no modo de diagnóstico, o arquivo de origem, o número da linha e o índice são mostrados em logcat. Por padrão, esse modo não lançar uma mensagem de cancelamento. Revise logcat para conferir se há erros.

    external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'