Дезинфицирующее средство для кода

Инструмент для обнаружения ошибок, связанных с памятью

Очиститель кода — это программный инструмент, который обнаруживает ошибки в виде неопределенного или подозрительного поведения компилятора , вставляющего код инструментирования во время выполнения. Класс инструментов был впервые представлен AddressSanitizer (или ASan ) от Google в 2012 году, который использует напрямую отображенную теневую память для обнаружения повреждений памяти, таких как переполнение буфера или доступ к висячему указателю (use-after-free).

АдресСанитайзер

ASan от Google, представленный в 2012 году, использует схему теневой памяти для обнаружения ошибок памяти. Он доступен в:

  • Clang (начиная с версии 3.1 [1] )
  • GCC (начиная с версии 4.8 [2] )
  • Xcode (начиная с версии 7.0 [3] )
  • MSVC (широко доступен, начиная с версии 16.9 [4] ).

В среднем инструментарий увеличивает время обработки примерно на 73%, а использование памяти на 240%. [5] Существует аппаратно-ускоренный ASan под названием HWAsan, доступный для AArch64 и (в ограниченной степени) x86_64. [6]

AddressSanitizer не обнаруживает никаких неинициализированных чтений памяти (но это обнаруживает MemorySanitizer [7] ), и обнаруживает только некоторые ошибки использования после возврата. [8] Он также не способен обнаружить все произвольные ошибки повреждения памяти, а также все произвольные ошибки записи из-за целочисленных недопереполнений/переполнений (когда целое число с неопределенным поведением используется для вычисления смещений адресов памяти). Смежные буферы в структурах и классах не защищены от переполнения, отчасти для предотвращения нарушения обратной совместимости. [9]

KernelAddressSanitizer

KernelAddressSanitizer ( KASan ) обнаруживает ошибки динамической памяти в ядре Linux. [10] Для инструментирования ядра требуется специальная функция в компиляторе, предоставляющая параметр командной строки, поскольку ядра не используют то же адресное пространство, что и обычные программы. [ 11] [12]-fsanitize=kernel-address

Другие дезинфицирующие средства

Google также выпустила LeakSanitizer (LSan, утечки памяти ), ThreadSanitizer (TSan, гонки данных и взаимоблокировки ), MemorySanitizer (MSan, неинициализированная память ) и UndefinedBehaviorSanitizer ( UBSan , неопределенное поведение , с детальным контролем). [13] Эти инструменты, как правило, доступны в Clang/LLVM и GCC. [14] [15] [16] Подобно KASan, существуют версии LSan, MSan, TSan, специфичные для ядра, а также полностью оригинальные санитайзеры ядра, такие как KFENCE и KCSan. [17]

Дополнительные инструменты очистки (сгруппированные по компиляторам под флагом -fsanitize или аналогичным) включают: [14] [15] [16]

  • Целостность потока управления LLVM и ее аналог в ядре, который проверяет виртуальные таблицы и приведение типов для CFI прямого доступа
  • MemTagSanitizer — ASan-подобный инструмент, использующий возможности Armv8.5-A для очень низких накладных расходов
  • ShadowCallStack, инструмент AArch64, обеспечивающий защиту теневого стека
  • Scudo Hardened Allocator, альтернативный распределитель памяти, включающий GWP-ASan, вероятностный аналог ASan с низкими накладными расходами [18]
  • libFuzzer, инструмент LLVM, который добавляет покрытие кода к фаззингу [19]

Использование

Дезинфектор кода обнаруживает подозрительное поведение во время работы программы. Один из распространенных способов использования дезинфектора — это его сочетание с фаззингом , который генерирует входные данные, которые с большой вероятностью могут вызвать ошибки. [20]

Пользователи

Разработчики Chromium и Firefox являются активными пользователями AddressSanitizer; [20] [21] инструмент обнаружил сотни ошибок в этих веб-браузерах. [22] Ряд ошибок был обнаружен в FFmpeg [23] и FreeType . [24] Ядро Linux включило AddressSanitizer для архитектуры x86-64 , начиная с версии Linux 4.0.

Примеры

ASan: использование кучи после освобождения

