Можно ли считывать память из другой программы, выделяя все пустое пространство в системе?

26

Теоретически, если бы я создал программу, которая бы выделяла всю неиспользуемую память в системе и продолжала запрашивать все больше и больше памяти, поскольку другие приложения освобождали память, которая им больше не нужна, было бы возможно читать недавно освобожденную память из других приложений ? Или это как-то защищено современной операционной системой?

У меня нет практического применения для этого, мне просто любопытно. Я понимаю, что есть некоторые проблемы с распределением «всей доступной памяти» в реальной жизни.

Изменить: чтобы уточнить, я спрашиваю конкретно о «освобожденной» памяти, не обращаясь к памяти, которая в настоящее время выделена другим приложением.

ConditionRacer
источник

Ответы:

23

Нет, потому что хорошее ядро ​​стирает содержимое памяти перед тем, как оно будет передано процессу, для защиты от именно той атаки, которую вы предлагаете.

В системах Unixy память распределяется между процессами путем расширения так называемого прерывания программы , которое является пределом виртуально адресуемой области, которую может использовать процесс. Процесс сообщает ядру, что он хочет расширить свое адресуемое пространство, и ядро ​​разрешит это, если будет доступна память, или если вызов не удастся. (Название brk()системного вызова происходит от этой концепции.)

На практике большие блоки освобожденной памяти не часто сталкиваются с разрывом программы, что и требуется процессу для возврата памяти в ядро ​​путем сокращения разрыва программы. Это, конечно, все зависит от реализации вашей системы malloc()и free(). Если у вас есть доступные источники, они сообщат вам, была ли когда-либо возвращена память.

Нет никаких последствий для безопасности для того, чтобы malloc()не инициализировать память, потому что все, что она получила, brk()будет очищено, а все, что ранее free()было записано d, будет записано тем же процессом

Blrfl
источник
19

Да, теоретически возможно прочитать освобожденную память другого процесса. Это было источником ряда атак на повышение привилегий в тот же день. Из-за этого операционные системы в настоящее время эффективно обнуляют память, если она была ранее выделена другим процессом. Причина, по которой вы не всегда видите обнуленную память, состоит в том, что более эффективно не обнулять память, если она была ранее выделена тем же процессом. ОС пытается вернуть страницы памяти тому же процессу, если это возможно.

Карл Билефельдт
источник
1
«Да, но нет» - это «нет». @Blrfl это правильно.
Росс Паттерсон
4
@RossPatterson: С теоретической точки зрения Карл на самом деле более прав, чем я. Практическая реальность такова, что основные операционные системы закрыли эту дыру несколько лет назад.
Blrfl
@Blrfl Понял. Но «много лет назад» было в конце 1960-х, когда впервые появились системы подкачки и виртуальная память. Конечно, ко времени Multics, VM / 370 и OS / VS. Отсутствие ошибок, это не было возможно в памяти большинства практикующих программистов.
Росс Паттерсон
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 Я вижу некоторое несоответствие здесь. Вы имели в виду "тот же исполняемый файл"? Как проверяется, не обнулять ли - по пути к диску?
jakub.g
1
Я думаю, что что-то упустил. Почему тогда, когда я компилирую и запускаю некоторую программу на C ++, скажем, с неинициализированными целыми числами, они не равны 0, когда я читаю эти переменные?
jakub.g
2

Здесь есть несколько слоев, которые влияют на ответ.

Если вы предполагаете использовать современную операционную систему виртуальной памяти, вы не сможете увидеть остатки данных других процессов на страницах, которые вы выделяете.

Когда процесс загружается впервые, таблица страниц загружается, и потенциально страницы этой памяти выделяются кадры. Как минимум, таблица страниц или ее дополнительная таблица будет содержать карту всей памяти, которую может выделить процесс. Здесь также устанавливается начальный останов процесса, упомянутый выше.

Хотя malloc () может, если процесс разрешен, изменить прерывание процесса, добавив больше страниц в таблицу страниц процесса (дополнительную страницу) для удовлетворения запроса, место, где один процесс может «получить другой» данные процесса, находится в нижний слой реальной памяти.

В обоих этих сценариях современная операционная система, использующая разбиение на страницы по требованию или отложенное распределение, еще не выделяет физическую память (кадры). Операционная система просто «делает заметки» о том, какая виртуальная память для этого процесса считается допустимой. Фактическая память назначается только при необходимости.

