Integridade do fluxo de controle

Segundo dados de 2016, cerca de 86% de todas as vulnerabilidades do Android estavam relacionadas à segurança da memória. relacionados. A maioria das vulnerabilidades é explorada por invasores que mudam a vida Fluxo de controle de um aplicativo para realizar atividades maliciosas arbitrárias com todos os privilégios do aplicativo explorado. Fluxo de controle integridade (CFI) é um mecanismo de segurança que impede alterações na gráfico de fluxo de controle original de um binário compilado, tornando-o significativamente mais difícil para realizar esses ataques.

No Android 8.1, ativamos a implementação de CFI do LLVM na pilha de mídia. Em No Android 9, ativamos a CFI em mais componentes e também no kernel. O CFI do sistema é ativada por padrão, mas é preciso ativar a CFI de kernel.

A CFI do LLVM exige a compilação com Otimização do tempo de vinculação (LTO). A LTO preserva a representação de bitcode do LLVM dos arquivos de objeto até link-time, que permite ao compilador entender melhor quais otimizações que podem ser realizadas. Ativar a LTO reduz o tamanho do binário final e melhora mas aumenta o tempo de compilação. Nos testes no Android, a combinação de LTO e CFI resulta em uma sobrecarga insignificante quanto ao tamanho e ao desempenho do código. em um e alguns casos melhoraram.

Para mais detalhes técnicos sobre o CFI e como outras verificações de controle avançado são são tratados, consulte a página de design do LLVM Documentação.

Exemplos e origem

A CFI é fornecida pelo compilador e adiciona instrumentação ao binário durante tempo de compilação. Oferecemos suporte à CFI no conjunto de ferramentas do Clang e no sistema de compilação do Android. no AOSP.

O CFI é ativado por padrão em dispositivos Arm64 para o conjunto de componentes em /platform/build/target/product/cfi-common.mk: Ele também é ativado diretamente em um conjunto de componentes de mídia makefiles/blueprint arquivos, como /platform/frameworks/av/media/libmedia/Android.bp e /platform/frameworks/av/cmds/stagefright/Android.mk.

Implementação da CFI do sistema

A CFI será ativada por padrão se você usar o Clang e o sistema de build do Android. Como a CFI ajuda a manter os usuários do Android seguros, não a desative.

Na verdade, recomendamos que você habilite a CFI para componentes adicionais. Os candidatos ideais são código nativo privilegiado ou código nativo que processa entradas de usuário não confiáveis. Se você estiver usando o Clang e o sistema de compilação do Android, você pode habilitar a CFI em novos componentes adicionando algumas linhas aos seus makefiles ou arquivos de blueprint.

Compatibilidade com CFI em makefiles

Para ativar a CFI em um arquivo do Make, como /platform/frameworks/av/cmds/stagefright/Android.mk, adicionar:

LOCAL_SANITIZE := cfi
# Optional features
LOCAL_SANITIZE_DIAG := cfi
LOCAL_SANITIZE_BLACKLIST := cfi_blacklist.txt

  • LOCAL_SANITIZE especifica CFI como a limpador durante a ser construído.
  • LOCAL_SANITIZE_DIAG ativa o modo de diagnóstico para a CFI. O modo de diagnóstico imprime informações de depuração adicionais no logcat durante o que é útil para desenvolver e testar seus builds. Marca não se esqueça de remover esse modo nos builds de produção.
  • O LOCAL_SANITIZE_BLACKLIST permite que os componentes desativar a instrumentação CFI para funções individuais ou arquivos de origem. Você pode usar uma lista negra como último recurso para corrigir quaisquer problemas enfrentados pelo usuário que poderia existir de outra forma. Para mais detalhes, consulte Desativação da CFI.

Suporte à CFI em arquivos de blueprint

Para ativar a CFI em um arquivo de blueprint, como /platform/frameworks/av/media/libmedia/Android.bp, faça o seguinte: adicionar:

   sanitize: {
        cfi: true,
        diag: {
            cfi: true,
        },
        blacklist: "cfi_blacklist.txt",
    },

Solução de problemas

Se você ativar a CFI em novos componentes, poderá ter alguns problemas com erros de incompatibilidade de tipo de função e incompatibilidade de tipo de código Assembly erros.

Erros de incompatibilidade de tipo de função ocorrem porque a CFI restringe chamadas indiretas a apenas vamos para funções que possuem o mesmo tipo dinâmico que o tipo estático usado na a chamada. A CFI restringe chamadas de função de membros virtuais e não virtuais para pular apenas a objetos que são uma classe derivada do tipo estático do objeto usado para fazer a chamada. Isso significa que, quando um código viola uma dessas e suposições, a instrumentação adicionada pela CFI será cancelada. Por exemplo, o o stack trace mostra um SIGABRT e o logcat contém uma linha sobre o fluxo de controle e a integridade do sistema encontra uma incompatibilidade.

Para corrigir isso, certifique-se de que a função chamada tenha o mesmo tipo que foi declarado estaticamente. Aqui estão dois exemplos de CLs:

Outro problema possível é tentar ativar a CFI no código que contém chamadas à montagem. Como o código Assembly não é digitado, o resultado é um tipo incompatibilidade.

Para corrigir isso, crie wrappers de código nativo para cada chamada de montagem e atribua empacota a mesma assinatura de função que o poiner de chamada. O wrapper pode então chamar diretamente o código Assembly. Como as ramificações diretas não são instrumentadas CFI (eles não podem ser realocados no tempo de execução e, portanto, não representam um risco de segurança), isso corrigirá o problema.

Se houver muitas funções de montagem e elas não puderem ser corrigidas, também coloca na lista de proibições todas as funções que contêm chamadas indiretas para assembly. Isso é porque desativa as verificações de CFI nessas funções, abrindo de ataque menor.

Como desativar a CFI

Como não observamos sobrecarga no desempenho, não é necessário desativar CFI. No entanto, se houver impacto para o usuário, você poderá desativar seletivamente a CFI para funções individuais ou arquivos de origem, fornecendo um arquivo de lista negra de limpeza durante a compilação. A lista de proibições instrui o compilador a desativar a CFI a instrumentação em locais específicos.

O sistema de build do Android oferece suporte a listas negras por componente, você pode escolher arquivos de origem ou funções individuais que não receberão CFI instrumental) para Make e Soong. Para mais detalhes sobre o formato de um de lista negra, consulte a documentação upstream documentos do Clang (link em inglês).

Validação

No momento, não há testes CTS especificamente para CFI. Em vez disso, verifique se Os testes CTS são aprovados com ou sem a CFI ativada para verificar se a CFI não está afetando o dispositivo.