mprotect в linux - PullRequest
       83

mprotect в linux

1 голос
/ 14 февраля 2012

Если я mprotect сегмент с PROT_NONE и если SIGSEGV происходит из-за записи, которая обрабатывается sigaction с sa_sigaction, мы сможем найти адрес, где происходит ошибка, используя siginfo_t х si_addr. Но есть ли способ найти данные и длину данных, которые пытались записать?

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

Ответы [ 3 ]

2 голосов
/ 14 февраля 2012

Ядро не знает, поэтому оно не может сказать вам.Но вы можете попытаться выяснить, хотите ли вы.У вас есть кодовый адрес, который вышел из строя в стеке, так что вы можете разобрать код там, чтобы попытаться выяснить это.Нет другого способа узнать (подумайте об этом, если вам не понятно почему).Инструкция не сработала, потому что она коснулась защищенной страницы, это все, что известно, если только вы не проанализируете код сборки.

Если вы не можете сказать, с каким объектом вы имеете дело, зная только страницу, на которой произошла ошибка, я 'Настоятельно рекомендую вам пересмотреть вопрос об изменении вашего дизайна.(posix_memalign, возможно?)

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

  1. Контекст A обращается к странице Q с семантикой CoW.Контекст A получает доступ только для чтения к странице.

  2. Контекст B обращается к странице Q с семантикой CoW.Контекст B получает доступ только для чтения к странице.

  3. Контекст A идет для изменения страницы, мы делаем копию для контекста B. Контекст A теперь имеет доступ для записи к странице и изменяет ее.it.

  4. Мы переключаемся из контекста A в контекст B. На этом этапе вы должны переключить копию страницы, которую вы сделали для контекста B.

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

2 голосов
/ 14 февраля 2012

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

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

  • Отслеживание состояния страницы
  • Увеличение разрешений по мере необходимости
1 голос
/ 30 октября 2013

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

Как только вы защитите свой сегмент памяти, если вы получите к нему доступ таким образом, который нарушает защиту, вы получите сигнал SIGSEGV.В обработчике сигнала вы получите указатель на siginfo_t.Это дает вам необходимую информацию.si_addr дает вам адрес инструкции, вызвавшей незаконный доступ, а si_ptr дает вам адрес, к которому был получен незаконный доступ.Затем вы сравниваете si_ptr с сегментами памяти, которые вы защищаете, пока не найдете тот, к которому он принадлежит, и вам нужно скопировать его для «копирования при записи» ... как только вы это сделаете, вам нужно будет вызватьчто-то вроде setcontext () или siglongjmp () для продолжения работы с известного места.

Надеюсь, это поможет.

...