На основе этих соглашений реализации malloc()
обычно возвращают память, первый байт которой выровнен в соответствии с размером слова процессора (4 байта для 32-разрядных и 8 байтов на 64-разрядных процессоров). По умолчанию Electric Fence пытается эмулировать такое поведение, предлагая функцию malloc()
, возвращающую только адреса, кратные sizeof(int)
.
В большинстве программ подобное выравнивание не критично, то есть распределение памяти происходит инкрементным образом на основе размера машинного слова либо в виде простых символьных строк, для которых требования по выравниванию не предусмотрены (поскольку каждый элемент занимает всего 1 байт).
В случае с нашей тестовой программой первый вызов malloc()
распределил пять байт.
Для того чтобы Electric Fence удовлетворял своим ограничениям по выравниванию, он трактует этот вызов как запрос восьми байт, с дополнительными тремя доступными байтами. В этом случае небольшие переполнения буфера, распространяющиеся на эту область, не перехватываются.
В связи с тем, что выравнивание malloc()
обычно можно игнорировать, а выравнивание может способствовать незаметному переполнению буфера, Electric Fence предоставляет возможность управление выравниванием через переменную окружения ЕF_ALIGNMENT
. Если эта переменная установлена, все результаты malloc()
выравниваются в соответствии с ее значением. Например, если переменная установлена в значение 5, все результаты malloc()
будут рассматриваться как кратные 5 (тем не менее, это значение не особенно полезно). Для отключения выравнивания памяти перед запуском программы установите ЕF_ALIGNMENT
в 1
. В среде Linux некорректно выровненный доступ в любом случае исправляются в ядре, несмотря на то, что в результате скорость выполнения программы может существенно снизиться. Программа будет функционировать корректно, если только в ней не присутствуют небольшие переполнения буфера.
Ниже приведен пример поведения тестовой программы, скомпонованной с Electric Fence, после установки ЕF_ALIGNMENT
в 1
.
$ export EF_ALIGNMENT=1
$ gdb broken
...
(gdb) run
Starting program: /usr/src/lad/code/broken
Electric Fence 2.2.0 Copyright (C) 1987 - 1999 Bruce Perens.
Program received signal SIGSEGV, Segmentation fault.
0x002a78c6 in strcpy() from /lib/tls/libc.so.6
(gdb) where
#0 0x002a78c6 in strcpy() from /lib/tls/libc.so.6
#1 0x08048522 in broken() at broken.c:15
#2 0x08048638 in main() at broken.с:47
На этот раз Electric Fence нашел переполнение буфера, которое произошло первым.
7.5.3. Другие средства
Electric Fence не только помогает обнаружить переполнение буфера, но и может найти недогрузку буфера (выполняя доступ к памяти, расположенной перед началом выделяемого malloc()
буфера) и получает доступ к памяти, освобождаемой с помощью free()
. Если переменная окружения EF_PROTECT_BELOW
установлена в 1
, Electric Fence перехватывает недогрузку буфера вместо его переполнения. Это происходит путем размещения недоступной области памяти непосредственно перед фактической областью памяти, возвращаемой функцией malloc()
. При этом Electric Fence не сможет обнаружить переполнение буфера из-за страничной организации памяти, реализованной в большинстве процессоров. Выравнивание памяти может затруднить обнаружение переполнения буфера, однако оно не влияет на недогрузку буфера. Функция malloc()
из Electric Fence всегда возвращает адрес памяти в начале страницы, которая всегда выровнена по границе слова.
Если EF_PROTECT_FREE
установлена в 1
, free()
делает переданную ей область памяти недоступной, но не возвращает ее в пул свободной памяти. Если программа пытается получить доступ к этой памяти на любом этапе в будущем, ядро обнаружит несанкционированный доступ. Настройка EF_PROTECT_FREE
помогает удостовериться, что код ни на одном этапе выполнения не использует память, освобожденную с помощью free()
.
7.5.4. Ограничения
Несмотря на то что Electric Fence выполняет неплохую работу по обнаружению переполнения буферов, выделенных malloc()
, он не помогает отслеживать проблемы ни с глобальными, ни с локальными данными. Electric Fence также не обнаруживает утечки памяти, потому решать эту проблему придется другими средствами.
7.5.5. Потребление ресурсов