É possível ler a memória de outro programa alocando todo o espaço vazio em um sistema?

26

Teoricamente, se eu construísse um programa que alocasse toda a memória não utilizada em um sistema e continuasse a solicitar mais e mais memória à medida que outros aplicativos liberassem a memória que não precisam mais, seria possível ler a memória liberada recentemente de outros aplicativos ? Ou isso é de alguma forma protegido pelo sistema operacional moderno?

Não tenho aplicação prática para isso, estou apenas curioso. Sei que há alguns problemas com a alocação de "toda a memória disponível" na vida real.

Editar: para esclarecer, estou perguntando especificamente sobre a memória "Liberada", não acessando a memória atualmente alocada por outro aplicativo.

ConditionRacer
fonte

Respostas:

23

Não, porque um bom kernel limpa o conteúdo da memória antes de ser emitido para um processo para proteger exatamente contra o tipo de ataque que você propõe.

Nos sistemas Unixy, a memória é alocada aos processos estendendo o que é chamado de quebra de programa , que é o limite de espaço praticamente endereçável que um processo pode usar. Um processo diz ao kernel que deseja estender seu espaço endereçável, e o kernel permitirá se houver memória disponível ou se a chamada falhar. (O nome da brk()chamada do sistema vem desse conceito.)

Na prática, grandes blocos de memória liberada não costumam se deparar com a interrupção do programa, o que seria necessário para que um processo retornasse memória ao kernel diminuindo a interrupção do programa. Obviamente, isso depende da implementação malloc()e do sistema do seu sistema free(). Se você tiver fontes disponíveis, eles dirão se a memória é ou não retornada.

Não há implicações de segurança para malloc()não inicializar a memória, porque qualquer coisa obtida brk()foi removida e qualquer coisa anteriormente free()d foi gravada pelo mesmo processo.

Blrfl
fonte
19

Sim, teoricamente é possível ler a memória liberada de outro processo. Foi a fonte de vários ataques de escalonamento de privilégios no passado. Por isso, hoje em dia, os sistemas operacionais efetivamente zeram a memória se ela foi alocada anteriormente por outro processo. O motivo pelo qual você nem sempre vê a memória zerada é porque é mais eficiente não zerar a memória se ela foi alocada anteriormente pelo mesmo processo. O sistema operacional tenta devolver as páginas de memória para o mesmo processo, se puder.

Karl Bielefeldt
fonte
1
"Sim, mas não" é "não". @Blrfl está certo.
Ross Patterson
4
@ RossPatterson: No ponto teórico, Karl está realmente mais certo do que eu. A realidade prática é que os sistemas operacionais tradicionais fecharam esse buraco anos atrás.
Blrfl
@Blrfl Entendido. Mas "anos atrás" foi no final dos anos 1960, quando os sistemas de paginação e memória virtual foram introduzidos pela primeira vez. Certamente na época do Multics, VM / 370 e OS / VS. Erros ausentes, isso não foi possível na memória da maioria dos programadores praticantes.
Ross Patterson
The reason you don't always see zeroed out memory is because it is more efficient not to zero out the memory if it was previously allocated by the same process Eu vejo alguma inconsistência aqui. Você quis dizer "mesmo executável"? Como é verificado se não deve zerar - pelo caminho do disco?
jakub.g
1
Eu acho que estou perdendo alguma coisa. Por que, então, quando compilo e executo algum programa C ++ com, digamos, números inteiros não inicializados, eles não são iguais a 0 quando leio essas variáveis?
jakub.g
2

Existem várias camadas envolvidas aqui que afetam a resposta.

Se você assumir um sistema operacional moderno de memória virtual, não poderá ver os restos de outros dados de processos nas páginas alocadas.

Quando um processo é carregado pela primeira vez, a tabela de páginas é carregada e, potencialmente, quadros de memória real são alocados para essas páginas. No mínimo, a tabela de páginas ou sua tabela suplementar conterá um mapa de toda a memória que o processo pode alocar. É também aqui que a quebra do processo inicial, mencionada acima, é definida.

Embora malloc () possa, se o processo for permitido, fazer com que a interrupção do processo mude, adicionando mais páginas a uma tabela de página de processos (página suplementar) para atender à solicitação, o local em que um processo pode "obter outro" dados de processo está em a camada inferior de memória real.

