Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical Language for Extracting Data from Source Codes and Preparing Them for Analysis

Practical Language for Extracting Data from Source Codes and Preparing Them for Analysis

Talk at Yandex Perl Meetup (06 June 2018). The presentation is about how tools written in Perl can be used for verification of Linux kernel modules. Various types of source code transformations with style preservation, interactive callgraphs, reports with various complexity metrics. How we use the tools in the AstraVer project for writing formal specifications (ACSL) on code and how it helps us with regulatory certification. The tools: https://github.com/evdenis/spec-utils

Denis

June 06, 2018
Tweet

More Decks by Denis

Other Decks in Programming

Transcript

  1. Практический язык для извлечения данных из исходных кодов и подготовки

    их к анализу 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
  2. О Докладчике Разработчик ИСП РАН (ispras.ru). Отдел технологий программирования. Аспирант

    НИУ ВШЭ (hse.ru). Верификация программного обеспечения, разработка формальных спецификаций, инструментов статического и динамического анализа для ядра Linux. GitHub: https://github.com/evdenis KeyBase: https://keybase.io/efremov
  3. О чем речь? • Стандарты • 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 "Методы и средства обеспечения безопасности. Критерии оценки безопасности информационных технологий" • Сертификация ПО на соответствие стандартам • Исходные коды • Формальная, полу-формальная, неформальная документация • Тесты, спецификации • Описание цикла разработки • Программы, которые помогают готовить сертификационный пакет
  4. Что важно для анализа кода программистом? • Форматирование • Документация

    • «Понятность» • Инструменты навигации • Подготовка кода для запуска тяжеловесных статических инструментов (Frama-C, VCC, Isabelle, CPAChecker, …) • Возможность менять подготовленный код с возвратом «назад» • Карты кода
  5. Как работают инструменты с Си • Запуск препроцессора • Убираются

    комментарии • Раскрываются макросы • Запуск компилятора до стадии построения Control Flow Graph (CFG) • Полная потеря форматирования • Исходные код на CFG уровне слишком сильно отличается от оригинального
  6. Существующие инструменты: facebook/pfff • Инструменты для анализа кода, его визуализации

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

    пропустить конструкцию, которую не удается распознать? • Что будет если CFG не точно построить (например, будут лишние зависимости)? • Что будет если сложность кода и его зависимости не совсем точно посчитаются? • Возможно ли запустить инструменты на «неполном» наборе кода?
  8. 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 )};
  9. 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]; }
  10. Общая схема работы инструмента Подготовка • Объединение исходных кодов в

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

    Объединяются все *.c файлы • Include директивы выносятся на верхний уровень с сохранением порядка • Запускается препроцессор GCC • Без раскрытия макросов (флаг –fdirectives-only) • С учётом только директив условной компиляции и include • С сохранением комментариев (флаг –С)
  12. Алгоритм построения графа зависимостей (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; }
  13. Алгоритм построения графа зависимостей (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
  14. Алгоритм построения графа зависимостей (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); };
  15. Алгоритм построения графа зависимостей (5) • Создаётся глобальные хеш элементов

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

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

    графа вызовов (callgraph) Green – added Red – deleted Black – unchanged
  18. Что можно реализовать на этой основе (4) Вывод только отдельных

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

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

    LIVE DEMONSTRATION SELinux Callgraph sel_netport_sid_slow function https://asciinema.org/a/186083
  21. Чего нельзя реализовать на этой основе Syntactical Grep && Semantic

    Patch Использование макроса ARRAY_SIZE Аллоцирование очищенного буфера Coccinelle: http://coccinelle.lip6.fr/ Pfff: https://github.com/facebook/pfff
  22. Сложности (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);
  23. Сложности (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);
  24. Сложности (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)
  25. Сложности (3) • Static функции одинаковыми именами в разных *.c

    файлах • Какое-нибудь хитрое использование препроцессора … International Obfuscated C Code Contest https://www.ioccc.org/ • Но: Код, который проходит сертификацию, должен быть читаемым…
  26. Почему Perl? Гибкость языка Practical Extraction and Report Language •

    Atomic Patterns: qr/(?>$fret)/ • Recursive Patterns: qr'(?>(?<fbody>\{(?:(?>[^\{\}]+)|(?& 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))/ …
  27. Почему 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 версия
  28. Инструменты • 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 …): • Каждая функция выводится в отдельный файл со своими зависимостями • Проверяется компилируемость
  29. Где применяются инструменты • Разработка формальных спецификаций для драйверов на

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