2010-08-09 2 views
5

Мне интересно, есть ли способ защитить каждую страницу в адресном пространстве процесса Linux (изнутри самого процесса, путем mprotect()). Под «каждой страницей» я действительно имею в виду каждую страницу адресного пространства процесса , которое может быть записано обычной программой , работающей в пользовательском режиме, - поэтому текст программы, константы, , глобальные и кучи - - но я был бы доволен только константами, globals и кучей. Я не хочу писать-защищать стек - то, что кажется плохой идеей.Могу ли я защищать каждую страницу в адресном пространстве Linux-процесса?

Одна из проблем заключается в том, что я не знаю, с чего начать защиту от записи памяти. Рассматривая /proc/pid/maps, в котором показаны разделы памяти , используемые для данного pid, они всегда начинаются с адреса 0x08048000 с текстом программы. (В Linux, насколько я могу судить, память процесса выложена с текстом программы на дне , затем константами выше этого, затем глобальными, затем кучей, затем пустым пространством разного размера в зависимости от на размер кучи или стек , а затем стек, растущий с верхней части памяти на виртуальный адрес 0xffffffff.) Можно указать, где находится вершина (куча sbrk(0), которая просто возвращает указатель на текущий «перерыв», т. е. верх кучи), но на самом деле не путь к , где начинается куча.

Если я попытаюсь защитить все страницы от 0x08048000 до перерыва, I в конечном итоге получит ошибку mprotect: Cannot allocate memory. Я не знаю, почему mprotect будет в любом случае распределять память - и Google не очень помогает. Есть идеи?

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

Спасибо!

+1

У меня на самом деле уже есть код, который делает именно то, что вы пытаетесь сделать. Ваша идея будет работать, но вы не сможете защитить страницы, на которых будут находиться ваши «эти-страницы-написанные» списки, или ваш обработчик SEGV вызовет SEGV! – Borealid

+0

@Borealid, спасибо, и теперь проблема, которую я пытаюсь решить (теперь у меня обработчик segfault и обработчик/proc/self/maps). Как избежать защиты страниц, содержащих этот список? Выделение списка в стеке будет работать, но тогда я не вижу способа передать его обработчику. В качестве альтернативы я мог бы выделить его как глобальный, но я бы хотел использовать более удобную структуру данных, чем массив фиксированной длины (например, контейнер STL), и я не всегда мог бы знать, где находится список, который я пишу в памяти. –

+0

@borealid: Вы сказали, что у вас есть код, который делает именно это - не могли бы вы поделиться своим кодом? Я новичок здесь, и я не мог найти способ напрямую связаться с вами (обратным каналом). Я пытаюсь сделать именно то, что делает Линси, поэтому любые примеры кода были бы очень полезными. –

ответ

5

Вы получаете ENOMEM от mprotect(), если попытаетесь называть его на страницах, которые не отображаются.

Ваш лучший выбор - открыть /proc/self/maps и прочитать его по одной строке за один раз с fgets(), чтобы найти все сопоставления в вашем процессе.Для каждого записываемого отображения (указанного во втором поле), которое не является стеком (указано в последнем поле), вызовите mprotect() с правильным базовым адресом и длиной (рассчитанной с начального и конечного адресов в первом поле).

Обратите внимание, что в этот момент вам необходимо настроить обработчик ошибок, так как действие чтения файла maps, скорее всего, вызовет записи в вашем адресном пространстве.

+0

Спасибо - я надеялся, что будет некоторая дорога, связанная с необходимостью ручного анализа/proc/self/maps, но кажется, что нет (из обсуждения на http://stackoverflow.com/questions/269314/есть-есть-а-лучше-полосные, чем при разборе-Proc нормальновсасывающих карты к фигуре-из памяти Protectio). –

0

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

+0

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

+0

На самом деле я пытался сказать, что ваши секторы кода, скорее всего, уже защищены от записи. –

Смежные вопросы