Slide 1

Slide 1 text

Практический язык для извлечения данных из исходных кодов и подготовки их к анализу Signed-off-by: Denis Efremov [email protected] ISP RAS/NRU HSE Yandex Perl Meetup June 06, 2018 GPG Fingerprint: 7654 0336 0294 0DF1 920F E403 B522 95B0 3350 301F

Slide 2

Slide 2 text

О Докладчике Разработчик ИСП РАН (ispras.ru). Отдел технологий программирования. Аспирант НИУ ВШЭ (hse.ru). Верификация программного обеспечения, разработка формальных спецификаций, инструментов статического и динамического анализа для ядра Linux. GitHub: https://github.com/evdenis KeyBase: https://keybase.io/efremov

Slide 3

Slide 3 text

О чем речь? • Стандарты • Orange Book: division A (verified protection) (A1, Beyond A1) • Common Criteria (EAL7) • DO-178C/DO-333 "Formal Methods Supplement to DO-178C and DO-278A”IEC 61508 (SIL4) • ГОСТ Р ИСО/МЭК 15408-3-2013 "Методы и средства обеспечения безопасности. Критерии оценки безопасности информационных технологий" • Сертификация ПО на соответствие стандартам • Исходные коды • Формальная, полу-формальная, неформальная документация • Тесты, спецификации • Описание цикла разработки • Программы, которые помогают готовить сертификационный пакет

Slide 4

Slide 4 text

Что важно для чтения кода программистом? • Форматирование • Документация • «Понятность» • Инструменты навигации

Slide 5

Slide 5 text

Что важно для анализа кода программистом? • Форматирование • Документация • «Понятность» • Инструменты навигации • Подготовка кода для запуска тяжеловесных статических инструментов (Frama-C, VCC, Isabelle, CPAChecker, …) • Возможность менять подготовленный код с возвратом «назад» • Карты кода

Slide 6

Slide 6 text

Как работают инструменты с Си • Запуск препроцессора • Убираются комментарии • Раскрываются макросы • Запуск компилятора до стадии построения Control Flow Graph (CFG) • Полная потеря форматирования • Исходные код на CFG уровне слишком сильно отличается от оригинального

Slide 7

Slide 7 text

Существующие инструменты: facebook/pfff • Инструменты для анализа кода, его визуализации и трансформаций, сохраняющих исходный стиль https://github.com/facebook/pfff (OCaml) • Парсер: препроцессор + Си + форматирование • Ошибки парсинга (нужен предварительный сбор макросов) • Неполная поддержка языка Си с расширениями

Slide 8

Slide 8 text

Насколько критична точность при подобном анализе? • Что будет если пропустить конструкцию, которую не удается распознать? • Что будет если CFG не точно построить (например, будут лишние зависимости)? • Что будет если сложность кода и его зависимости не совсем точно посчитаются? • Возможно ли запустить инструменты на «неполном» наборе кода?

Slide 9

Slide 9 text

Why Not? (Linux Kernel tools/checkpatch.pl) (1) our @typeList = ( qr{void}, qr{(?:(?:un)?signed\s+)?char}, qr{(?:(?:un)?signed\s+)?short\s+int}, qr{(?:(?:un)?signed\s+)?short}, qr{(?:(?:un)?signed\s+)?int} ); our $C90_int_types = qr{(?x: long\s+long\s+int\s+(?:un)?signed| long\s+long\s+(?:un)?signed\s+int| long\s+long\s+(?:un)?signed )};

Slide 10

Slide 10 text