Em ambos os cenários, um sistema operacional moderno que usa paginação por demanda ou alocação lenta, ainda não está alocando memória física (quadros). O sistema operacional está apenas "fazendo anotações" sobre qual memória virtual para esse processo é considerada válida. A memória real é atribuída apenas quando necessário.

Memória física ou quadros são alocados a um processo quando a página virtual é realizada e mapeada em uma tabela de páginas de processos É aqui que existe o potencial de exposição de dados. Isso acontece durante uma falha de página. A exposição ocorre porque um processo anterior pode estar usando o mesmo quadro e seus dados foram abandonados ou trocados, para liberar espaço para a solicitação de memória física atual. O sistema operacional deve ter cuidado para garantir que os dados do processo solicitante sejam trocados corretamente ou que o quadro seja limpo (zerado) antes de continuar o processo. Isso também é mencionado acima como um problema "antigo, mas resolvido".

Isso torna um pouco irrelevante se a memória de outros processos foi "liberada" ou não. Outros processos "liberados" de memória ainda residem nas páginas atribuídas a esse processo e geralmente não são mapeados até o processo terminar, pois eles serão trocados apenas quando a memória ficar baixa ou caso contrário eles serão despejados. malloc () e free () gerenciam a memória virtual atribuída ao processo no nível (usuário).

Na sua pergunta, seu processo continua solicitando mais e mais memória, em teoria, empurrando todos os outros processos para fora da memória. Na realidade, existem estratégias de alocação de quadros - global e local - que também podem afetar a resposta. É provável que o processo force a falta de memória de suas próprias páginas antes de poder exceder o sistema operacional e todos os outros processos. Embora isso vá além da sua pergunta inicial.

Tudo isso é discutível em um sistema como o MS-DOS. O MS-DOS (e outros sistemas mais simples) não usa memória virtual (por si só) e você pode facilmente cutucar e cutucar outros dados de "processos".

Algumas boas referências, que podem ser mais fáceis de entender do que o código-fonte do Linux, seriam um bom livro de sistemas operacionais, Conceitos de Sistemas Operacionais por Silberscatz, Gavin e Gange ou Design de Sistemas Operacionais por Andrew Tanenbaum. Além disso, algo como Nachos de Berkeley ou Pintos de Stanford são pequenos sistemas operacionais criados para o aprendizado e têm essas mesmas idéias.

0xACE
fonte
0

Eu tentei isso no Ubuntu há 16.04 meses. Assim como o 0xACE disse, o SO moderno aloca uma página virtual zero quando você chama malloc (). Porém, se você não gravar nada no buffer alocado, ele não será mapeado na memória física (ou seja, princípio de cópia na gravação), portanto, você sempre lerá zeros de um bloco "não inicializado". Talvez haja algum SO incorporado compilado com a opção "CONFIG_MMAP_ALLOW_UNITIALIZED" para obter melhor desempenho. Nesse caso, você pode obter o que deseja.

weir007
fonte
-1

Não, isso não permitirá que outro programa leia a memória de outros graças à magia da paginação . Dessa forma, o uso total de memória pode exceder a memória RAM descarregando partes dela para o disco rígido.

Além disso, a memória máxima que um processo pode alocar é arbitrariamente limitada pelo sistema operacional (até 4 GB para uma arquitetura de 32 bits), após o qual a próxima allocchamada retornará um erro de falta de memória.

catraca arrepiante
fonte
Não existem APIs específicas da plataforma que possam contornar isso? Sinceramente, não sei, mas não ficaria surpreso (por exemplo, o Linux permite impedir que o SO mova uma página da memória física, via mlock).
Se houver 4 GB de RAM e a paginação estiver limitada a 8 GB, e se o aplicativo solicitar 12 GB (em um x64)?
Arseni Mourzenko
em seguida, as chamadas de sistema deve retornar um erro quando a memória muito pouco livre permanecerá, que ou o computador simplesmente moer a um impasse quando não há qualquer esquerda ...
aberração catraca
4
Ele não está perguntando sobre a leitura da memória de outra pessoa, mas a leitura da memória LIBERADA. Essa seção do ram está atualmente livre e ... eu não acho ... que os esquemas de paginação zerem a memória depois que ela for liberada. Portanto, o programa alocaria um bloco de memória e analisaria os dados não inicializados que já estão lá.
Philip
@ philip correto, estou perguntando especificamente sobre a memória liberada.
ConditionRacer