Целостность потока управления (CFI) — это механизм безопасности, который запрещает вносить изменения в исходный граф потока управления скомпилированного двоичного файла, что значительно усложняет выполнение таких атак.
В Android 9 мы включили реализацию CFI в LLVM в большем количестве компонентов, а также в ядре. Системный CFI включен по умолчанию, но вам нужно включить CFI ядра.
CFI LLVM требует компиляции с Link-Time Optimization (LTO) . LTO сохраняет представление объектных файлов в битовом коде LLVM до момента компоновки, что позволяет компилятору лучше понять, какие оптимизации можно выполнить. Включение LTO уменьшает размер конечного двоичного файла и повышает производительность, но увеличивает время компиляции. При тестировании на Android сочетание LTO и CFI приводит к незначительным накладным расходам на размер кода и производительность; в нескольких случаях оба улучшились.
Дополнительные технические сведения о CFI и о том, как обрабатываются другие проверки прямого управления, см. в проектной документации LLVM .
Реализация
Патчи kCFI есть во всех поддерживаемых версиях ядра Android. Параметр CONFIG_CFI_CLANG
включает kCFI и установлен по умолчанию в GKI.
Исправление проблем
После включения обработайте любые ошибки несоответствия типов, которые могут существовать в их драйверах. Косвенный вызов функции через несовместимый указатель функции приводит к отключению CFI. При обнаружении сбоя CFI ядро выводит предупреждение, включающее в себя как вызванную функцию, так и трассировку стека, которая привела к сбою. Исправьте это, убедившись, что указатели функций всегда имеют тот же тип, что и вызываемая функция.
Чтобы помочь в отладке сбоев CFI, включите CONFIG_CFI_PERMISSIVE
, который выводит предупреждение, а не вызывает панику ядра. Разрешающий режим не должен использоваться в рабочей среде.
Проверка
В настоящее время нет теста CTS специально для CFI. Вместо этого убедитесь, что тесты CTS проходят с включенным CFI или без него, чтобы убедиться, что CFI не влияет на устройство.