Защитите все адресное пространство с помощью mprotect

Для моего университетского проекта мне нужно ЗАПИСАТЬ защитить все адресное пространство процесса. Я читал файл /proc/self/maps и анализировал сопоставление.

Итак, для каждой записи в формате 08048000-0804c000 r-xp 00000000 08:03 7971106 /bin/cat я читаю первые две записи (здесь 08048000 & 0804c000), преобразовывая их в десятичные числа. Предположим, что десятичный эквивалент равен A и B соответственно. Затем я делаю mprotect((int*)A, B-A, PROT_READ). Но этот подход дает мне ошибку сегментации. Я не могу понять, что я сделал неправильно здесь. Может быть, у меня есть пробел в знаниях, который вызывает проблему. Кто-то может дать мне несколько предложений?


person azizulhakim    schedule 28.11.2013    source источник


Ответы (1)


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

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

Скорее всего, это произойдет, когда вы вернетесь из mprotect() после «защиты» стека.

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

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

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

person Kristof Provost    schedule 28.11.2013
comment
Спасибо за ответ. Да, вы правы по своим пунктам. Но на самом деле внутри обработчика mprotect() я снимаю защиту с адресуемой области памяти, повторно выполняю инструкцию доступа к памяти, а затем снова применяю защиту. На самом деле цель проекта — отслеживать изменения в адресном пространстве, чтобы я мог вернуться к какому-то предыдущему состоянию приложения. Таким образом, техника должна была работать без каких-либо ошибок сегментации. Вы так не думаете? - person azizulhakim; 28.11.2013
comment
Если я вас правильно понимаю, и вы пытаетесь обработать ошибку доступа к памяти внутри обработчика сигнала SIGSEGV (mprotect() не имеет обратного вызова), вы все еще сталкиваетесь с той же проблемой. Вы получите вторую ошибку сегментации, просто пытаясь настроить стек для обработчика сигнала или, по крайней мере, при вызове mprotect() во второй раз. Я не думаю, что есть какой-либо способ сделать это, не сохраняя хотя бы часть памяти доступной для записи. - person Kristof Provost; 28.11.2013
comment
Есть ли другая простая альтернатива решению проблемы, с которой мы столкнулись? - person azizulhakim; 29.11.2013
comment
Я бы посмотрел на ptrace(). Это то, что использует gdb. Вы также можете попробовать взглянуть на Valgrind, поскольку он решает аналогичную проблему. - person Kristof Provost; 29.11.2013
comment
Значит ли это, что мы не можем защитить весь адрес с помощью mprotect? Если это так, то какую часть мы можем защитить без каких-либо проблем? - person azizulhakim; 02.12.2013
comment
Я бы начал с попытки защитить все, кроме стека. Этот должен оставаться для чтения/записи. Также не забудьте сохранить разрешение на выполнение для всего, что в настоящее время имеет его. - person Kristof Provost; 02.12.2013
comment
Открой gdb и посмотри на дамп памяти. Посмотрите, где он падает. Тогда вы будете знать, что он пытается прочитать/записать/выполнить. - person Kristof Provost; 06.12.2013