Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
AddressSanitizerКак сделать программы на C/С++     надежнее и безопаснее       Костя Серебряный             Google
План доклада●   Ошибки доступа в память (C/C++)●   AddressSanitizer -- инструмент для    поиска ошибок    ○   Что делает  ...
Почему С или С++ ?●   Всё написано на C или C++    ○   Даже если Вы об этом не знаете●   Виртуальные машины (Java, Perl, P...
C++ в Google●   Всего > 100М строк кода    ○   Больше всего кода на С++●   Серверная часть    ○   Mapreduce, Bigtable, Spa...
Плата за эффективность+ "Ручное" управление памятью- Ошибки использования памяти  * Переполнение буфера  * Использование п...
Что же делать?●   Бинарная инструментация    ○   Valgrind, Dr.Memory, Intel Parallel Studio, Purify,        Bounds Checker...
AddressSanitizer●   Инструментирующий компилятор +    библиотека●   Май 2011: первая версия    ○   Май 2012: входит в LLVM...
Кстати: Clang, LLVM●   Компилятор C/C++ (opensource)●   Независимые модули    ○   C++ frontend    ○   Статический анализ, ...
AddressSanitizer●   Переполнение буфера    ○   Динамические объекты    ○   Стековые объекты    ○   Глобальные объекты●   И...
Самое главное●   Среднее замедление: < 2x    ○   3x-3.5x на очень больших бинарниках (кэш        инструкций)●   Клиентские...
Пример global-buffer-overflowint global_array[100] = {-1};int main(int argc, char **argv) {    return global_array[argc + ...
Пример stack-buffer-overflowint main(int argc, char **argv) { int stack_array[100]; stack_array[1] = 0; return stack_array...
Пример heap-buffer-overflowint main(int argc, char **argv) { int *array = new int[100]; int res = array[argc + 100]; // BO...
Пример heap-use-after-freeint main(int argc, char **argv) { int *array = new int[100]; delete [] array; return array[argc]...
КАК ЖЕ ЭТО ВСЕ РАБОТАЕТ?
Теневой (shadow) байт●   У любых выравненных 8-и байт    программы одно из 9-ти состояний:                                ...
Отображение память                тень  0xffffffff   Виртуальные адреса:  0x20000000                Тень = Память / 8     ...
Или так:0xffffffff0x40000000                      Тень =             Память / 8 + 0x200000000x3fffffff             Память0...
Инструментирование: 8 байт       *a = ...char *shadow = (a>>3)+Offset;if (*shadow)   ReportError(a);*a = ...
Инструментирование: < 8 байт       *a = ...char *shadow = (a>>3)+Offset;if (*shadow &&    *shadow <= ((a&7)+N-1))   Report...
Немножко ассемблераshr $0x3,%rax       # shift by 3mov $0x100000000000,%rcxor %rax,%rcx        # add offsetcmpb $0x0,(%rcx...
Стековые переменныеvoid foo() {    char a[328];    <------------- CODE ------------->}
Стековые переменныеvoid foo() {  char rz1[32]; // 32-byte aligned  char a[328];  char rz2[24];  char rz3[32];  int *shadow...
Глобальные переменныеint a;struct {  int original;  char redzone[60];} a; // 32-aligned
Библиотека●   Ининциализация теневой памяти●   Замена malloc/free    ○   Отравленные области вокруг malloc    ○   Отравлен...
Трофеи● Chromium (включая WebKit); в первые 10 месяцев  ○ heap-use-after-free: 201  ○ heap-buffer-overflow: 73  ○ global-b...
Есть что улучшить●   Статический анализ    ○   Меньше проверок●   Инструментировать всё    ○   Библиотеки, Ассемблер●   Ад...
Короче...●   AddressSanitizer:    ○   Находит много ошибок в коде на C/C++    ○   Очень быстрый    ○   Можно использовать ...
А еще у нас есть...●   ThreadSanitizer    ○   Находит гонки (data races)    ○   С++ и Go●   MemorySanitizer    ○   Находит...
Q&A
ASan/MSan vs Valgrind                      Valgrind   ASan        MSanHeap out-of-bounds    YES        YES         NOStack...
Upcoming SlideShare
Loading in …5
×

Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (Константин Серебряный)

2,066 views

Published on

  • Be the first to comment

  • Be the first to like this

Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (Константин Серебряный)

  1. 1. AddressSanitizerКак сделать программы на C/С++ надежнее и безопаснее Костя Серебряный Google
  2. 2. План доклада● Ошибки доступа в память (C/C++)● AddressSanitizer -- инструмент для поиска ошибок ○ Что делает ○ Как работает
  3. 3. Почему С или С++ ?● Всё написано на C или C++ ○ Даже если Вы об этом не знаете● Виртуальные машины (Java, Perl, Python)● Базы данных (MySQL)● Веб серверы (Apache)● Все остальное тоже (libpng, libz, memcached)
  4. 4. C++ в Google● Всего > 100М строк кода ○ Больше всего кода на С++● Серверная часть ○ Mapreduce, Bigtable, Spanner, Chubby, ...● Chrome (> 10M строк)
  5. 5. Плата за эффективность+ "Ручное" управление памятью- Ошибки использования памяти * Переполнение буфера * Использование после free Открытые ворота для хакеров
  6. 6. Что же делать?● Бинарная инструментация ○ Valgrind, Dr.Memory, Intel Parallel Studio, Purify, Bounds Checker, Insure++, ... ○ Медленно (> 20x), только heap● Отладочный malloc ○ Постраничная защита ■ electric fence, libgmalloc, Page Heap ○ Магические значения ○ Находят не всё, медленно, только heap
  7. 7. AddressSanitizer● Инструментирующий компилятор + библиотека● Май 2011: первая версия ○ Май 2012: входит в LLVM 3.1● clang -faddress_sanitizer a.c
  8. 8. Кстати: Clang, LLVM● Компилятор C/C++ (opensource)● Независимые модули ○ C++ frontend ○ Статический анализ, диагностика ○ Оптимизатор ○ Кодогенератор (x86, ARM, ...)● Основной компилятор на MacOS, iOS● Активно используется в Google● Сопоставим с GCC по производительности
  9. 9. AddressSanitizer● Переполнение буфера ○ Динамические объекты ○ Стековые объекты ○ Глобальные объекты● Использование после free()● Двойной free, пересечение параметров memcpy, и др.
  10. 10. Самое главное● Среднее замедление: < 2x ○ 3x-3.5x на очень больших бинарниках (кэш инструкций)● Клиентские приложения почти не замедляются ○ Chrome, Firefox
  11. 11. Пример global-buffer-overflowint global_array[100] = {-1};int main(int argc, char **argv) { return global_array[argc + 100]; // BOOM}% clang++ -O1 -faddress-sanitizer example_GlobalOutOfBounds.cc ; ./a.out==10538== ERROR: AddressSanitizer global-buffer-overflowREAD of size 4 at 0x000000415354 thread T0 #0 0x402481 in main example_GlobalOutOfBounds.cc:3 #1 0x7f0a1c295c4d in __libc_start_main ??:0 #2 0x402379 in _start ??:00x000000415354 is located 4 bytes to the right of global variable global_array (0x4151c0) of size 400
  12. 12. Пример stack-buffer-overflowint main(int argc, char **argv) { int stack_array[100]; stack_array[1] = 0; return stack_array[argc + 100]; } // BOOM% clang++ -O1 -faddress-sanitizer example_StackOutOfBounds.cc; ./a.out==10589== ERROR: AddressSanitizer stack-buffer-overflowREAD of size 4 at 0x7f5620d981b4 thread T0 #0 0x4024e8 in main example_StackOutOfBounds.cc:4 #1 0x7f5621db6c4d in __libc_start_main ??:0 #2 0x402349 in _start ??:0Address 0x7f5620d981b4 is located at offset 436 in frame <main> of T0s stack: This frame has 1 object(s): [32, 432) stack_array
  13. 13. Пример heap-buffer-overflowint main(int argc, char **argv) { int *array = new int[100]; int res = array[argc + 100]; // BOOM delete [] array; return res; }% clang++ -O1 -faddress-sanitizer example_HeapOutOfBounds.cc; ./a.out==10565== ERROR: AddressSanitizer heap-buffer-overflowREAD of size 4 at 0x7fe4b0c76214 thread T0 #0 0x40246f in main example_HeapOutOfBounds.cc:3 #1 0x7fe4b0cb4c4d in __libc_start_main ??:00x7fe4b0c76214 is located 4 bytes to the right of 400-byte region [0x7fe..., 0x7fe...)allocated by thread T0 here: #0 0x402c36 in operator new[](unsigned long) _asan_rtl_ #1 0x402422 in main example_HeapOutOfBounds.cc:3
  14. 14. Пример heap-use-after-freeint main(int argc, char **argv) { int *array = new int[100]; delete [] array; return array[argc]; } // BOOM% clang++ -O1 -faddress-sanitizer example_UseAfterFree.cc; ./a.out==30226== ERROR: AddressSanitizer heap-use-after-freeREAD of size 4 at 0x7faa07fce084 thread T0 #0 0x40433c in main example_UseAfterFree.cc:40x7faa07fce084 is located 4 bytes inside of 400-byte region [0x7fa...,x7fa...)freed by thread T0 here: #0 0x4058fd in operator delete[](void*) _asan_rtl_ #1 0x404303 in main example_UseAfterFree.cc:4previously allocated by thread T0 here: #0 0x405579 in operator new[](unsigned long) _asan_rtl_ #1 0x4042f3 in main example_UseAfterFree.cc:2
  15. 15. КАК ЖЕ ЭТО ВСЕ РАБОТАЕТ?
  16. 16. Теневой (shadow) байт● У любых выравненных 8-и байт программы одно из 9-ти состояний: 0 ○ N хороших байт 7 ○ (8 - N) плохих 6 5 Хорошие 4 Плохие 3 2 Тень 1 -1
  17. 17. Отображение память тень 0xffffffff Виртуальные адреса: 0x20000000 Тень = Память / 8 Память Тень 0x1fffffff 0x04000000 Закрыто 0x03ffffff 0x00000000
  18. 18. Или так:0xffffffff0x40000000 Тень = Память / 8 + 0x200000000x3fffffff Память0x28000000 Тень0x27ffffff0x24000000 Закрыто0x23ffffff0x200000000x1fffffff0x00000000
  19. 19. Инструментирование: 8 байт *a = ...char *shadow = (a>>3)+Offset;if (*shadow) ReportError(a);*a = ...
  20. 20. Инструментирование: < 8 байт *a = ...char *shadow = (a>>3)+Offset;if (*shadow && *shadow <= ((a&7)+N-1)) ReportError(a);*a = ...
  21. 21. Немножко ассемблераshr $0x3,%rax # shift by 3mov $0x100000000000,%rcxor %rax,%rcx # add offsetcmpb $0x0,(%rcx) # load shadowje 1f <foo+0x1f>ud2a # generate SIGILL*movq $0x1234,(%rdi) # original store* May use call instead of UD2
  22. 22. Стековые переменныеvoid foo() { char a[328]; <------------- CODE ------------->}
  23. 23. Стековые переменныеvoid foo() { char rz1[32]; // 32-byte aligned char a[328]; char rz2[24]; char rz3[32]; int *shadow = (&rz1 >> 3) + kOffset; shadow[0] = 0xffffffff; // poison rz1 shadow[11] = 0xffffff00; // poison rz2 shadow[12] = 0xffffffff; // poison rz3 <------------- CODE -------------> shadow[0] = shadow[11] = shadow[12] = 0;}
  24. 24. Глобальные переменныеint a;struct { int original; char redzone[60];} a; // 32-aligned
  25. 25. Библиотека● Ининциализация теневой памяти● Замена malloc/free ○ Отравленные области вокруг malloc ○ Отравление памяти при free, карантин ○ Сохранение стеков malloc/free● Перехват memset, strlen, и т.п.● Вывод сообщений
  26. 26. Трофеи● Chromium (включая WebKit); в первые 10 месяцев ○ heap-use-after-free: 201 ○ heap-buffer-overflow: 73 ○ global-buffer-overflow: 8 ○ stack-buffer-overflow: 7 ○ Google выплатил > $100k внешним исследователям● Сотни ошибок в серверных приложениях Google● Firefox, FreeType, FFmpeg, WebRTC, libjpeg-turbo● Perl, Vim, LLVM, GCC● MySQL● А у Вас баги есть?
  27. 27. Есть что улучшить● Статический анализ ○ Меньше проверок● Инструментировать всё ○ Библиотеки, Ассемблер● Адаптировать для ядра● Портировать на Windows ○ Уже работает для С
  28. 28. Короче...● AddressSanitizer: ○ Находит много ошибок в коде на C/C++ ○ Очень быстрый ○ Можно использовать при тестировании ○ ... и в боевом режиме (осторожно) ○ Работает на Linux, MacOS, Android ○ Часть LLVM ○ clang.llvm.org/docs/AddressSanitizer.html
  29. 29. А еще у нас есть...● ThreadSanitizer ○ Находит гонки (data races) ○ С++ и Go● MemorySanitizer ○ Находит использование неинициализированных данных (С++)
  30. 30. Q&A
  31. 31. ASan/MSan vs Valgrind Valgrind ASan MSanHeap out-of-bounds YES YES NOStack out-of-bounds NO YES NOGlobal out-of-bounds NO YES NOUse-after-free YES YES NOUse-after-return NO Sometimes NOUninitialized reads YES NO YESCPU Overhead 10x-300x 1.5x-3x 3x

×