// Для компиляции: g++ -O -g -fsanitize=address heap-use-after-free.ccint main ( int argc , char ** argv ) {      int * массив = новый int [ 100 ];     удалить [] массив ;   вернуть массив [ argc ]; // БУМ  }
$ ./г.выход==5587==ОШИБКА: AddressSanitizer: heap-use-after-free по адресу 0x61400000fe44 на pc 0x47b55f bp 0x7ffc36b28200 sp 0x7ffc36b281f8ЧТЕНИЕ размера 4 в 0x61400000fe44 поток T0 #0 0x47b55e в главном /home/test/example_UseAfterFree.cc:5 #1 0x7f15cfe71b14 в __libc_start_main (/lib64/libc.so.6+0x21b14) #2 0x47b44c в _start (/root/a.out+0x47b44c)0x61400000fe44 расположен на 4 байта внутри 400-байтовой области [0x61400000fe40,0x61400000ffd0)освобождено потоком T0 здесь: #0 0x465da9 в операторе delete[](void*) (/root/a.out+0x465da9) #1 0x47b529 в главном /home/test/example_UseAfterFree.cc:4ранее выделено потоком T0 здесь: #0 0x465aa9 в операторе new[](unsigned long) (/root/a.out+0x465aa9) #1 0x47b51e в основном /home/test/example_UseAfterFree.cc:3РЕЗЮМЕ: AddressSanitizer: heap-use-after-free /home/test/example_UseAfterFree.cc:5 mainТеневые байты вокруг ошибочного адреса: [...] 0x0c287fff9fb0: фа фа фа фа фа фа фа фа фа фа фа фа фа фа фа=>0x0c287fff9fc0: фа фа фа фа фа фа фа фа[fd]fd fd fd fd fd fd fd 0x0c287fff9fd0: фд фд фд фд фд фд фд фд фд фд фд фд фд фд фд фд фд [...]Легенда теневых байтов (один теневой байт представляет 8 байтов приложения): Адресуемый: 00 Частично адресуемый: 01 02 03 04 05 06 07 Куча слева redzone: fa Куча правая красная зона: fb Освобожденная область кучи: fd Стек левая красная зона: f1 Стек в середине красной зоны: f2 Стек правая красная зона: f3 Стек частичной красной зоны: f4 Стек после возврата: f5 Использование стека после области действия: f8 Глобальная красная зона: f9 Глобальный порядок инициализации: f6 Отравлен пользователем: f7 ASan внутренний: fe==5587==ПРЕРЫВАНИЕ

ASan: переполнение буфера кучи

// ЗАПУСК: clang++ -O -g -fsanitize=адрес heap-buf-of.cc && ./a.outint main ( int argc , char ** argv ) {      int * массив = новый int [ 100 ];     массив [ 0 ] = 0 ;   int res = array [ argc + 100 ]; // БАБАХ       удалить [] массив ;   возврат рез ; }
==25372==ОШИБКА: AddressSanitizer: переполнение буфера кучи по адресу 0x61400000ffd4 на компьютере 0x0000004ddb59 bp 0x7fffea6005a0 sp 0x7fffea600598ЧТЕНИЕ размера 4 в 0x61400000ffd4 поток T0 #0 0x46bfee в главном /tmp/main.cpp:4:130x61400000ffd4 расположен на 4 байта правее 400-байтовой области [0x61400000fe40,0x61400000ffd0)выделено потоком T0 здесь: #0 0x4536e1 в операторе delete[](void*) #1 0x46bfb9 в основном /tmp/main.cpp:2:16

ASan: переполнение стека-буфера

// ЗАПУСК: clang -O -g -fsanitize=адрес стек-буфера-из-.cc && ./a.outint main ( int argc , char ** argv ) {      int stack_array [ 100 ];  стековый_массив [ 1 ] = 0 ;   return stack_array [ argc + 100 ]; // БАБАХ    }
==7405==ОШИБКА: AddressSanitizer: переполнение буфера стека по адресу 0x7fff64740634 на компьютере 0x46c103, процессор 0x7fff64740470, процессор 0x7fff64740468ЧТЕНИЕ размера 4 в 0x7fff64740634 поток T0 #0 0x46c102 в основном /tmp/example_StackOutOfBounds.cc:5Адрес 0x7fff64740634 находится в стеке потока T0 по смещению 436 в кадре #0 0x46bfaf в основном /tmp/example_StackOutOfBounds.cc:2 В этом кадре 1 объект(ов): [32, 432) 'stack_array' <== Доступ к памяти по смещению 436 приводит к переполнению этой переменной

ASan: Глобальное переполнение буфера

