Есть ли способ превентивно избежать сегментации? - PullRequest
3 голосов
/ 28 ноября 2010

Вот ситуация:

Я анализирую взаимодействие программ с драйвером с помощью модуля LD_PRELOAD, который перехватывает системный вызов ioctl (). Система, с которой я работаю (встроенное ядро ​​Linux 2.6.18), к счастью, имеет длину данных, закодированных в параметре 'request', поэтому я могу с радостью вывести данные ioctl правильной длины.

Однако довольно много этих данных имеют указатели на другие структуры, и я не знаю их длины (это то, что я исследую, в конце концов). Поэтому я сканирую данные на предмет указателей и сбрасываю данные в этой позиции. Я боюсь, что это может оставить мой код открытым для segfaults, если указатель находится близко к границе сегмента (и мое раннее тестирование, кажется, показывает, что это так).

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

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

Ответы [ 4 ]

3 голосов
/ 28 ноября 2010

Откройте дескриптор файла для /dev/null и попробуйте write(null_fd, ptr, size). Если он возвращает -1 с errno, установленным на EFAULT, память недействительна. Если он возвращает size, память безопасна для чтения. Может быть более элегантный способ запрашивать достоверность / разрешения памяти с некоторым изобретением POSIX, но это классический простой способ.

1 голос
/ 28 ноября 2010

Если во встроенном linux установлена ​​/ proc / filesystem, вы можете проанализировать файл / proc / self / maps и проверить указатель / смещения по этому.Файл карт содержит отображения памяти процесса, см. здесь

0 голосов
/ 28 ноября 2010

Разве вы не можете просто проверить границы сегмента?(Я предполагаю, что под границами сегментов вы подразумеваете границы страниц?)

Если да, то границы страниц хорошо разграничены (4 КБ или 8 КБ), поэтому простое маскирование адреса должно с этим справиться.

0 голосов
/ 28 ноября 2010

Я не знаю такой возможности. Но вы можете достичь чего-то подобного. Как упоминает man 7 signal, можно поймать SIGSEGV. Таким образом, я думаю, что вы могли бы

  1. Начать с разыменования байтовой последовательности, известной как указатель
  2. Доступ к одному байту за другим, в какое-то время срабатывает SIGSEGV
  3. В обработчике SIGSEGV отметьте переменную, которая проверяется в цикле шага 2
  4. Выйти из цикла, эта страница готова.

С этим связано несколько проблем.

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

Непроверенные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...