STACKLEAK é um recurso de segurança do kernel Linux desenvolvido originalmente pelos criadores do Grsecurity / PaX. Decidi trazer STACKLEAK para o kernel oficial baunilha (linha principal do kernel Linux). Este artigo abordará a estrutura interna, as propriedades dessa função de segurança e seu longo e difícil caminho na linha principal.

O STACKLEAK protege contra várias classes de vulnerabilidades no kernel do Linux, a saber:
- reduz as informações úteis para o atacante, que podem vazar da pilha nuclear para o espaço do usuário;
- bloqueia alguns ataques a variáveis não inicializadas na pilha do kernel;
- fornece ferramentas dinâmicas de detecção de estouro de pilha.
Esse recurso de segurança se encaixa perfeitamente no conceito do Kernel Self Protection Project (KSPP): segurança é mais do que apenas corrigir bugs. Absolutamente todos os erros no código não podem ser corrigidos e, portanto, o kernel do Linux deve funcionar com segurança em situações de erro, inclusive ao tentar explorar vulnerabilidades. Mais detalhes sobre o KSPP estão
disponíveis no wiki do projeto .
STACKLEAK está presente como PAX_MEMORY_STACKLEAK no patch grsecurity / PaX. No entanto, o patch grsecurity / PaX deixou de ser distribuído gratuitamente desde abril de 2017. Portanto, a aparência do STACKLEAK no kernel vanilla seria valiosa para usuários do Linux com maiores requisitos de segurança da informação.
Ordem de serviço:
- selecione STACKLEAK no patch grsecurity / PaX,
- estude o código cuidadosamente e forme um patch,
- envie para o LKML, obtenha feedback, melhore, repita novamente antes de ser aceito na linha principal.
No momento da redação deste artigo (25 de setembro de 2018), a
versão 15 de uma série de patches foi enviada. Ele contém uma parte e um código independentes da arquitetura para x86_64 e x86_32. O suporte do STACKLEAK para arm64, desenvolvido por Laura Abbott da Red Hat, já conseguiu entrar no kernel 4.19 da baunilha.
STACKLEAK: recursos de segurança
Limpando Informações Residuais na Pilha do Kernel
Essa medida reduz as informações úteis que alguns vazamentos da pilha nuclear para o espaço do usuário podem produzir.
Um exemplo de vazamento de informações da pilha do kernel é apresentado na Figura 1.
Esquema 1.No entanto, vazamentos desse tipo se tornam inúteis se, no final de uma chamada do sistema, a parte usada da pilha do kernel for preenchida com um valor fixo (Figura 2).

