Чтение онлайн

на главную - закладки

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

#include <alloca.h>

void * alloca(size_t size);

Подобно

malloc
,
alloca
выделяет область памяти длиной
size
байтов и возвращает указатель на начало этой области. Вместо использования памяти из программной кучи этот метод распределяет память из вершины стека, из того же места, где хранятся локальные переменные. Первое преимущество данной функции перед локальными переменными состоит в том, что необходимое количество байтов точно вычисляется в программе, а не определяется приблизительно. Превосходство над
malloc
заключается в том, что при завершении работы функции память освобождается автоматически. Все это позволяет охарактеризовать
alloca
как легкий способ распределения памяти, которая требуется только временно. До тех пор, пока размер буфера вычисляется должным образом (не забудьте учесть
'\0'
в конце каждой строки С!), можно не бояться переполнения буфера [161] .

161

Функция

alloca
не является стандартным средством языка С, однако компилятор gcc предоставляет
alloca
в большинстве поддерживаемых операционных систем. В более старых версиях gcc (до версии 3.3)
alloca
не всегда должным образом взаимодействовала с массивами динамических размеров (другое расширение GNU), поэтому примите во внимание, что использовать нужно только одну из версий.

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

strncpy
и
strncat
легко предотвращают перегрузки буфера при копировании строк.

#include <string.h>

char * strncpy (char * dest, const char * src, size_t max);

char * strncat (char * dest, const char * src, size_t max);

Обе функции ведут себя как их родственники, называемые аналогично,

strcpy
и
strcat
, но они возвращают за один раз только max байт, копируемые в строку назначения. Если достигнут предел, то результирующая строка не завершается
'\0'
, поэтому обычные строковые функции не смогут с ней работать. По этой причине необходимо явно завершить строку после вызова одной из подобных функций.

strncpy(dest, src, sizeof(dest));

dest[sizeof(dest) - 1] = '\0';

Частой ошибкой при использовании

strncat
является передача общего размера
dest
в качестве параметра
max
. Это приводит к потенциальному переполнению буфера, так как
strncat
добавляет до
max
байт в
dest
; она не прекращает копировать байты, когда общая длина
dest
достигает
max
байтов.

Несмотря на то что эти функции могут сделать выполнение программы некорректным при передаче длинных строк (из-за усечения этих строк), данный прием хорошо предотвращает перегрузки в буферах статических размеров. Во многих случаях это приемлемый компромисс (во всяком случае, при этом не произойдет ничего хуже того, что может случиться из-за переполнения буфера).

Функция

strncpy
решает проблему копирования строки в статический буфер без переполнения его. А функции
strdup
автоматически выделяют буфер, достаточный для хранения строки, до начала копирования в него исходной строки.

#include <string.h>

char * strdup(const char * src);

char * strdupa(const char * src);

char * strndup(const char * src, int max);

char * strndupa(const char * src, int max);

Первая из приведенных функций,

strdup
, копирует строку
src
в буфер, выделенный методом
malloc
, и возвращает буфер вызывающему оператору. Вторая функция,
strdupa
, выделяет буфер с помощью
alloca
. При этом обе функции выделяют буфер, в точности достаточный для хранения строки и замыкающего символа
'\0'
.

Остальные две функции,

strndup
и
strndupa
, копируют не более чем max байтов из
str
в буфер вместе с замыкающим
'\0'
(и выделяют не более чем
max
+1 байтов). При этом выделение буфера происходит при помощи метода
malloc
(для
strndup
) или
alloca
(для
strndupa
).

Функция

sprintf
также входит в число тех, которые часто вызывают переполнение буфера. Так же как
strcat
и
strcpy
, функция
sprintf
имеет разновидность, позволяющую облегчить защиту от перегрузок.

#include <stdio.h>

int snprintf(char * str, size_t max, char * format, ...);

Попытки определить размер буфера, необходимый для

sprintf
, могут
оказаться слишком сложными. Он зависит от таких элементов, как значения всех форматируемых чисел (для которых могут быть нужны или не нужны знаки чисел), используемые аргументы форматирования и длины всех строк, которые были затронуты форматированием. Для того чтобы избежать переполнения буфера, функция
snprintf
помещает в
str
не более чем max символов, включая замыкающий
'\0'
. В отличие от
strcat
и
strncat
, функция
snprintf
корректно завершает строку, при необходимости пренебрегая символом из форматируемой строки. Она возвращает количество символов, которые будет занимать конечная строка при наличии доступного пространства. Также сообщается, нужно ли усекать строку до
max
символов (не считая последний
'\0'
) [162] . Если возвращаемое значение меньше чем
max
, значит, функция успешно завершила свою работу. Если же равно или больше, значит, предел
max
превышен.

162