Физическая память или кадры выделяются процессу, когда виртуальная страница реализована и отображается в таблицу страниц процессов. Здесь существует потенциальная возможность раскрытия данных. Это происходит во время ошибки страницы. Это связано с тем, что предыдущий процесс мог использовать этот же кадр, а его данные были либо заброшены, либо заменены, чтобы освободить место для текущего запроса физической памяти. Операционная система должна быть осторожна, чтобы гарантировать, что данные запрашивающих процессов правильно заменены или кадр очищен (обнулен) перед возобновлением процесса. Это также упоминалось выше как «старая, но решенная» проблема.

Это делает его несколько неактуальным, если память других процессов была «освобождена» или нет. «Освободившаяся» память других процессов по-прежнему находится на страницах, назначенных этому процессу, и обычно не отображается, пока процесс не завершится, поскольку они просто будут выгружены, когда память будет заполнена или они будут выселены иным образом. malloc () и free () управляют виртуальной памятью, назначенной процессу на уровне (пользователя).

В вашем вопросе ваш процесс продолжает запрашивать все больше и больше памяти, теоретически вытесняя все другие процессы из памяти. В действительности, существуют стратегии распределения кадров - глобальные и локальные - которые также могут повлиять на ответ. С большой вероятностью процесс вытеснит свои собственные страницы из памяти, прежде чем ему будет разрешено переполнение операционной системы и всех других процессов. Хотя это выходит за рамки вашего первоначального вопроса.

Все это спорный вопрос в такой системе MS-DOS. MS-DOS (и другие, более простые системы) не используют виртуальную память (сами по себе), и вы можете легко тыкать и подталкивать другие «обрабатывающие» данные.

Некоторые хорошие ссылки, которые, возможно, будет легче понять, чем исходный код Linux, могут быть хорошим учебником по операционным системам, «Концепции операционных систем» Silberscatz, Gavin и Gange или «Дизайн операционных систем» Эндрю Таненбаума. Кроме того, что-то вроде Nachos из Беркли или Pintos из Stanford - это небольшие операционные системы, созданные для обучения, и в них заложены те же идеи.

0xACE
источник
0

Я попробовал это на Ubuntu 16.04 месяцев назад. Как и сказал 0xACE, современная ОС выделяет виртуальную страницу с нулем, когда вы вызываете malloc (). Но если вы ничего не записываете в выделенный буфер, он не будет отображаться в физическую память (то есть принцип копирования при записи), поэтому вы всегда будете читать нули из «неинициализированного» блока. Может быть, есть некоторые встроенные ОС, скомпилированные с опцией «CONFIG_MMAP_ALLOW_UNITIALIZED» для повышения производительности, в этом случае вы можете получить то, за что вы заплатили.

weir007
источник
-1

Нет, это не позволит другой программе читать чужую память благодаря магии подкачки . Таким образом, общее использование памяти может превысить физический объем памяти путем разгрузки ее частей на жесткий диск.

Кроме того, максимальная память, которую может выделить процесс, произвольно ограничена ОС (до 4 гигабайт для 32-битной архитектуры), после чего следующий allocвызов вернет ошибку нехватки памяти.

чокнутый урод
источник
Разве нет платформо-зависимых API, которые могли бы обойти это? Честно говоря, я не знаю, но я не удивлюсь (например, Linux позволяет запретить ОС перемещать страницу из физической памяти через mlock).
Если имеется 4 ГБ ОЗУ, а подкачка ограничена 8 ГБ, что делать, если приложение запрашивает 12 ГБ (на x64)?
Арсений Мурзенко
тогда системные вызовы должны возвращать ошибку, когда останется слишком мало свободной памяти, или компьютер просто остановится, когда не останется ничего ...
ratchet freak
4
Он не спрашивает о чтении чужой памяти, а скорее читает их освобожденную память. Этот раздел оперативной памяти в настоящее время свободен, и ... я не думаю ... что схемы подкачки обнуляют память после освобождения. Таким образом, программа выделяет блок памяти и анализирует уже неинициализированные данные.
Филипп
@ philip правильно, я спрашиваю конкретно об освобожденной памяти.
ConditionRacer