Есть ли лучший способ, чем синтаксический анализ /proc/self / maps, чтобы определить защиту памяти?
-
06-07-2019 - |
Вопрос
В Linux (или Solaris) есть ли способ лучше, чем ручной синтаксический анализ /proc/self/maps
повторно, чтобы выяснить, можете ли вы прочитать, записать или выполнить все, что хранится по одному или нескольким адресам в памяти?
Например, в Windows у вас есть VirtualQuery
.
В Linux я могу mprotect
чтобы изменить эти значения, но я не могу прочитать их обратно.
Кроме того, есть ли какой-либо способ узнать, когда эти разрешения изменяются (напримеркогда кто-то использует mmap
в файле за моей спиной), кроме как делать что-то ужасно агрессивное и использовать ptrace
во всех потоках процесса и перехватывая любую попытку создать syscall
это может повлиять на карту памяти?
Обновить:
К сожалению, я использую это внутри JIT, у которого очень мало информации о коде, который он выполняет, чтобы получить приблизительное представление о том, что является постоянным.Да, я понимаю, что у меня могла бы быть постоянная карта изменяемых данных, например, страница vsyscall, используемая Linux.Я может смело возвращайтесь к предположению, что все, что не включено в начальный синтаксический анализ, изменчиво и опасно, но я не совсем доволен этим вариантом.
Прямо сейчас, что я делаю, так это читаю /proc/self/maps
и постройте структуру, по которой я могу выполнять бинарный поиск для защиты данного адреса.Каждый раз, когда мне нужно узнать что-то о странице, которой нет в моей структуре, я перечитываю /proc/self/maps, предполагая, что она была добавлена за это время, иначе я все равно собирался бы выполнить сегментацию.
Просто кажется, что разбирать текст, чтобы получить эту информацию, и не знать, когда она изменится, ужасно грубо.(/dev/inotify
не работает практически ни с чем в /proc
)
Решение
Я не знаю эквивалента VirtualQuery
в Linux.Но есть некоторые другие способы сделать это, которые могут сработать, а могут и не сработать:
вы настраиваете обработчик сигналов, перехватывающий SIGBUS / SIGSEGV, и продолжаете чтение или запись.Если память защищена, будет вызван ваш код перехвата сигнала.Если нет, то ваш код перехвата сигнала не вызывается.В любом случае вы выиграете.
вы могли бы отслеживать каждый свой звонок
mprotect
и создайте соответствующую структуру данных, которая поможет вам узнать, защищен ли регион от чтения или записи.Это хорошо, если у вас есть доступ ко всему коду, который используетmprotect
.вы можете отслеживать все
mprotect
вызывает ваш процесс, связывая ваш код с библиотекой, переопределяющей функциюmprotect
.Затем вы можете создать необходимую структуру данных, чтобы узнать, защищен ли регион от чтения или записи, а затем вызвать системуmprotect
для реальной установки защиты.вы можете попробовать использовать
/dev/inotify
и следите за файлом/proc/self/maps
для любых изменений.Я предполагаю, что это не сработает, но попробовать стоит.
Другие советы
Там вроде есть /was /proc/[pid|self] /pagemap, документация в ядре, предостережения здесь:https://lkml.org/lkml/2015/7/14/477 Так что это не совсем безобидно...