Как смягчить призрак с помощью GCC и Clang (или LLVM в целом)
Microsoft добавил удобный /Qspectre
к их компилятору MSVC (хотя это, кажется, только (пытается) смягчить Spectre v1 в настоящее время), которое они будут обновлять с течением времени. Это очень хорошо с точки зрения пользователей, просто включите этот флаг, и вы получите самое последнее и лучшее средство защиты, которое они имеют в магазине.
С LLVM и GCC это выглядит немного по-другому. Я не думаю, что их смягчение официально выпущено еще.
LLVM должен получить -mretpoline
флаг компилятора, который смягчает Spectre v2 через батуты возврата для косвенных вызовов.
GCC, с другой стороны, имеет патчи, которые добавляют три параметра компилятора для смягчения Specter v2:
-mindirect-branch
это может быть установлено вthunk
, Насколько я понимаю, это создает ретполины для каждого косвенного вызова.-mfunction-return
это может быть установлено вthunk
, Я полагаю, что он использует эти retpolines для каждой функции возврата, что может быть необходимо для Skylake, потому что эти процессоры также могут предсказать результаты?-mindirect-branch-register
Это использует регистр вместо стека для хранения адреса косвенного вызова?
Так что я совсем запутался. Какая опция компилятора смягчает то, что и в каких сценариях они необходимы для приложения пользовательского пространства?
Это хорошая идея, чтобы вообще включить их? Будут ли они также генерировать эти ретполины, если они скомпилированы для архитектуры процессора, которая даже не имеет спекулятивного исполнения (например, микропроцессоры)?
Что насчет Призрака v1?
ОБНОВИТЬ:
Позвольте мне задать более точные вопросы:
- Мое понимание того, что параметры компилятора делают правильно?
- Применяются ли параметры GCC везде или только для процессоров со спекулятивным исполнением?
- Применяются ли параметры LLVM везде или только на процессорах с умозрительным исполнением?
- Что именно смягчают эти параметры (полностью ли они смягчают Spectre v2)?
- Давайте рассмотрим все остальное, что я задал, как дополнительные "бонусные" вопросы, которые полезно знать, но не обязательно для моего вопроса.
1 ответ
Мое понимание того, что параметры компилятора делают правильно?
Я думаю так.
Применяются ли параметры GCC везде или только для процессоров со спекулятивным исполнением?
Варианты пока специфичны для x86. Я не проверял, есть ли эквивалентные патчи ARM, но в любом случае эти параметры будут хотя бы частично зависеть от архитектуры процессора.
Я только посмотрел на некоторые из патчей, но это не похоже на дополнительные проверки во время выполнения. Скорее, выбор инструкций изменяется, чтобы сервер не испускал нежелательных косвенных переходов вообще, если заданы параметры.
Таким образом, опция не применяется к совершенно не связанным архитектурам, но не делается попытка выяснить, уязвим ли конкретный ЦП во время выполнения. Обратите внимание, что наиболее известные процессоры x86 продаются начиная с ок. Pentium Pro использует умозрительное исполнение.
Что именно смягчают эти параметры (полностью ли они смягчают Spectre v2)?
Главным образом они смягчают внедрение цели ветвления (Specter v2), гарантируя, что при соответствующем косвенном вызове не происходит спекуляция, контролируемая атакующим.
Retpolines достигают этого, используя инструкции возврата для перехода к целевому адресу, который использует другой предиктор ветвления, который в основном запоминает, откуда поступил последний вызов. Этим манипулирует сгенерированный код, который выполняет инструкцию вызова перед инструкцией возврата, что гарантирует, что предполагаемое выполнение попадет в тупик, поместив инструкцию mfence после вызова. Смотрите этот ответ для более подробной информации.
Внедрение в филиал является проблемой, поскольку, как объясняется в документе " Призрак" в разделе "5.1 Обсуждение", может быть много кода, сопоставленного злоумышленнику для использования. Обсуждение говорит о Windows, но я мог бы предположить, что должен быть некоторый код из разделяемых библиотек, сопоставленных также в Linux. Если адреса этого кода более рандомизированы, эксплуатация может быть более сложной, но я бы не стал рассчитывать на это без проверки. В частности, ядро Linux содержит много кода, который может быть использован злоумышленником с возможностью внедрения произвольных целей ветвления.
-mfunction-return
На первый взгляд кажется глупым защищать возврат, заменяя его более сложным возвратом, но согласно этому сообщению Дэвида Вудхауса, вариант был запрошен разработчиками ядра Linux, так как при недостаточном количестве запоминаемых адресов возврата (в основном скрытый стек) после стека вызовов) некоторые процессоры снова используют глобальный предиктор ветвления, которым может манипулировать злоумышленник. Таким образом, ваше объяснение было правильным. Согласно тому же сообщению, этот флаг не был сразу использован ядром Linux. Я предполагаю, что влияние на производительность будет значительным, так как отдача гораздо более распространена, чем в других косвенных ветвях, а специализированный прогноз доходности позволит достичь отличных показателей эффективности на практике.
-mindirect-branch-register
Я не совсем уверен, что -mindirect-branch-register
смягчает. По-видимому, он необходим в наборе тестов вместе с другими опциями, но я пока не смог найти объяснения. Также Xen использует эту опцию вместе с -mindirect-branch=thunk-extern
Это означает, что они сами пишут код thunk и не позволяют компилятору его сгенерировать. Вопреки моему первоначальному предположению, это не имеет ничего общего с потенциальной спекуляцией во время загрузки адреса, поскольку она предназначена для использования с ретполинами, которые предотвращают эту спекуляцию. В некоторых обсуждениях было упомянуто, что версия thunks, которые получают целевой адрес в стеке, а не в регистре, изначально имела конфликты с технологией Intel Control-flow Enforcement Technology (CET). Я полагаю, поскольку ретполины используют возвраты необычным образом, CET предотвратил скачки. Однако, согласно этому обсуждению, эти проблемы, по-видимому, были решены, и на машинах, которые поддерживают CET, доступны и другие меры по смягчению (IBRS_ALL), которые позволяют заменять повторы ретполина непрямыми скачками. Я предполагаю, что этот вариант сам по себе не очень поможет.
Обновление: Призрак Вариант 1
Недавно Чендлер Кэррут предложил, как смягчить Призрак V1 в LLVM. Эта работа еще не завершена, но еще не опубликована (по состоянию на март 2018 года). Основная идея состоит в том, чтобы замаскировать уязвимые адреса или загруженные значения на неправильно спроектированных путях, прежде чем их можно будет использовать с побочными эффектами.