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, cominteger_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]'