Why Not? (Linux Cross Reference) (2) my $_identifier_re = qr( (?m:^|(?<=[^a-zA-Z0-9_\#])) # Non-symbol chars. (_*[a-zA-Z][a-zA-Z0-9_]*) # The symbol. \b)x; my $_reserved = { map { $_ => 1 } qw(asm auto break case char const continue default do double else enum ...)}; sub parsespec { return ['atom', '\\\\.', undef, 'comment', '/\*', '\*/', 'comment', '//', "\$", 'string', '"(?:[^\\\\"]*\\\\.)*[^\\\\"]*"', undef, 'string', "'(?:[^\\\\']*\\\\.)*[^\\\\']*'", undef]; }

Slide 11

Slide 11 text

Общая схема работы инструмента Подготовка • Объединение исходных кодов в единый файл • Раскрытие директив условной компиляции; включение заголовочных файлов • Предобработка исходного кода (макросы, строки, комментарии) Построение графа • Независимые поиск элементов по типам • Выделение меток и идентификаторов • Построение графа зависимостей Анализ • Сбор метрик по исходному коду • Разрешение циклов • Вывод подграфа, карты исходных кодов…

Slide 12

Slide 12 text

Алгоритм построения графа зависимостей (1) • Загрузка исходного кода • Объединяются все *.c файлы • Include директивы выносятся на верхний уровень с сохранением порядка • Запускается препроцессор GCC • Без раскрытия макросов (флаг –fdirectives-only) • С учётом только директив условной компиляции и include • С сохранением комментариев (флаг –С)

Slide 13

Slide 13 text

Алгоритм построения графа зависимостей (2) • Все комментарии и строки в коде заменяется на специальные уникальные идентификаторы • Первым делом из кода выбираются определения макросов. После они также заменяются на специальные идентификаторы, которые при дальнейшем разборе рассматриваются как пробелы #define macro_test() ({0;}) some_typedef_t *test(void) { /* TODO: int main() {return 0;} */ macro_test(); printf("}{{ int test(args) {};"); return NULL; } $@1$ some_typedef_t *test(void) { $%2$ macro_test(); printf($^3$); return NULL; }

Slide 14

Slide 14 text

Алгоритм построения графа зависимостей (3) • Осуществляется поиск в исходном коде на элементов следующих типов: typedef, enum, structure, global, declaration, function • Каждому элементу из этих множеств присваивается уникальный идентификатор (используется для обозначения узла в графе) id: 1idkfa type: struct name: hell id: 2iddqd type: function name: kill id: 4iddt type: global name: cyberdaemon Id:5idfa type: declaration name: kill_em_all id: 3idclip type: typedef name: ptr_to_hell_t Id:5idmypos type: enum name: my_kill_list

Slide 15

Slide 15 text

Алгоритм построения графа зависимостей (4) • У каждого элемента выделяется ряд атрибутов • Общие: имя, содержимое • Специфичные: поля у структур, константы у enum • Множество идентификаторов (ids) • Множество меток (tags) some_typedef_t *test(void) { $%2$ macro_test(); printf($^3$); return NULL; } struct security_operations { void (*skb_owned_by) (struct sk_buff *skb); int (*key_alloc) (struct key *key); void (*key_free) (struct cred *cred); };

Slide 16

Slide 16 text

Алгоритм построения графа зависимостей (5) • Создаётся глобальные хеш элементов • В ключах – метки из множеств идентификаторов • В значениях – сами объекты • Коллизии • Создаётся вложенный хеш к типом элемента в качестве ключа (Hash::Ordered) • Создаётся пустой ориентированный граф, куда вносятся все элементы (изолированные вершины могут быть) (Graph::Directed) • На основе таблицы допустимости вхождений элементов, индекса, и множества меток строятся связи между вершинами графа

Slide 17

Slide 17 text

Фильтр допустимости зависимостей элементов

Slide 18

Slide 18 text

Фильтр допустимости зависимостей элементов

Slide 19

Slide 19 text

Фильтр допустимости зависимостей элементов

Slide 20

Slide 20 text

Что можно реализовать на этой основе (1) Анализ сложности функций, составление отчетов

Slide 21

Slide 21 text

Что можно реализовать на этой основе (2) Интерактивная карта исходных кодов с собранными метриками LIVE DEMONSTRATION https://youtu.be/AuUsaleib9M

Slide 22

Slide 22 text

Что можно реализовать на этой основе (3) Diff версий для графа вызовов (callgraph) Green – added Red – deleted Black – unchanged

Slide 23

Slide 23 text

Что можно реализовать на этой основе (4) Вывод только отдельных функций с их зависимостями • Вывод отдельных функций с их зависимостями (gcc -c) • Выделение подграфа • Разрешение циклов • Функция <-> Функция, Структура <-> Структура, … • Топологическая сортировка для вывода

Slide 24

Slide 24 text

Что можно реализовать на этой основе (4) Вывод только отдельных функций с их зависимостями LIVE DEMONSTRATION SELinux Callgraph sel_netport_sid_slow function https://asciinema.org/a/186080

Slide 25

Slide 25 text

Что можно реализовать на этой основе (5) Обратный перенос изменений LIVE DEMONSTRATION SELinux Callgraph sel_netport_sid_slow function https://asciinema.org/a/186083

Slide 26

Slide 26 text

Чего нельзя реализовать на этой основе Syntactical Grep && Semantic Patch Использование макроса ARRAY_SIZE Аллоцирование очищенного буфера Coccinelle: http://coccinelle.lip6.fr/ Pfff: https://github.com/facebook/pfff

Slide 27

Slide 27 text

Сложности (1) • Сочетание макросов и кода на Си в глобальных объявлениях (нужно явно добавлять идентификаторы в глобальные переменные) #define GFS2_ATTR(name, mode, show, store) \ static struct gfs2_attr gfs2_attr_##name = \ __ATTR(name, mode, show, store) GFS2_ATTR(freeze, 0644, freeze_show, freeze_store);

Slide 28

Slide 28 text

Сложности (1) • Сочетание макросов и кода на Си в глобальных объявлениях (нужно явно добавлять идентификаторы в глобальные переменные) #define GFS2_ATTR(name, mode, show, store) \ static struct gfs2_attr gfs2_attr_##name = \ __ATTR(name, mode, show, store) GFS2_ATTR(freeze, 0644, freeze_show, freeze_store);

Slide 29

Slide 29 text

Сложности (2) • Сочетание макросов и кода на Си в глобальных объявлениях (нужно явно добавлять идентификаторы в глобальные переменные) #define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \ static int func(const char *name, int name_len, \ unsigned int d_type) \ {...} FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)

Slide 30

Slide 30 text

Сложности (3) • Static функции одинаковыми именами в разных *.c файлах • Какое-нибудь хитрое использование препроцессора … International Obfuscated C Code Contest https://www.ioccc.org/ • Но: Код, который проходит сертификацию, должен быть читаемым…

Slide 31

Slide 31 text

Почему Perl? Гибкость языка Practical Extraction and Report Language • Atomic Patterns: qr/(?>$fret)/ • Recursive Patterns: qr'(?>(?\{(?:(?>[^\{\}]+)|(?& fbody))*\}))' • "Possessive" Quantifiers (*+,++,...): m/^${h}*+\Ktypedef/ • Conditional Expression: qr/(?($condition)$yes|$no)/ • Look-Ahead, Look-Behind: qr/\b(?!fmt)${varname}\b${ptr}/ • Branch Reset: qr/(?|$ids)/ • (*PRUNE), (*SKIP), (*FAIL): qr/(?:;|$fbody(*SKIP)(*FAIL))/ …

Slide 32

Slide 32 text

Почему Perl? Модули Practical Extraction and Report Language • Graph, Hash::Ordered – построение графа, управление зависимостями • Graph::Directed, Graph::Reader::Dot, Graph::Writer::Dot – работа с графами, генерация dot файлов для graphviz • Algorithm::Diff – для возврата изменений в исходный код • Class::CSV, Excel::Writer::XLSL, Text::ANSITable – генерация отчётов • Module::Loader – реализация плагинов • Storable – кеширование графа • Starman, Plack, DBD::SQLite – web версия

Slide 33

Slide 33 text

Инструменты • Forge: https://forge.ispras.ru/projects/astraver-utils/repository GitHub: https://github.com/evdenis/spec-utils • Docker для быстрого развертывания демонстрации web карты • Интеграция с travis-ci, coveralls, kritika.io • SLOC: 8617 (according to SLOCCount) • Тестирование на модулях ядра (ramfs, sysfs …): • Каждая функция выводится в отдельный файл со своими зависимостями • Проверяется компилируемость

Slide 34

Slide 34 text

Где применяются инструменты • Разработка формальных спецификаций для драйверов на языке ACSL (специальные комментарии) • Интегрирован в цикл проверки кода и спецификаций (buildbot) • Используется для предоставления отчётов в сертифицирующие органы • Проект AstraVer: http://www.ispras.ru/technologies/astraver_toolset/ • “Моделирование и верификация политик безопасности управления доступом в операционных системах” П.Н. Девянин et al. http://www.ispras.ru/publications/2018/security_policy_modeling_and_ve rification/

Slide 35

Slide 35 text

Вопросы?