Sanitização por transbordamento de inteiros

Estouros de inteiros não intencionais podem causar corrupção de memória ou vulnerabilidades de divulgação de informações em variáveis ​​associadas a acessos ou alocações de memória. Para combater isso, adicionamos os sanitizadores de estouro de inteiros assinados e não assinados do Clang UndefinedBehaviorSanitizer (UBSan) para fortalecer a estrutura de mídia no Android 7.0. No Android 9, expandimos o UBSan para cobrir mais componentes e melhorar o suporte do sistema de compilação para ele.

Isso foi projetado para adicionar verificações em torno de operações/instruções aritméticas - que podem estourar - para abortar com segurança um processo se ocorrer um estouro. Esses sanitizadores podem mitigar uma classe inteira de vulnerabilidades de corrupção de memória e divulgação de informações em que a causa raiz é um estouro de número inteiro, como a vulnerabilidade original do Stagefright.

Exemplos e fonte

O Integer Overflow Sanitization (IntSan) é fornecido pelo compilador e adiciona instrumentação ao binário durante o tempo de compilação para detectar overflows aritméticos. Ele é habilitado por padrão em vários componentes em toda a plataforma, por exemplo /platform/external/libnl/Android.bp .

Implementação

IntSan usa sanitizadores de estouro de inteiros assinados e não assinados do UBSan. Essa mitigação é habilitada em um nível por módulo. Ele ajuda a manter os componentes críticos do Android seguros e não deve ser desativado.

Recomendamos que você habilite a Sanitização por estouro de número inteiro para componentes adicionais. Os candidatos ideais são código nativo privilegiado ou código nativo que analisa a entrada do usuário não confiável. Há uma pequena sobrecarga de desempenho associada ao desinfetante 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 o desempenho é uma preocupação.

Suportando IntSan em makefiles

Para habilitar o IntSan em um makefile, adicione:

LOCAL_SANITIZE := integer_overflow
# Optional features
LOCAL_SANITIZE_DIAG := integer_overflow
LOCAL_SANITIZE_BLACKLIST := modulename_blacklist.txt
  • LOCAL_SANITIZE pega uma lista de sanitizadores separados por vírgula, com integer_overflow sendo um conjunto pré-empacotado de opções para sanitizadores de estouro de inteiros assinados e não assinados com uma lista negra padrão .
  • LOCAL_SANITIZE_DIAG ativa o modo de diagnóstico para os sanitizadores. Use o modo de diagnóstico apenas durante o teste, pois isso não será abortado em estouros, negando completamente a vantagem de segurança da mitigação. Consulte Solução de problemas para obter detalhes adicionais.
  • LOCAL_SANITIZE_BLACKLIST permite especificar um arquivo de lista negra para evitar que funções e arquivos de origem sejam limpos. Consulte Solução de problemas para obter detalhes adicionais.

Se você quiser um controle mais granular, habilite os sanitizadores individualmente usando um ou ambos os sinalizadores:

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

Suportando IntSan em arquivos de blueprint

Para habilitar a sanitização de estouro de número inteiro em um arquivo de blueprint, como /platform/external/libnl/Android.bp , adicione:

   sanitize: {
      integer_overflow: true,
      diag: {
          integer_overflow: true,
      },
      blacklist: "modulename_blacklist.txt",
   },

Assim como os arquivos make, a propriedade integer_overflow é um conjunto pré-empacotado de opções para os sanitizadores de estouro de inteiros assinados e não assinados com uma lista negra padrão .

O diag de propriedades de diagnóstico habilita o modo de diagnóstico para os sanitizantes. Use o modo de diagnóstico apenas durante o teste. O modo de diagnóstico não aborta em estouros, o que nega completamente a vantagem de segurança da mitigação nas compilações do usuário. Consulte Solução de problemas para obter detalhes adicionais.

A propriedade blacklist permite a especificação de um arquivo de lista negra que permite aos desenvolvedores impedir que funções e arquivos de origem sejam higienizados. Consulte Solução de problemas para obter detalhes adicionais.

Para habilitar os sanitizantes individualmente, use:

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

Solução de problemas

Se você estiver habilitando a sanitização de estouro de número inteiro em novos componentes ou depender de bibliotecas de plataforma que tiveram sanitização de estouro de número inteiro, você poderá encontrar alguns problemas com estouros de número inteiro benignos causando abortos. Você deve testar os componentes com a sanitização habilitada para garantir que estouros benignos possam aparecer.

Para encontrar, aborts causados ​​por sanitização em builds de usuários, procure por travamentos do SIGABRT com mensagens Abort indicando um estouro capturado pelo UBSan, como:

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

O rastreamento de pilha deve incluir a função que está causando a interrupção, no entanto, estouros que ocorrem em funções inline podem não ser evidentes no rastreamento de pilha.

Para determinar mais facilmente a causa raiz, habilite o diagnóstico na biblioteca que aciona a interrupção e tente reproduzir o erro. Com o diagnóstico ativado, o processo não será abortado e continuará a ser executado. Não abortar ajuda a maximizar o número de estouros benignos em um caminho de execução específico sem ter que recompilar após corrigir cada bug. O diagnóstico produz uma mensagem de erro que inclui o número da linha e o arquivo de origem que está causando a interrupção:

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')

Uma vez localizada a operação aritmética problemática, certifique-se de que o estouro é benigno e intencional (por exemplo, não tem implicações de segurança). Você pode resolver a interrupção do desinfetante por:

  • Refatorando o código para evitar o estouro ( exemplo )
  • Estouro explicitamente por meio das funções __builtin_*_overflow do Clang ( exemplo )
  • Desabilitando a sanitização na função especificando o atributo no_sanitize ( exemplo )
  • Desativando a sanitização de uma função ou arquivo de origem por meio de um arquivo de lista negra ( exemplo )

Você deve usar a solução mais granular possível. Por exemplo, uma função grande com muitas operações aritméticas e uma única operação de estouro deve ter a única operação refatorada em vez de toda a função na lista negra.

Padrões comuns que podem resultar em estouros benignos incluem:

  • Casts implícitos em que um estouro não assinado ocorre antes de ser convertido em um tipo assinado ( exemplo )
  • Exclusões de lista vinculada que diminui o índice de loop na exclusão ( exemplo )
  • Atribuindo um tipo não assinado a -1 em vez de especificar o valor máximo real ( exemplo )
  • Loops que decrementam um inteiro sem sinal na condição ( exemplo , exemplo )

Recomenda-se que os desenvolvedores garantam que, nos casos em que o desinfetante detecta um estouro, ele é realmente benigno, sem efeitos colaterais indesejados ou implicações de segurança antes de desabilitar a higienização.

Desativando IntSan

Você pode desabilitar o IntSan com listas negras ou atributos de função. Desabilite com moderação e somente quando refatorar o código não for razoável ou se houver sobrecarga de desempenho problemática.

Consulte a documentação upstream do Clang para obter mais informações sobre como desabilitar o IntSan com atributos de função e formatação de arquivo de lista negra . A lista negra deve ter como escopo o desinfetante específico usando nomes de seção que especificam o desinfetante de destino para evitar afetar outros desinfetantes.

Validação

Atualmente, não há teste CTS especificamente para Sanitização por transbordamento inteiro. Em vez disso, certifique-se de que os testes CTS sejam aprovados com ou sem IntSan habilitado para verificar se ele não está afetando o dispositivo.