Целостность потока управления (CFI) — это механизм безопасности, который запрещает внесение изменений в исходный граф потока управления скомпилированного бинарного файла, что значительно затрудняет проведение подобных атак.
Начиная с Android 9, вы можете включить CFI в ядре.
В ядре Linux существовали две разные реализации CFI:
- Для Linux 6.0 и ниже используется Clang CFI, который основан на Clang LTO.
- для Linux 6.1 и выше, Clang KCFI
Для работы Clang CFI требуется компиляция с оптимизацией на этапе компоновки (LTO) . LTO сохраняет представление объектных файлов в виде битового кода LLVM до момента компоновки, что позволяет компилятору лучше понимать, какие оптимизации могут быть выполнены. В ходе тестирования на Android комбинация LTO и CFI привела к незначительному увеличению размера кода и производительности. Однако включение LTO значительно увеличивает время сборки ядра.
Clang KCFI не требует LTO, поэтому более новые ядра Android получают преимущества CFI без дополнительных затрат времени на сборку, связанных с LTO.
Выполнение
Управление CFI осуществляется с помощью опции CONFIG_CFI_CLANG , которая включает либо Clang CFI, либо Clang KCFI.
Более подробную техническую информацию о CFI и о том, как обрабатываются другие проверки прямого управления, см. в документации по проектированию LLVM . Там KCFI обозначается как -fsanitize=kcfi .
Поиск неисправностей
После включения необходимо устранить любые ошибки несоответствия типов, которые могут возникнуть с драйверами. Косвенный вызов функции через несовместимый указатель на функцию приводит к сбою CFI. При обнаружении ошибки CFI ядро выводит предупреждение, содержащее как вызываемую функцию, так и трассировку стека, приведшую к сбою. Исправьте это, убедившись, что указатели на функции всегда имеют тот же тип, что и вызываемая функция.
Для облегчения отладки сбоев CFI включите CONFIG_CFI_PERMISSIVE , который выводит предупреждение вместо вызова ошибки ядра. Разрешительный режим не должен использоваться в производственной среде.
Валидация
В настоящее время нет специальных тестов CTS для CFI. Вместо этого убедитесь, что тесты CTS проходят успешно как с включенным, так и с выключенным CFI, чтобы проверить, не влияет ли CFI на работу устройства.