Somente da mesma maneira que modprobe"derrota" a segurança carregando um novo código no kernel.
Por várias razões, às vezes faz mais sentido ter código semi-privilegiado (como drivers gráficos dentro do servidor X) executando no espaço do usuário em vez de um thread do kernel.
- Ser capaz de
killfazê - lo mais facilmente, a menos que bloqueie o HW.
- Para que ele exija a página de código / dados dos arquivos no sistema de arquivos. (A memória do kernel não é paginável)
- Dando a ele seu próprio espaço de endereço virtual, onde os erros no servidor X podem travar o servidor X, sem derrubar o kernel.
Não faz muito por segurança, mas há grandes vantagens em termos de confiabilidade e arquitetura de software.
A instalação de drivers gráficos no kernel pode reduzir as alternâncias de contexto entre os clientes X e o servidor X, como apenas um usuário-> kernel-> usuário, em vez de ter que colocar dados em outro processo de espaço de uso, mas os servidores X historicamente são muito grandes e com erros demais querer que eles estejam totalmente no kernel.
Sim, o código malicioso com esses privs pode assumir o controle do kernel, se ele quiser, usando /dev/mempara modificar o código do kernel.
Ou no x86, por exemplo, execute uma cliinstrução para desativar as interrupções nesse núcleo depois de fazer uma ioplchamada do sistema para definir seu nível de privilégio de E / S para tocar 0.
Mas mesmo o x86 iopl"only" dá acesso a algumas instruções : in / out (e as versões das strings ins / outs) e cli / sti. Ele não permite que você use rdmsrou wrmsrleia ou escreva "registros específicos do modelo" (por exemplo, IA32_LSTARque define o endereço do ponto de entrada do kernel para a syscallinstrução x86-64 ) ou lidtsubstitua a tabela de descritores de interrupção (o que permitiria sobre a máquina a partir do kernel existente, pelo menos nesse núcleo.)
Você não pode nem ler registros de controle (como o CR3, que contém o endereço físico do diretório de páginas de nível superior, que um processo de ataque pode achar útil como deslocamento /dev/mempara modificar suas próprias tabelas de páginas como uma alternativa mmapa mais /dev/mem. )
invd(invalidar todos os caches sem write-back !! ( caso de uso = BIOS anterior antes da RAM ser configurada)) é outro divertido que sempre exige CPL 0 total (nível de privilégio atual), não apenas IOPL. Even wbinvdé privilegiado porque é muito lento (e não pode ser interrompido) e precisa liberar todos os caches em todos os núcleos. (Consulte Existe uma maneira de liberar todo o cache da CPU relacionado a um programa? E uso de instruções WBINVD )
Os erros que resultam em um salto para um endereço incorreto executando dados como código, portanto, não podem executar nenhuma dessas instruções por acidente em um servidor X no espaço do usuário.
O nível de privilégio atual (no modo protegido e longo) são os 2 bits baixos de cs(o seletor de segmento de código) . mov eax, cs/ and eax, 3trabalha em qualquer modo para ler o nível de privilégio.
Para escrever o nível de privilégio, você deve definir jmp farou call fardefinir CS:RIP(mas a entrada GDT / LDT para o segmento de destino pode restringi-lo com base no antigo nível de privilégio, e é por isso que o espaço do usuário não pode fazer isso para se elevar). Ou você pode usar intou syscallpara alternar para tocar 0 no ponto de entrada do kernel.
ioplnão permite todas as instruções privilegiadas, por isso ainda é útil para garantir que um programa de espaço de usuário com erros não seja executado acidentalmenteinvdsaltando por um ponteiro de função corrompido que aponta para a memória executável iniciada por0F 08bytes. Adicionei uma resposta com alguns dos motivos que não são de segurança, pelos quais é útil fazer com que os processos no espaço do usuário elevem seus privilégios.