8.5.2 Устранение переполнений памяти |
Предыдущая Содержание Следующая |
Несмотря на простоту в использовании, язык Си является небезопасным языком, потому что он не предотвращает переполнения буфера. Многие функции в библиотеке Си описаны как небезопасные для использования (например, печально известная функция gets()), но это не мешает тому, чтобы небрежный программисту использовал такие функции и вызывал нарушения безопасности в системе. Ниже приведены некоторые примеры этого, которые возникают из-за такого небрежного программирования.
▪Изменение хода выполнения кода: переполнение буфера может изменить адрес возврата в стеке или произвольного указателя функции в памяти. ▪Перезапись переменной с данными: переменная, которая содержит какие-то секретные сведения, например, строку подключения к базе данных.
Если вы загрузили исходный код приложения из Сети, и хотели бы проверить его на ошибки переполнения, есть готовые инструменты, доступные для помощи вам. Инструментом, который был написан в основном для поиска переполнений буфера, является Electric Fence. Обратите внимание, что dmalloc также способен делать проверки на ошибки при вычислении смещения (обычно на плюс/минус единицу). Но метод, предоставляемый dmalloc, не совсем понятный, потому что это полностью реализован в программном обеспечении. Есть два недостатка схемы dmalloc:
▪dmalloc реализует проверку на ошибку вычисления смещения путём добавления в выделенную область магического числа и проверкой, что магическое число не перезаписано. Частота проверок контролируется с помощью параметра отладки inter. Эта схема может быть эффективной при поиске переполнения, но она может быть неэффективной для указывания на ошибочную инструкцию. ▪dmalloc может обнаружить только записи за границы буфера; однако, чтения за границами буфера по-прежнему остаются незамеченными.
Electric Fence позволяет использовать оборудование, чтобы точно выявить неправильную инструкцию, которая пытается читать и писать за границами буфера. Кроме того, он может быть использован для обнаружения любых ситуаций, когда программное обеспечение обращается к памяти, которая уже была освобождена. Electric Fence управляет этим путём выделения страницы (или набора страниц) для каждого запроса памяти, а затем делает страницы за пределами буфера недоступными для чтения или записи. Таким образом, если программное обеспечение пытается получить доступ к памяти за пределами этих границ, это приводит к ошибке сегментации. Аналогично, если память освобождается вызовом free(), она делается недоступной с помощью защиты виртуальной памяти и любой код, который затрагивает освобождённую память, получит ошибку сегментации. Electric Fence доступен как библиотека libefence.a; она должна быть скомпонована с приложением, которое должно быть отлажено на предмет переполнения буфера. Использование Electric Fence иллюстрирует Распечатка 8.7. Как видно в Распечатке 8.7, рекомендуемым способом запуска Electric Fence является запуск его из gdb, чтобы неправильная инструкция могла быть поймана с полной отладочной информацией. Этот пример показывает случай переполнения буфера. Electric Fence также может поймать обращения за нижней границей выделенной памяти, но для того, чтобы сделать это, до запуска приложения должна быть экспортирована переменная окружения EF_PROTECT_BELOW. Это необходимо, потому что по умолчанию Electric Fence ловит только переполнения буфера путем размещения памяти, недоступной для обращения, после конца каждого выделенного куска. Установка этой переменной гарантирует, что недоступная для обращения память размещается до начала выделенной памяти. Таким образом, чтобы убедиться, что приложение не имеет ни переполнений, ни обращений за нижнюю границу, это приложение должно быть вызвано дважды: один раз без установки переменной EF_PROTECT_BELOW и второй раз после её установки. Поскольку Electric Fence требует, чтобы при каждом выделении памяти выделялась по крайней мере одна страница памяти, это может потребовать весьма много памяти. Рекомендуется использовать Electric Fence только для отладки систем; при поставке систем он должен быть выключен.
|
Предыдущая Содержание Следующая |