Postado por Sami Tolvanen, engenheiro de software da equipe, Segurança do Android
O modelo de segurança do Android é executado pelo kernel do Linux, o que faz dele um alvo tentador para invasores. Temos nos esforçado bastante para aumentar a proteção do kernel em versões anteriores do Android e no Android 9. Demos continuidade a esse trabalho nos concentrando em mitigações de segurança por compilador contra ataques de reutilização de código.
O Pixel 3 do Google será o primeiro dispositivo Android a ser fornecido com a implementação de ponta no kernel do LLVM, a Integridade do fluxo de controle (CFI) , e o suporte à CFI estará disponível para as versões 4.9 e 4.14 do kernel do Android . Esta postagem descreve como a CFI de kernel funciona e oferece soluções para os problemas mais comuns que os desenvolvedores podem encontrar ao ativar o recurso.
Proteção contra ataques de reutilização de código
Um método comum de explorar o kernel é usar um bug para substituir um ponteiro de função armazenado na memória, como um ponteiro de callback ou um endereço de retorno que foi colocado na pilha. Ele permite que o invasor execute partes arbitrárias do código do kernel para completar a exploração, mesmo que não possa inserir um código executável próprio. Esse método de conquista de execução de código é especialmente popular com o kernel devido ao imenso número de ponteiros de função que ele usa e também por causa das proteções existentes da memória que tornam a inserção de código mais desafiadora.
A CFI tenta mitigar esses ataques adicionando verificações extras para confirmar que o fluxo de controle do kernel fica dentro de um gráfico pré-calculado. Isso não evita que um invasor altere um ponteiro de função se um bug conceder acesso de gravação, mas restringe de modo significativo os destinos válidos de chamada, o que dificulta muito mais a exploração desse bug na prática.
Figura 1. Em um kernel de dispositivo Android, a CFI do LLVM limita 55% das chamadas indiretas a, no máximo, 5 destinos possíveis e 80% a, no máximo, 20 destinos.
Ganho de visibilidade completa do programa com a Otimização de Tempo de Vinculação (LTO)
Para determinar todos os destinos válidos de chamadas para cada branch indireto, o compilador precisa ver todo o código de kernel de uma vez. Tradicionalmente, os compiladores trabalham em uma única unidade de compilação (arquivo fonte) por vez e deixam a combinação dos arquivos de objeto para o vinculador. A solução do LLVM para a CFI é exigir o uso da LTO, na qual o compilador produz bitcode específico ao LLVM para todas as unidades de compilação C, e um vinculador com reconhecimento da LTO usa um backend do LLVM para combinar o bitcode e compilá-lo em código nativo.
Figura 2. Uma visão geral simplificada do funcionamento da LTO no kernel. Todo o bitcode do LLVM é combinado, otimizado e gerado em código nativo na hora de vincular.
Durante décadas, o Linux usou a cadeia de ferramentas GNU para montar, compilar e vincular o kernel. Embora continuemos usando o assembler GNU para o código de montagem autônomo, a LTO exige que mudemos para o assembler integrado do LLVM para a montagem em linha, com o GNU gold ou o próprio lld do LLVM como vinculador. Mudar para uma cadeia de ferramentas relativamente não testada em um projeto de software imenso pode resultar em problemas de compatibilidade, que já foram resolvidos em nossos conjuntos de patches arm64 LTO para as versões do kernel 4.9 e 4.14 .
Além de possibilitar a CFI, a LTO também produz um código mais rápido devido a otimizações globais. Entretanto, otimizações adicionais em geral resultam em um tamanho binário maior, o que pode ser indesejável em dispositivos com recursos muito limitados. Desativar as otimizações específicas à LTO, como indentação global e desenrolamento de loops, pode reduzir o tamanho binário, mas isso sacrifica parte dos ganhos de desempenho. Ao usar o GNU gold, as otimizações mencionadas acima podem ser desativadas com as seguintes adições às LDFLAGS:
LDFLAGS += -plugin-opt=-inline-threshold=0 \
-plugin-opt=-unroll-threshold=0
As sinalizações para desativar otimizações individuais não fazem parte da interface estável do LLVM e podem mudar em versões futuras do compilador.
Implementação da CFI no kernel do Linux
A implementação da CFI do LLVM adiciona uma verificação antes de cada branch indireto para confirmar que o endereço de destino direciona para uma função válida com uma assinatura correta. Isso evita que um branch indireto pule para um local de código arbitrário e até mesmo limite as funções que podem ser chamadas. Como os compiladores C não implementam restrições similares em branches indiretos, ocorreram diversas violações de CFI devido a discrepâncias nas declarações dos tipos de função mesmo no kernel principal que tratamos em nossos conjuntos de patches CFI para kernels 4.9 e 4.14 .
Os módulos do kernel adicionam outra complicação à CFI, já que são carregados no tempo de execução e podem ser compilados de modo independente do resto do kernel. Para aceitar módulos que podem ser carregados, implementamos o suporte à CFI entre DSO do LLVM no kernel, incluindo uma sombra CFI que acelera as pesquisas entre módulos. Quando compilados com suporte entre DSO, cada módulo de kernel contém informações sobre os destinos válidos do branch local, e o kernel busca informações no módulo correto com base no endereço de destino e no layout de memória dos módulos.
Figura 3. Um exemplo de verificação de CFI entre DSO inserida em um kernel arm64. As informações sobre o tipo são passadas em X0, e o endereço do destino para validação, em X1.
As verificações da CFI adicionam naturalmente uma sobrecarga aos branches indiretos, mas devido a otimizações mais agressivas, nossos testes mostram que o impacto é mínimo, e o desempenho geral do sistema até melhorou de 1 a 2% na maioria dos casos.
Ativação da CFI de kernel para um dispositivo Android
A CFI para arm64 exige a versão de clang superior ou igual a 5.0 e binutils superior ou igual a 2.27. O sistema de compilação de kernel também presume que o plug-in LLVMgold.so está disponível em LD_LIBRARY_PATH. Binários pré-criados da cadeia de ferramentas para clang e binutils estão disponíveis em AOSP, mas binários upstream também podem ser usados.
As seguintes opções de configuração de kernel são necessárias para ativar a CFI de kernel:
CONFIG_LTO_CLANG=y
CONFIG_CFI_CLANG=y
Usar CONFIG_CFI_PERMISSIVE=y também pode ser útil ao depurar uma violação de CFI ou durante a preparação do dispositivo. Essa opção transforma uma violação em um aviso em vez de um kernel panic.
Como mencionado na seção anterior, o problema mais comum que encontramos ao ativar a CFI no Pixel 3 foram violações inofensivas causadas por discrepâncias no tipo de ponteiro de função. Quando o kernel é executado nessa violação, comunica um aviso de tempo de execução que contém a pilha de chamadas no momento da falha e o destino da chamada que falhou na verificação de CFI. Alterar o código para usar um tipo de ponteiro de função correto resolve o problema. Apesar de termos corrigido todas as discrepâncias conhecidas no tipo de branch indireto no kernel do Android, problemas semelhantes ainda podem ser encontrados em drivers específicos ao dispositivo, por exemplo.
CFI failure (target: [<fffffff3e83d4d80>] my_target_function+0x0/0xd80):
------------[ cut here ]------------
kernel BUG at kernel/cfi.c:32!
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
…
Call trace:
…
[<ffffff8752d00084>] handle_cfi_failure+0x20/0x28
[<ffffff8752d00268>] my_buggy_function+0x0/0x10
…
Figura 4. Um exemplo de kernel panic causado por uma falha da CFI.
Outra possível dificuldade são os conflitos de espaço de endereço, mas isso deve ser menos comum em código de driver. As verificações da CFI do LLVM só entendem o endereço virtual do kernel, e qualquer código executado em outro nível de exceção ou que faz uma chamada indireta a um endereço físico resultará em uma violação de CFI. Esses tipos de falha podem ser resolvidos com a desativação da CFI para uma função individual usando o atributo __nocfi ou desativando a CFI para arquivos de código inteiros ao usar a sinalização de compilador $(DISABLE_CFI) no Makefile.
static int __nocfi address_space_conflict()
{
void (*fn)(void);
…
/* branching to a physical address trips CFI w/o __nocfi */
fn = (void *)__pa_symbol(function_name);
cpu_install_idmap();
fn();
cpu_uninstall_idmap();
…
}
Figura 5. Um exemplo de correção de uma falha da CFI causada por um conflito de espaço de endereço.
Por fim, como vários recursos de aumento da proteção, a CFI também pode ser acionada por erros de corrompimento de memória que poderiam resultar em falhas aleatórias do kernel mais tarde. Isso pode ser mais difícil de depurar, mas ferramentas de depuração de memória como KASAN podem ser úteis neste caso.
Conclusão
Implementamos suporte para a CFI do LLVM nos kernels 4.9 e 4.14 do Android. O Pixel 3 do Google será o primeiro dispositivo Android a ser fornecido com essas proteções, e disponibilizamos o recurso para todos os fornecedores de dispositivo pelo kernel comum do Android. Se você estiver fornecendo um novo dispositivo arm64 com Android 9, recomendamos a ativação da CFI de kernel para ajudar na proteção contra as vulnerabilidades do kernel.
A CFI do LLVM protege os branches indiretos contra invasores que conseguem acesso a um ponteiro de função armazenado na memória do kernel. Isso dificulta um método comum de exploração do kernel. Nosso trabalho futuro envolve também a proteção dos endereços de retorno de função contra ataques similares com o uso da Pilha de chamadas de sombra do LLVM, que estará disponível em uma versão futura do compilador.
4 comentários :
Situs Judi Terpercaya dewapoker online pasti memberikan fasilitas sistem permainan poker online yang canggih, proses transaksi yang sangat cepat, dan pelayanan terbaik demi kenyamanan semua member. Bagi anda yang ingin bermain judi online seperti permainan poker online,domino qiu qiu, ceme,blackjack, ataupun capsa susun bisa mendaftarkan diri anda di dewa poker . dewa poker online menjadi Trendsetter Game Judi Poker Online Paling Terpercaya dan Recommended dari berbagai Situs, Blog, Media Sosial dan Beberapa Grup Pecinta Game Online Uang Asli.
Tidak ada orang yang selalu beruntung dalam bermain poker online. Raih kemenangan judi online anda bersama kami sekarang juga, dan rasakan sensasi permainan Player Vs Player 100% dan dapatkan jackpot yang sangat mudah hanya di poker online 2019. Pokerbo888 BANDAR POKER ONLINE DAN AGEN DOMINO QIU QIU TERPERCAYA DI INDONESIA. Dan tidak lupa lagi POKER 88 akan memberikan tambahan chips untuk member baru yang mendaftar dan melakukan deposit dengan ketentuan sebagai berikut : 1. BONUS DEPOSIT MEMBER BARU 100.000. TERPERCAYA DAN PERTAMA YANG MENERIMA DEPOSIT VIA GOPAY ,GABUNG DAN DAPATKAN BONUS DEPOSIT PERDANA DIWEBSITE KAMI POKERBO888.
Banyak sekali kelebihan dari situs judi online yang akan membantu anda untuk menyalurkan hobi anda. Judi bola mainbolajalan adalah tempat bermain yang aman dan menyenangkan untuk mengasah ketangkasan yang anda miliki. Bermain judi bola online lebih menguntungkan dibandingkan anda bermain judi bola darat dan juga banyak hadiah dan bonus bonus menarik yang bisa anda dapatkan di situs resmi kami agen judi online terpercaya, AYO DAFTAR SEKARANG DI MAINBOLAJALAN.COM
You can get useful info about MLA Style on https://pro-essay-writer.com/blog/mla-style-guide. I had such experience, by the way
papua4d
ojktoto
rubah4d
Togel online
Postar um comentário