Безопасный компилятор


Скачать сборник технологий

Безопасный компилятор

Документация и поддержка

Безопасный компилятор предотвращает появление уязвимостей в программе при выполнении агрессивных оптимизаций кода (например, в результате использования конструкций, проявляющих неопределённое поведение). Минимально ограничивает выполняемые оптимизации, что позволяет избежать значительного падения производительности по сравнению с полным отключением оптимизаций.

Особенности и преимущества

Разработаны два варианта безопасного компилятора, которые могут быть использованы в качестве замены открытых промышленных компиляторов GCC и Clang (LLVM):

  • SAFEC (на основе GCC);
  • Safelang (на основе Clang).

Оба компилятора выполняют требования к функциям безопасности из ГОСТ Р 71206-2024 «Защита информации. Разработка безопасного программного обеспечения. Безопасный компилятор языков C/C++. Общие требования».

SAFEC и Safelang – это:

  • Доработанные оптимизации компилятора для консервативной обработки конструкций с неопределённым поведением и безопасного доопределения семантики программы.
  • Принудительная инициализация неинициализированных автоматических переменных.
  • Выдача предупреждений компиляции при обнаружении конструкций с неопределенным поведением.
  • Добавление динамических проверок для отдельных классов конструкций в целях исключения появления неопределённого поведения по время работы программы.
  • Диверсификация генерируемого кода во время выполнения программы.
  • Отсутствие необходимости модифицировать исходный код и файлы системы сборки, что позволяет максимально упростить пользование компилятором.
  • Распределение функций безопасности по трём классам, определяющим компромисс между безопасностью генерируемого кода и его производительностью. Самый низкий класс – III, самый высокий – I.

SAFEC и Safelang осуществляют следующие действия:

Согласно III классу:

  • Предотвращение возникновения целочисленного переполнения, доступа к объектам через указатель несовместимого типа, разыменования нулевого указателя, замены функций ввода/вывода и работы с памятью стандартной библиотеки на эквивалентные машинные инструкции. Предотвращение перезаписи значений переменных автоматического класса памяти в результате вызова функций семейства longjmp (Safelang).
  • Обнаружение деления на ноль, некорректности битовых сдвигов, выхода за границы кадра стека, операций загрузки и/или записи в массив за пределами выделенной для него памяти. Обнаружение переменных автоматического класса памяти, которые могут храниться на машинном регистре при вызове функций семейства longjmp (SAFEC).

Согласно II классу:

  • Анализ аргументов битовых сдвигов; избыточности операций работы с памятью; выравнивания данных при работе с векторными инструкциями; адресной арифметики при оптимизациях, связанных с изменением порядка операций обращения к памяти.
  • Инициализация не инициализированных явно переменных автоматического класса памяти нулевыми значениями.
  • Остановка процесса трансляции при выдаче определённых предупреждений.

Согласно I классу:

  • Диверсификация машинного кода – уникальное распределение кода функций в памяти в ходе динамической компоновки программы или при выполнении статической компиляции. Инструмент диверсификации раньше был частью системы ИСП Обфускатор, а теперь интегрирован в безопасный компилятор.
  • Добавление в программу машинного кода, вызывающего её аварийный останов при обнаружении ситуаций с неопределённым поведением во время выполнения программы:

    1) Операции с целыми или вещественными типами:

    • загрузка небулевого значения в переменную булевого типа;
    • преобразование значений вещественной переменной, приводящее к целочисленному или вещественному переполнению;
    • операция сдвига, в которой величина сдвига отрицательна либо не меньше ширины типа сдвигаемого значения;
    • операция со знаковыми целыми переменными, результат которой не может быть представлен в нужном типе;
    • целочисленное деление или взятие остатка, в котором значение делителя равно нулю.

    2) Операции с указателями и массивами:

    • загрузка или запись по некорректно выравненному или нулевому указателю;
    • загрузка или запись в массив по адресу, находящемуся за пределами выделенной для него памяти;
    • передача нулевого указателя в качестве параметра функции, помеченного атрибутом nonnull;
    • выполнение операции адресной арифметики, приводящей к целочисленному переполнению;
    • возврат нулевого значения из функции, объявление которой содержит атрибут returns_nonnull;
    • выделение в автоматической памяти массива переменной длины с некорректным размером.

    3) Операции с функциями:

    • вызов по указателю функции, тип которой не соответствует объявленному типу указателя;
    • выход из функции, имеющей возвращаемое значение, без выполнения операции возврата значения;
    • вызов встроенной функции компилятора с недопустимыми значениями аргументов;
    • выполнение точки в программе, отмеченной как недостижимая.

Диверсификация машинного кода (по I классу безопасности)

Диверсификация – это защита от массовой эксплуатации уязвимостей, возникающих в результате ошибок или закладок. Если злоумышленник смог атаковать одно из устройств с одинаковым ПО, остальные останутся под защитой благодаря внесённым в код изменениям.

Инструмент диверсификации:

  • Позволяет настраивать баланс между степенью запутывания и уровнем производительности (если также требуется защита от обратного анализа). Минимальное замедление работы — в 1,2 раза, максимальное — в 8 раз.
  • Применяет оригинальный метод обеспечения целостности потока управления (CFI), который успешно противодействует большинству атак с повторным использованием кода (ROP, JOP, ret-to-plt и др.). Среднее замедление диверсификации из компилятора SAFEC на наборе тестов SPEC CPU2006 составляет около 2%, что заметно ниже, чем у традиционных методов.
  • Обеспечивает бесконфликтное совмещение с другими средствами защиты ПО (в том числе с системным механизмом ASLR).
  • Реализует два метода – динамическую и статическую диверсификацию.
    • Динамическая диверсификация кода гарантирует один и тот же код на всех устройствах (например, в случае обязательной сертификации) и позволяет перемещать до 98% кода с небольшим увеличением его объёма и ухудшением производительности примерно на 1,5%. Ее преимущества по сравнению с аналогами:
      • перемешивание до функции (в отличие от технологий ASLR и Pagerando, которые перемещают только крупные блоки кода);
      • перемешивание функций во всей системе, кроме ядра, а также отсутствие конфликта с антивирусами (преимущества перед аналогичной технологией Selfrando, разработанной для Tor Browser).
    • Статическая диверсификация кода по заданному ключу генерирует при компиляции уникальный исполняемый файл. Ее преимущества:
      • не увеличивается объём бинарного кода (в частности, важно для интернета вещей);
      • ухудшение производительности практически нулевое;
      • благодаря работе внутри компилятора, а не постфактум в компоновщике, можно применять расширенный набор диверсифицирующих преобразований и более гибко его настраивать.

Для кого предназначены SAFEC и Safelang?

  • Разработчики ОС.
  • Компании, разрабатывающие ПО с высокой степенью надёжности и безопасности.

Опыт внедрения

Безопасный компилятор поставляется в ряд российских компаний и организаций. Инструмент диверсификации как отдельный компонент на базе компилятора GCC внедрен в ОС «Циркон», которую используют МИД и Пограничная служба ФСБ России.

Поддерживаемые ОС

  • Целевые ОС: семейство Linux, для SAFEC также Windows (MinGW).
  • Целевые процессорные архитектуры: x86 (32/64), armv7, arm64, RISC-V 64.

Схема работы

Safecomp

Документация

Сайт безопасного компилятора SAFEC

Разработчик/участник

Компиляторные технологии

Перейти к списку всех технологий