address sanitizer или как сделать программы на c/с++ надежнее и...

31
AddressSanitizer Как сделать программы на C/С++ надежнее и безопаснее Костя Серебряный Google

Upload: ontico

Post on 19-Jun-2015

1.241 views

Category:

Documents


4 download

TRANSCRIPT

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

AddressSanitizer Как сделать программы на C/С++

надежнее и безопаснее

Костя СеребряныйGoogle

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

План доклада

● Ошибки доступа в память (C/C++)● AddressSanitizer -- инструмент для

поиска ошибок○ Что делает○ Как работает

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

Почему С или С++ ?

● Всё написано на C или C++○ Даже если Вы об этом не знаете

● Виртуальные машины (Java, Perl, Python)

● Базы данных (MySQL)

● Веб серверы (Apache)

● Все остальное тоже (libpng, libz, memcached)

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

C++ в Google

● Всего > 100М строк кода○ Больше всего кода на С++

● Серверная часть○ Mapreduce, Bigtable, Spanner, Chubby, ...

● Chrome (> 10M строк)

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

Плата за эффективность

+ "Ручное" управление памятью - Ошибки использования памяти * Переполнение буфера * Использование после free

Открытые ворота для хакеров

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

Что же делать?

● Бинарная инструментация○ Valgrind, Dr.Memory, Intel Parallel Studio, Purify,

Bounds Checker, Insure++, ... ○ Медленно (> 20x), только heap

● Отладочный malloc○ Постраничная защита

■ electric fence, libgmalloc, Page Heap○ Магические значения○ Находят не всё, медленно, только heap

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

AddressSanitizer

● Инструментирующий компилятор + библиотека

● Май 2011: первая версия○ Май 2012: входит в LLVM 3.1

● clang -faddress_sanitizer a.c

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

Кстати: Clang, LLVM

● Компилятор C/C++ (opensource)● Независимые модули

○ C++ frontend○ Статический анализ, диагностика○ Оптимизатор○ Кодогенератор (x86, ARM, ...)

● Основной компилятор на MacOS, iOS● Активно используется в Google● Сопоставим с GCC по производительности

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

AddressSanitizer

● Переполнение буфера○ Динамические объекты○ Стековые объекты ○ Глобальные объекты

● Использование после free()● Двойной free, пересечение параметров

memcpy, и др.

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

Самое главное

● Среднее замедление: < 2x○ 3x-3.5x на очень больших бинарниках (кэш

инструкций)

● Клиентские приложения почти не замедляются

○ Chrome, Firefox

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

Пример 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-overflow READ 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 ??:0

0x000000415354 is located 4 bytes to the right of global variable 'global_array' (0x4151c0) of size 400

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

Пример 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 ??:0

Address 0x7f5620d981b4 is located at offset 436 in frame <main> of T0's stack: This frame has 1 object(s): [32, 432) 'stack_array'

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

Пример 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 ??:0

0x7fe4b0c76214 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

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

Пример 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:4

0x7faa07fce084 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:4

previously allocated by thread T0 here: #0 0x405579 in operator new[](unsigned long) _asan_rtl_ #1 0x4042f3 in main example_UseAfterFree.cc:2

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

КАК ЖЕ ЭТО ВСЕ РАБОТАЕТ?

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

Теневой (shadow) байт

0

7

6

5

4

3

2

1

-1

● У любых выравненных 8-и байт программы одно из 9-ти состояний:

○ N хороших байт○ (8 - N) плохих

Addressable

Unaddressable

Shadow

Хорошие

Плохие

Тень

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

Отображение память тень

Виртуальные адреса:Тень = Память / 8

0xffffffff0x20000000

0x1fffffff0x04000000

0x03ffffff0x00000000

Память

Тень

Закрыто

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

Или так:0xffffffff0x40000000

0x3fffffff0x28000000

0x27ffffff0x24000000

0x23ffffff0x20000000

0x1fffffff0x00000000

Тень = Память / 8 + 0x20000000

Память

Тень

Закрыто

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

Инструментирование: 8 байт*a = ...

char *shadow = (a>>3)+Offset;if (*shadow)

ReportError(a);*a = ...

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

Инструментирование: < 8 байт*a = ...

char *shadow = (a>>3)+Offset;if (*shadow && *shadow <= ((a&7)+N-1)) ReportError(a);*a = ...

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

Немножко ассемблераshr $0x3,%rax # shift by 3 mov $0x100000000000,%rcx or %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

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

Стековые переменныеvoid foo() { char a[328];

<------------- CODE ------------->

}

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

Стековые переменные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; }

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

Глобальные переменные

int a;

struct { int original; char redzone[60];} a; // 32-aligned

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

Библиотека

● Ининциализация теневой памяти● Замена malloc/free

○ Отравленные области вокруг malloc○ Отравление памяти при free, карантин○ Сохранение стеков malloc/free

● Перехват memset, strlen, и т.п. ● Вывод сообщений

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

Трофеи

● 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

● А у Вас баги есть?

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

Есть что улучшить

● Статический анализ○ Меньше проверок

● Инструментировать всё○ Библиотеки, Ассемблер

● Адаптировать для ядра

● Портировать на Windows○ Уже работает для С

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

Короче...

● AddressSanitizer: ○ Находит много ошибок в коде на C/C++ ○ Очень быстрый○ Можно использовать при тестировании○ ... и в боевом режиме (осторожно)○ Работает на Linux, MacOS, Android○ Часть LLVM

○ clang.llvm.org/docs/AddressSanitizer.html

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

А еще у нас есть...

● ThreadSanitizer○ Находит гонки (data races)○ С++ и Go

● MemorySanitizer○ Находит использование

неинициализированных данных (С++)

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

Q&A

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

Valgrind ASan MSan

Heap out-of-bounds YES YES NO

Stack out-of-bounds NO YES NO

Global out-of-bounds NO YES NO

Use-after-free YES YES NO

Use-after-return NO Sometimes NO

Uninitialized reads YES NO YES

CPU Overhead 10x-300x 1.5x-3x 3x

ASan/MSan vs Valgrind