В некоторых устаревших версиях библиотеки С вместо этого возвращается -1 (если строка не помещается). Старая версия библиотеки С уже не поддерживается и не используется в защищенных программах, однако на man-странице по функции

snprintf
демонстрируется код, обрабатывающий оба варианта.

Функция

vsprintf
несет те же проблемы, a
vsnprintf
предлагает способ их преодоления.

22.3.2. Разбор имен файлов

Абсолютно обычным действием для привилегированных приложений является предоставление доступа к файлам ненадежным пользователям и разрешение этим пользователям передавать имена файлов, к которым необходим доступ. Хорошим примером служит Web-сервер. URL-адрес HTTP содержит имя файла, полученное сервером как запрос на передачу удаленному (ненадежному) пользователю. На Web-сервере необходимо убедиться, что возвращаемый файл — это именно тот, который был сконфигурирован на отправку, а также внимательно проверить правильность имен файлов.

Представьте Web-сервер, обслуживающий файлы из

home/httpd/html
, выполняющий это посредством простого добавления имени файла из URL, который требуется предоставить, концу
/home/httpd/html
. Такой процесс дает правильный файл, однако это также позволяет удаленным пользователям увидеть любой файл системы, к которой Web-сервер имеет доступ, просто запросив, к примеру, файл
../../.. /etc/passwd
. Подобные каталоги
..
необходимо явно проверять и отклонять. Системный вызов
chroot
предоставляет хороший способ, позволяющий сделать обработку имен файлов в программах более простой.

Если имена файлов передаются в другие программы, то необходима еще более тщательная проверка. Например, если в имени файла используется начальный символ

, то весьма вероятно, что другая программа интерпретирует его как опцию командной строки.

22.3.3. Переменные окружения

В программах, работающих с возможностями setuid или setgid, нужно проявлять особую осторожность с установками окружения. Эти переменные определяются пользователем, активизировавшим программу, тем самым открывается путь для атак. Самая явная атака может пройти через переменную окружения

PATH
, изменяющую те каталоги, в которых функции
execlp
и
execvp
отыскивают программы. Если привилегированная программа запускает другие программы, то она должна убедиться, что это именно те программы, которые нужны! Пользователь, который имеет возможность подменить программный путь поиска, легко может подвергнуть программу опасности.

Существуют и другие переменные окружения, которые могут оказаться опасными. Например, переменная

LD_PRELOAD
позволяет пользователю указать некоторую библиотеку для загрузки до стандартной библиотеки С. Это может быть полезным, но одновременно и очень опасным в привилегированных приложениях (по этой же причине переменная окружения игнорируется, если реальное и эффективное универсальные имена совпадают).

Если программа локализована, то переменная

NLSPATH
также становится проблемной. Она позволяет пользователю переключать используемый программой языковой каталог, который определяет способ перевода строк. Это означает, что в переводных программах пользователь имеет возможность указать значение для любой переводимой строки. Строку можно сделать сколько угодно длинной, вынуждая программу быть крайне осторожной при выделении буфера. Еще более опасным является то, что при переводе форматирующих строк для таких функций, как
printf
, можно изменить формат. Например, строка
Hello World, today is %s
может превратиться в
Hello World, today is %c%d%s.
Трудно предсказать, какое воздействие могут оказать подобные изменения на функционирование программы!

Поделиться:
Популярные книги

Чужое наследие

Кораблев Родион
3. Другая сторона
Фантастика:
боевая фантастика
8.47
рейтинг книги
Чужое наследие

Бальмануг. Студентка

Лашина Полина
2. Мир Десяти
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Бальмануг. Студентка

Авиатор: назад в СССР

Дорин Михаил
1. Авиатор
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Авиатор: назад в СССР

Генерал-адмирал. Тетралогия

Злотников Роман Валерьевич
Генерал-адмирал
Фантастика:
альтернативная история
8.71
рейтинг книги
Генерал-адмирал. Тетралогия

На границе империй. Том 6

INDIGO
6. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.31
рейтинг книги
На границе империй. Том 6

Теневой путь. Шаг в тень

Мазуров Дмитрий
1. Теневой путь
Фантастика:
фэнтези
6.71
рейтинг книги
Теневой путь. Шаг в тень

Защитник

Астахов Евгений Евгеньевич
7. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Защитник

Кодекс Охотника. Книга XIII

Винокуров Юрий
13. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XIII

Его маленькая большая женщина

Резник Юлия
Любовные романы:
современные любовные романы
эро литература
8.78
рейтинг книги
Его маленькая большая женщина

Проклятый Лекарь IV

Скабер Артемий
4. Каратель
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Проклятый Лекарь IV

Жандарм 4

Семин Никита
4. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Жандарм 4

Тринадцатый V

NikL
5. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый V

Кодекс Охотника. Книга IV

Винокуров Юрий
4. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга IV

Энфис 2

Кронос Александр
2. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 2