Como o kernel impede que um programa malicioso leia toda a RAM física?

10

Se eu escrever um programa que tente ler a memória em todos os endereços possíveis e executá-lo em um Unix "cheio", ele não poderá acessar toda a RAM física. Mas como o sistema operacional impede isso?

Eu estou mais familiarizado com pequenas arquiteturas de CPU, onde qualquer parte do código de montagem pode acessar tudo. Não entendo como um programa (o kernel) pode detectar essas operações maliciosas.

nowox
fonte
2
Normalmente, a MMU cuida para que você não possa acessar a memória fora das áreas permitidas.
ott--
1
Bem, a MMU é configurada pelo assembly. Assim, um código de montagem pode alterar a configuração da MMU e acessar uma página de memória diferente, certo?
nowox
Isso só é verdade se você executar seu código como root.
#
2
Você deve ler sobre tabelas de páginas e abstração do kernel.
Clarus
@ott: nem o root pode modificar o MMU (pelo menos não no Linux). Somente o kernel faz.
Basile Starynkevitch

Respostas:

12

Não é o kernel que está impedindo o acesso à memória ruim, é a CPU. O papel do kernel é apenas configurar a CPU corretamente.

Mais precisamente, o componente de hardware que impede o acesso ruim à memória é a MMU . Quando um programa acessa um endereço de memória, o endereço é decodificado pela CPU com base no conteúdo da MMU. A MMU estabelece uma tradução de endereços virtuais para endereços físicos: quando a CPU carrega ou armazena em um determinado endereço virtual, calcula o endereço físico correspondente com base no conteúdo da MMU. O kernel define a configuração do MMU de forma que cada programa possa acessar apenas a memória a que tem direito. Os registros de memória e hardware de outros programas não são mapeados na memória de um programa: esses endereços físicos não têm um endereço virtual correspondente na configuração da MMU para esse programa.

Em uma alternância de contexto entre diferentes processos, o kernel modifica a configuração do MMU para que contenha a tradução desejada para o novo processo.

Alguns endereços virtuais não são mapeados, ou seja, a MMU os converte em um valor especial "sem esse endereço". Quando o processador desreferencia um endereço não mapeado, isso causa uma interceptação: o processador ramifica para um local predefinido no código do kernel. Algumas armadilhas são legítimas; por exemplo, o endereço virtual pode corresponder a uma página que esteja no espaço de troca ; nesse caso, o código do kernel carregará o conteúdo da página da troca e retornará ao programa original de forma que a instrução de acesso à memória seja executada novamente. Outros traps não são legítimos; nesse caso, o processo recebe um sinal que, por padrão, mata o programa imediatamente (e, se não for, ramifica para o manipulador de sinais no programa: em qualquer caso, a instrução de acesso à memória não é concluída).

Gilles 'SO- parar de ser mau'
fonte
Você poderia especificar um pouco a afirmação "o endereço é decodificado pela CPU com base no conteúdo da MMU" ? Existe um código real no programa em execução que decodifica os endereços? Ou quando uma CPU faz um acesso a um endereço - o acesso é feito à MMU, que a traduz / manipula adequadamente (faz um acesso à memória ou ao cache e retorna o resultado ou aciona um procedimento de kernel)? Assim, da perspectiva do microcontrolador / montagem, a MMU é uma nova peça. A CPU não está conectada diretamente à memória, está conectada à MMU e é aí que a abstração da memória virtual é feita.
xealits
3
@xealits A tradução do endereço virtual para o endereço físico é feita dentro da MMU, que é um circuito de hardware. Não há código para fazer isso no programa ou no kernel. O kernel é invocado apenas em casos excepcionais, quando o programa tenta acessar um endereço virtual para o qual a entrada MMU diz "endereço inválido". O kernel também faz o trabalho de configurar os registradores e as tabelas na RAM que a MMU usa.
Gilles 'SO- stop be evil'