Обходной путь для предупреждения Spectre MSVC C5040

MSVC только что выпустил обновление, в которое добавлено новое предупреждение о некотором коде, который компилятор вставит, чтобы смягчить (по-видимому, небольшой кусочек) Specter:

https://blogs.msdn.microsoft.com/vcblog/2018/01/15/spectre-mitigations-in-msvc/

Вот небольшой MCVE, полученный из их примера "проблемного" кода:

#include <stdio.h>

int main(int argc, char *argv) {
    unsigned char array1[1] = {0};
    int array1_length = 1;
    unsigned char array2[1] = {99};
    int untrusted_index = 0; /* in this MCVE, I trust it, compiler doesn't */
    for (; untrusted_index < array1_length; ++untrusted_index) {
        unsigned char value = array1[untrusted_index];
        unsigned char value2 = array2[value * 64];
        printf("Picked value %d\n", value2);
    }
    return 0;
}

"В приведенном выше примере код выполняет проверку границ массива, чтобы убедиться, что untrusted_index меньше длины массива 1. Это необходимо для того, чтобы программа не читала за пределами массива. Хотя это выглядит как звук как написано, он не учитывает микроархитектурное поведение процессора, связанное со спекулятивным исполнением ".

Итак, теперь вы получаете предупреждение:

Предупреждение C5045: Компилятор вставит смягчение Spectre для загрузки памяти, если указан ключ /Qspectre

Это способ сказать вам, что этот код может оказаться медленнее, чем вам хотелось бы (если он был скомпилирован /Qspectre), потому что он собирается добавить некоторые дополнительные средства защиты.

Поскольку кажется, что вы не можете принимать что-либо как должное, я с подозрением отношусь к изменениям, которые "просто убирают предупреждение". Например, изменение untrusted_index < array1_length в untrusted_index != array1_length кажется, делает это для конкретного экземпляра кода MCVE, который я привожу здесь. Но это жизнеспособный патч или их предупреждение просто неполное - и в следующем обновлении он тоже будет жаловаться на это?

Я знаю, что могу отключить предупреждение с помощью /wd5040 или другим способом. Но я заинтересован в том, чтобы убедиться, что если код скомпилирован с /Qspectre, что замедлений нет, и что нет предупреждений, если он не скомпилирован с /Qspectre. Я не хочу ходить, касаясь смены файлов < в != в условиях цикла - или как угодно - если это просто отток.

Таким образом, более серьезный вопрос будет, если существуют законные шаблоны обхода, которые являются такими основными, почему нет некоторых упоминаний о них? Например, описываемый мной случай - это итерация, в которой я контролирую индекс, и мне не нужно беспокоиться об этом из "ненадежного источника". Все же я получил предупреждение, и переключаясь с < в != заставил это уйти. Зачем? Должно ли это иметь?

2 ответа

Из самой статьи:

Важно отметить, что существуют ограничения для анализа, который MSVC и компиляторы в целом могут выполнять при попытке идентифицировать экземпляры варианта 1. Таким образом, нет никакой гарантии, что все возможные экземпляры варианта 1 будут инструментированы в /Qspectre.

Вероятно, вы столкнулись с одним из случаев, когда текущая реализация / Qspectre не будет уменьшать уязвимость по конструкции. Это разумно, потому что чрезмерное использование LFENCE может значительно снизить производительность. Смягчение каждого отдельного экземпляра варианта 1, присутствующего в коде, слишком дорого, чтобы полностью выполнить его в программном обеспечении (используя LFENCE).

В комментариях кто-то спросил:

Можете ли вы охарактеризовать для разработчиков ограничения MSVC и что еще нужно сделать разработчикам, чтобы защитить себя от "варианта 1"?

Автор статьи ответил:

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

Поэтому Microsoft, похоже, не хочет раскрывать, какие именно экземпляры варианта 1 не будут смягчены /Qspectre.

Если вам не нужно предупреждение, просто используйте #pragma warning(disable:5040) или отключите его на странице свойств проекта.

И обратите внимание, что предложенного вами изменения на "untrusted_index!= Array1_length" недостаточно, так как весь диапазон больше размера, доступного для злоупотребления.

Помните, что эта диагностика просто говорит вам, что компилятор будет делать что-то другое, чем раньше, с включенным смягчением спектра, это не значит, что вам обязательно нужно что- то делать с кодом.

Другие вопросы по тегам