Como o SO detecta violações de acesso à memória

12

Como um sistema operacional (preferencialmente Linux) sabe que você acessou um local de memória ao qual não tem permissão?

Esta pergunta foi inspirada por aqueles ponteiros malditos! A maneira que eu vejo é: tudo em computadores é sobre um compromisso entre velocidade, segurança, integridade e coisas do tipo.

Estou bem ciente dos mapas de memória no Linux, mas parece um pouco ridículo para mim que o kernel verifique se o local que você está tentando acessar reside em um intervalo válido TODAS AS VEZES que você faz um acesso. Parece que gastaria tanto tempo, que poderia ser gasto fazendo algo mais produtivo (mas possivelmente menos seguro sem verificação!). Ou talvez ele se lembre de todos os acessos recentes e os verifique em cada tick do timer de hardware? (Mas isso parece inseguro e, mais uma vez, lento.)

Fiquei surpreso que esta pergunta parece não ter sido respondida em nenhum lugar. É algo que sempre me perguntei. Isso me faz pensar que há uma seção de hardware que fará isso em nome do sistema operacional, em um nível agradável e conveniente de abstração. Mas ainda assim, possivelmente seria necessário carregar os próximos mapas de memória de processos em todos os switches de contexto, o que novamente parece lento.

Então, sim, de qualquer maneira, estou indo um pouco: como um SO detecta uma violação de memória?

Obrigado

    
por Doddy 17.09.2010 / 22:23

2 respostas

11

(A resposta a seguir pressupõe uma plataforma “moderna” de desktop, servidor ou plataforma de ponta (como smartphones, e cada vez mais sistemas menores também.) Para sistemas x86, o moderno significa 386 ou superior. A resposta a seguir também assume um sistema operacional "moderno", como quase qualquer unix, ou o Windows desde 95.

Isso não está acontecendo no SO, está acontecendo no processador, especificamente na MMU (< strong> unidade de gerenciamento de memória ) . A MMU suporta o endereçamento virtual, por meio do qual os bits que compõem um ponteiro não indicam diretamente a localização física dos bits na memória.

Em uma MMU típica, quando um ponteiro é desreferenciado, a MMU decompõe os bits em dois grupos: os bits de alta ordem compõem o número de página e os bits de baixa ordem formam o endereço dentro da página. A maioria das máquinas de desktop e servidor usa páginas de 4kB. A MMU procura o número da página virtual em uma tabela chamada TLB (é isso que você chama de “mapas de memória de processo”). O TLB indica o número da página física que corresponde a essa página virtual. A MMU então busca os dados da página física na memória.

Se o TLB não contiver uma entrada para esse número de página virtual específico, a MMU notificará o processador que ocorreu um acesso inválido; isso é tipicamente chamado de exceção.

Note que eu não mencionei o SO até agora. Isso porque toda essa operação é independente do sistema operacional. O SO entra em ação porque configura as coisas de duas maneiras:

  • O sistema operacional é responsável por alternar tarefas. Quando isso acontece, como você suspeitava, ele salva o TLB atual e o substitui pelo TLB salvo para a próxima tarefa agendada. Dessa forma, cada processo tem um TLB, portanto, o endereço 0x123456 no processo X pode não apontar para o mesmo local real na RAM que o mesmo endereço no processo Y ou pode simplesmente ser inválido. Se um processo tentar excluir a referência de um ponteiro fora de seu espaço de endereço, ele não alcançará o espaço de outro processo, em vez disso, ele alcançará nowhere .

  • O SO decide o que acontece quando uma exceção é levantada. Pode terminar o processo para fazer um acesso de memória inválido (falha de segmentação, falha de proteção geral, ...). Esta é também a maneira pela qual o swapping é implementado: o manipulador de exceções pode decidir buscar alguns dados do espaço de troca, atualizar o TLB de acordo e executar o acesso novamente.

Observe que a MMU fornece segurança porque o processo não pode alterar seu próprio TLB. Apenas o kernel do sistema operacional pode alterar os TLBs. O funcionamento das permissões de alteração do TLB está além do escopo desta resposta.

    
por 17.09.2010 / 23:37
6

1) Segfaults são detectados pela unidade de gerenciamento de memória. Quando você pede memória, o sistema operacional pede à Unidade de Gerenciamento de Memória para obter alguma do hardware. Tem de haver algo que controle todos os grandes blocos de memória que o sistema operacional lhe oferece. O SO tipo de mãos que sai para a MMU. Como ele conhece toda a memória que ele forneceu, ele também pode avisá-lo quando você tentar acessar um local de memória que você não obteve de alocações. O SO especificamente tem um evento para isso, a memória que você não possui. Eventualmente, o sistema operacional mata seu aplicativo, acionando um segfault ou o equivalente em outros sistemas operacionais.

Nem todos os sistemas operacionais têm essa proteção. O MacOS até 9 não tinha nada disso, embora a MMU tenha apoiado isso. Nem Win 3.1. O Win95 tinha alguma proteção, pois passou entre não ter proteção e depois adicionar alguns.

2) O SO não conhece nenhum outro detalhe além disso. Se você tem um ponteiro que acessa a memória que você nunca alocou, ele sabe. Se você tiver uma que vá para outra parte do seu aplicativo, ela não sabe, é claro. Ele permite que você corrompa isso. É aqui que você obtém pilhas corrompidas, com ponteiros perdidos do seu aplicativo substituindo outras partes do aplicativo.

Então, sim, você pode estragar seus próprios dados. Se você tiver um ponteiro perdido que sobrescreva seu próprio aplicativo, espere que você acerte sua pilha, já que isso provavelmente causará outra violação quando você tentar devolver a pilha, mas se você acertar seus próprios dados, você nunca saberá.

Você pode tentar ser mais rigoroso do que 'sem proteção', há uma ferramenta chamada Electric Fence ( link ) que será engane sua MMU para trabalhar um pouco mais e faça com que ela detecte mais falhas.

    
por 17.09.2010 / 22:43