Esquema 2.
Como resultado, STACKLEAK bloqueia alguns ataques a variáveis não inicializadas na pilha do kernel. Exemplos de tais vulnerabilidades: CVE-2017-17712, CVE-2010-2963. Podemos encontrar uma descrição da metodologia de exploração para a vulnerabilidade CVE-2010-2963
em um artigo de Kees Cook.
A essência do ataque a uma variável não inicializada na pilha do kernel é mostrada na Figura 3.
Esquema 3.STACKLEAK bloqueia ataques desse tipo, pois o valor que preenche a pilha nuclear no final de uma chamada do sistema indica uma área não utilizada no espaço de endereço virtual (Figura 4).
Esquema 4.Uma limitação importante é que o STACKLEAK não protege contra ataques semelhantes executados em uma única chamada do sistema.
Detecção de estouro de pilha no núcleo do kernel
No kernel vanilla (linha principal do kernel Linux), STACKLEAK é eficaz contra o estouro de profundidade da pilha do kernel somente em conjunto com CONFIG_THREAD_INFO_IN_TASK e CONFIG_VMAP_STACK. Ambas as medidas são implementadas por Andy Lutomirski.
A versão mais simples de explorar esse tipo de vulnerabilidade é mostrada na Figura 5.
Esquema 5.A substituição de certos campos na estrutura thread_info na parte inferior da pilha nuclear pode aumentar os privilégios do processo. No entanto, quando a opção CONFIG_THREAD_INFO_IN_TASK está ativada, essa estrutura é removida da pilha nuclear, o que elimina o método descrito para explorar a vulnerabilidade.
Uma versão mais avançada desse ataque é substituir dados em uma região de memória vizinha saindo da borda da pilha. Mais sobre essa abordagem:
Esse tipo de ataque é refletido na Figura 6.
Esquema 6.A proteção neste caso é CONFIG_VMAP_STACK. Quando essa opção está ativada, uma página de memória especial (página de proteção) é colocada ao lado da pilha nuclear, cujo acesso leva a uma exceção (Figura 7).
Esquema 7.Finalmente, a opção mais interessante de transbordar a pilha em profundidade é um ataque como o Stack Clash. A idéia foi
apresentada por Gael Delalleau em 2005.
Em 2017, pesquisadores da empresa Qualys repensaram o assunto,
chamando essa técnica de Stack Clash. O fato é que existe uma maneira de pular a página de proteção e substituir dados de uma região de memória vizinha (Figura 8). Isso é feito usando uma matriz de comprimento variável (VLA), cujo tamanho é controlado pelo invasor.
Esquema 8.Para mais informações sobre STACKLEAK e Stack Clash,
consulte o blog grsecurity .
Como o STACKLEAK protege contra Stack Clash na pilha nuclear? Antes de cada chamada para alloca (), uma verificação é realizada para o estouro da pilha em profundidade. Aqui está o código correspondente da versão 14 da série de patches:
void __used stackleak_check_alloca(unsigned long size) { unsigned long sp = (unsigned long)&sp; struct stack_info stack_info = {0}; unsigned long visit_mask = 0; unsigned long stack_left; BUG_ON(get_stack_info(&sp, current, &stack_info, &visit_mask)); stack_left = sp - (unsigned long)stack_info.begin; if (size >= stack_left) { #if !defined(CONFIG_VMAP_STACK) && defined(CONFIG_SCHED_STACK_END_CHECK) panic("alloca() over the kernel stack boundary\n"); #else BUG(); #endif } }
No entanto, essa funcionalidade foi excluída da versão 15. Isso ocorreu principalmente devido à
proibição controversa de Linus Torvalds
no uso de BUG_ON () nos patches de segurança do kernel do Linux.
Além disso, a 9ª versão da série de patches levou a uma discussão, como resultado da qual foi decidido eliminar todas as matrizes variáveis do kernel da linha principal. Cerca de 15 desenvolvedores estiveram envolvidos neste trabalho, e ele será
concluído em breve.
Impacto no desempenho da STACKLEAK
Dou os resultados dos testes de desempenho em x86_64. Equipamento: Intel Core i7-4770, 16 GB de RAM.
Teste 1, atraente: construindo um kernel Linux em um único núcleo de processador
Teste nº 2, sem atrativos:
Portanto, o efeito do STACKLEAK no desempenho do sistema depende do tipo de carga. Em particular, um grande número de chamadas curtas ao sistema aumenta a sobrecarga. T.O. O desempenho do STACKLEAK deve ser avaliado para a carga planejada antes da produção.
Dispositivo interno STACKLEAK
STACKLEAK consiste em:
- O código que limpa a pilha do kernel no final da chamada do sistema (originalmente escrito em assembler),
- Plug-in GCC para compilação instrumental de código do kernel.
A limpeza da pilha do kernel é feita na função stackleak_erase (). Essa função é concluída antes de retornar ao espaço do usuário após uma chamada do sistema. O STACKLEAK_POISON (-0xBEEF) é gravado na parte usada da pilha de encadeamentos. A variável lower_stack, atualizada constantemente em stackleak_track_stack (), aponta para o ponto inicial da limpeza.
Os estágios de stackleak_erase () são refletidos nos esquemas 9 e 10.
Esquema 9.
Esquema 10.T.O. stackleak_erase () limpa apenas a parte usada da pilha nuclear. É por isso que STACKLEAK é tão rápido. E se você limpar todos os 16 kB da pilha do kernel em x86_64 no final de cada chamada do sistema, o hackbench exibirá uma queda de desempenho de 40%.
A instrumentação do código do kernel no estágio de compilação é realizada no plug-in STACKLEAK GCC.
Os plug-ins do GCC são módulos para download específicos do projeto para o compilador do GCC. Eles registram novos passes no GCC Pass Manager, fornecendo retornos de chamada para esses passes.
Portanto, para a operação STACKLEAK de pleno direito, as chamadas para stackleak_track_stack () são inseridas no código de funções com um grande quadro de pilha. Além disso, antes de cada alloca (), uma chamada para o já mencionado stackleak_check_alloca () é inserida e, depois disso, uma chamada para stackleak_track_stack () é inserida.
Como já mencionado, na versão 15 da série de patches, a inserção de chamadas para stackleak_check_alloca () foi excluída do plug-in GCC.
Caminho na linha principal do kernel Linux
O caminho STACKLEAK na linha principal é muito longo e difícil (Figura 11).
Esquema 11. Progresso na implementação do STACKLEAK na linha principal do kernel Linux.Em abril de 2017, os criadores do grsecurity fecharam seus patches para a comunidade, começando a distribuí-los apenas em uma base comercial. Em maio de 2017, decidi assumir a tarefa de introduzir STACKLEAK no núcleo da baunilha. Assim começou uma jornada mais de um ano. A empresa Positive Technologies, na qual trabalho, me dá a oportunidade de lidar com essa tarefa durante parte do meu tempo de trabalho. Mas, basicamente, passo tempo "livre" nele.
Desde maio passado, minha série de patches passou por várias revisões, sofreu mudanças significativas, foi criticada duas vezes por Linus Torvalds. Eu queria deixar essa coisa toda muitas vezes. Mas, em determinado momento, havia um firme desejo de chegar ao fim. No momento da escrita (25 de setembro de 2018), a 15ª versão da série de patches estava no ramo linux-next, atende a todos os requisitos estabelecidos pelo Linus e está pronta para a janela de mesclagem do kernel 4.20 / 5.0.
Há um mês, falei sobre esse trabalho no Linux Security Summit. Eu forneço links para
slides e
vídeos :
Conclusão
STACKLEAK é um recurso de segurança do kernel Linux muito útil que bloqueia a exploração de vários tipos de vulnerabilidades ao mesmo tempo. Além disso, o autor original do PaX Team conseguiu torná-lo rápido e bonito na engenharia. Portanto, a aparência do STACKLEAK no kernel vanilla seria valiosa para usuários do Linux com maiores requisitos de segurança da informação. Além disso, o trabalho nessa direção chama a atenção da comunidade de desenvolvedores Linux para as ferramentas de autodefesa do kernel.
PS
STACKLEAK foi finalmente adotado pelo kernel Linux 4.20:
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2d6bb6adb714b133db92ccd4bfc9c20f75f71f3fAs arquiteturas suportadas são x86_64, x86_32 e arm64.
Além disso, foi concluído o trabalho para eliminar matrizes de tamanho variável do código do kernel do Linux. O aviso do compilador Gcc "-Wvla" está incluído na versão 4.20 do kernel:
lkml.org/lkml/2018/10/28/189