2013-03-19 4 views
15

Действительно ли gcc делает выделение памяти интеллектуально, чтобы предотвратить переполнение буфера?проблема выделения памяти gcc - атака переполнения буфера

int function(char *str) { 
    int a = 0;     // See the 
    char b[16] = "abcd";  // changes here 

    if(!strcmp(b, str)) 
     a = 1; 

    return a; 
} 

и

int function(char *str) { 
    char b[16] = "abcd";  // See the 
    int a = 0;     // changes here 

    if(!strcmp(b, str)) 
     a = 1; 

    return a; 
} 

Когда я отлаживать его с помощью GDB, он всегда выделяет память сначала целочисленных переменных, а затем массив символов; независимо от того, что является порядком объявления переменной. т. Е. В обоих случаях компилятор сначала выделяет память a, а затем - b.

(higher address) 
    Memory 
|  | 
|  | 
+--------+ 
|  | 
|  | 
|  | 
|  | 
+--------+ <----- b (16 bytes) 
|  | 
+--------+ <----- a (4 bytes) 
|  | 
(lower address) 

Таким образом, даже если мы поставляем более 16 символов в str, он не может повлиять на значение a. Может ли кто-нибудь помочь мне здесь?

спасибо.

+1

_The Standard_ допускает такое переупорядочение для любых целей, которые компилятор хочет выполнить. Наиболее распространенная - оптимизация. Это по-прежнему «интеллект», но не для предотвращения «атаки переполнения буфера». И это все еще неопределенное поведение_ (переполнение буфера) –

ответ

11

Да, если вы используете флаг -fstack-protector.

При запуске с флагом GCC добавляет стекалки канарейки, сортирует переменные массива в самой высокой части фрейма стека, чтобы затруднить их переполнение и повреждение других переменных, а также копирование аргументов функции, которые будут храниться с другие местные жители.

См Wikipedia page on Buffer overflow protection и ProPolice домашней страница для получения дополнительной информации

+0

@Ravi: некоторые дистрибутивы по умолчанию используют его. Попробуйте выполнить компиляцию с '-fno-stack-protector' и посмотрите, не изменилось ли это. – Hasturkun

+0

@MM .: Добавлено. Был в основном опущен для краткости. – Hasturkun

+1

Вы правы. GCC разрешает его по умолчанию. Если мы скомпилируем с '-fno-stack-protector', он выделяет память последовательно в порядке объявления, а не _array-переменных, в самую большую часть фрейма стека. спасибо – Ravi

-1

Содержит ли gcc интеллектуальное распределение памяти, чтобы предотвратить переполнение буфера?

Нет, это не так. Вы не можете предотвратить атаку или переполнение буфера без проверки границ, что не всегда возможно. Вы можете только иногда обнаруживать переполнение после факта.

В лучшем случае компилятор может включать дополнительную информацию (так называемый canary value) рядом с адресом возврата в стеке и перед возвратом из функции проверить, что она не повреждена и не перезаписана в результате переполнения буфера.

+2

Это неправильно, GCC может и переупорядочивает переменные, чтобы предотвратить эффекты переполнения буфера – Hasturkun

+0

@Hasturkun Вы не можете предотвратить переполнение без проверки границ. Вы можете только иногда их обнаружить. –

+0

Это правда. Но вы можете смягчить их, как это сделано ProPolice и т. Д. – Hasturkun

2

Даже если GCC имеет такую ​​функцию защиты от переполнения буфера, есть много других факторов, которые здесь может привести к фиксированному переменному порядку декларирования. Если объявление сделано не очень важно, компилятор принимает решения о распределении, основанные на том, когда и как переменная используется во время выполнения.

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

Итак, чтобы ответить на ваш вопрос: GCC выделяет переменные различными способами, в зависимости от порта компилятора. Как это происходит, это не то, о чем программист должен слишком беспокоиться. Могут быть варианты переупорядочения стека для защиты от атак переполнения буфера, но это имеет смысл только в некоторых типах приложений. Возможно, даже не будет никакого вклада в какую-то конкретную систему, поскольку мы все знаем. Поэтому для компилятора не имеет смысла включать эту функцию безопасности по умолчанию.

Смежные вопросы