Личный блог Suvan`a.

Работая и играя с Linux... И что из этого иногда получается.

Проверка границ.

Рубрика: Безопасность -> Укрепляем Linux
Метки:
Понедельник, 1 июня 2009 г.
Просмотров: 4601

Проверка границ - это процесс проверки индекса массива: выходит ли ин­декс за пределы допустимого диапазона или нет. Например, массив может содержать всего десять значений - с номерами от 0 до 9, а индекс может быть равен 10 - тогда он выходит за пределы диапазона. Проверка границ позволяет определить возможные попытки переполнения буфера.


     Проверка границ Джонс/Келли (Jones/Kelly).

     Первую работу в этой области опубликовали Ричард Джонс и Пол Келли в 1995 г. Предыдущие попытки реализовать проверку границ требовали из­менения внутреннего представления указателей (можно было два указате­ля, указывающих на начало и на конец объекта (массива)), но это вызвало очень много несовместимостей и неудобств: надо было перекомпилировать каждую используемую программой библиотеку.

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

     Этот метод может предотвратить все атаки переполнения буфера, но отрицательно влияет на производительность - в зависимости от приложе­ния производительность может уменьшиться более чем в 30 раз. Конечно, это самый плохой случай, в общем же производительность падает в 10 раз.

     CRED.

     Самый большой недостаток метода Джонса-Келли не в том, что страдает производительность, а его несовместимость с некоторыми приложениями. Джонс и Келли предположили, что любой выход указателя за пределы границ представляется ошибкой, но это не совсем так: возможно, кто-то временно направил указатель на значение, выходящее за пределы границ, но после­дующее выражение перенаправит указатель обратно в заданную область (массив). Тесты дали результат, что около 60% программ не работают с методом проверки границ Джонса-Келли.

     Окрыленные методом Джонса-Келли, Олатуний Рувас и Моника Лам (Стенфордский университет) показали свою реализацию метода про­верки границ - CRED (С Range Error Detector). Этот метод разрешает выход за пределы диапазона, только если это не результат переполнения буфера. CRED решает проблему несовместимости исходного метода про­верки границ.

     Для этого применяются специальные объекты ООВ (out-of-bounds), построенные для каждого выходящего за пределы диапазона указателя, а зна­чение указателя теперь устанавливается на адрес данного объекта. Объект содержит два значения: исходный адрес (выходящий за пределы границ) и объект, к которому относится этот адрес. CRED использует ООВ для определения объекта, на который должен ссылаться указатель, и показывает ошибку в случае, если указатель не указывает на этот объект.

Так как метод CRED защищает только от переполнения буфера, это дает возможность во много раз поднять производительность (по сравнению с ме­тодом Джонса/Келли). Метод CRED снижает производительность от 24% до 130%, в то время как метод Джонса-Келли снижает ее на 1000% (в самом худшем случае).

     Проверка границ методом CRED реализована в виде GCC-патча, который можно загрузить здесь: http://web.inter.nl.net/hcc/Haj.Ten.Brugge/. Установка данного патча похожа на установку SPP, поэтому не будем ее описывать. Для включения проверки границ можно передать компилятору опцию -fbounds-checking. Рассмотрим проверку границ на примере небольшой программы:

/* bounds-example.с */

Main () {

char *malloc(); char *a = malloc(2);

а[2]='х';

}

$ дсс -fbounds-checking bounds-example -о bounds-example

$ ./bound-example

Bounds Checking GCC v gcc-3.4.1-3.2 Copyright©!.995 Richard W.M. Jones

Bounds Checking comes with ABSOLUTELY NO WARRANTY. For details see

file

'COPYING' that should have come with the source to this program.

Bounds Checking is free software, and you are welcome to

distribute it under

certain conditions. See the file 'COPYING' for details.

For more information, set GCC_BOUNDS_OPTS to '-help'

bounds.example.с:4: Pointer calue: 0x806c002, Size: 1

bounds.example.с:4: Object 'malloc':

bounds . example . с : 4 : Address in memory: 0x806c000 .. 0x806c001

bounds.example.с:4: Size: 2 bytes

bounds.example.с:4 : Element size: 1 bytes

bounds.example.с:4: Number of.elements: 2

bounds.example.с : 4 : Created at: example.c, line 2

bounds.example.с:4: Storage class: heap

     При компиляции ошибок не будет, зато выполнение процесса будет прервано.