// ЗАПУСК: clang -O -g -fsanitize=адрес global-buf-of.cc && ./a.out int global_array [ 100 ] = { -1 }; int main ( int argc , char ** argv ) { return global_array [ argc + 100 ]; // БАХ }             
==7455==ОШИБКА: AddressSanitizer: глобальное переполнение буфера по адресу 0x000000689b54 на компьютере 0x46bfd8 bp 0x7fff515e5ba0 sp 0x7fff515e5b98ЧТЕНИЕ размера 4 в 0x000000689b54 поток T0 #0 0x46bfd7 в основном /tmp/example_GlobalOutOfBounds.cc:40x000000689b54 расположен на 4 байта правее глобальная переменная 'global_array' из 'example_GlobalOutOfBounds.cc' (0x6899c0) размером 400

UBSan: nullptr-разыменование

// ВЫПОЛНЕНИЕ: g++ -O -g -fsanitize=null null-dereference.c && ./a.out int main ( int argc , char ** argv ) { const char * ptr = nullptr ; return * ptr ; // БАХ }              
null-dereference.c:4:10: ошибка выполнения: загрузка нулевого указателя типа 'const char'Ошибка сегментации (сброс керна)

Смотрите также

Ссылки

  1. ^ "LLVM 3.1 Release Notes". LLVM . Получено 8 февраля 2014 г. .
  2. ^ "GCC 4.8 Release Notes". GCC . Получено 8 февраля 2014 г. .
  3. ^ «Address Sanitizer | Документация для разработчиков Apple».
  4. ^ "Visual Studio 2019 версии 16.9 Release Notes". Microsoft . Получено 5 марта 2021 г. .
  5. ^ Константин Серебряный; Дерек Брюнинг; Александр Потапенко; Дмитрий Вьюков. "AddressSanitizer: быстрая проверка корректности адресов" (PDF) . Труды конференции USENIX 2012 года на Annual Technical Conference .
  6. ^ «Документация по проектированию аппаратно-управляемого AddressSanitizer — документация Clang 17.0.0git». clang.llvm.org .
  7. ^ "MemorySanitizer". GitHub .
  8. ^ "ComparisonOfMemoryTools". AddressSanitizer Wiki . Получено 1 декабря 2017 г.
  9. ^ "Обход AddressSanitizer" (PDF) . Эрик Уимберли . Получено 1 июля 2014 г. .
  10. ^ "KernelAddressSanitizer (KASAN)". Архивировано из оригинала 2015-09-15.
  11. ^ Джейк Эдж. «Санитайзер адреса ядра».
  12. ^ Джонатан Корбет. «3.20 окно слияния часть 2».
  13. ^ Google (2 марта 2023 г.). «sanitizers: этот проект является домом для Sanitizers: AddressSanitizer, MemorySanitizer, ThreadSanitizer, LeakSanitizer и других». GitHub . Google. {{cite web}}: |last1=имеет общее название ( помощь )
  14. ^ ab "sanitizer - The Rust Unstable Book". doc.rust-lang.org . Эта функция позволяет использовать один из следующих sanitizers: [...] ControlFlowIntegrity LLVM Control Flow Integrity
  15. ^ ab "Руководство пользователя компилятора Clang — Документация Clang 17.0.0git". clang.llvm.org . -f[no-]sanitize=check1,check2,... Включить проверки времени выполнения для различных форм неопределенного или подозрительного поведения
  16. ^ ab "Параметры инструментирования (использование коллекции компиляторов GNU (GCC))". gcc.gnu.org .
  17. ^ «Linux Kernel Sanitizers». Google. 2 марта 2023 г.
  18. ^ "GWP-ASan — документация LLVM 17.0.0git". llvm.org .
  19. ^ "libFuzzer – библиотека для фаззинг-тестирования с контролем покрытия. — Документация LLVM 17.0.0git". llvm.org .
  20. ^ ab Абишек Арья; Крис Неккар; Chrome Security Team. «Fuzzing for Security».
  21. ^ "Securing Firefox: Trying new code analysis techniques". Архивировано из оригинала 2016-03-07 . Получено 2018-06-18 .
  22. ^ "Некоторые ошибки, обнаруженные AddressSanitizer". GitHub .
  23. ^ Матеуш Юрчик; Гинваэль Колдвинд (2014-01-10). "FFmpeg и тысяча исправлений". J00Ru//Vx Tech Blog .
  24. ^ «Результаты поиска AddressSanitizer в FreeType Bugs».
  • Группа Google AddressSanitizer (без списка рассылки)
  • Страница проекта AddressSanitizer
  • Документация AddressSanitizer (Clang)
Взято с "https://en.wikipedia.org/w/index.php?title=Code_sanitizer&oldid=1255347806"