Я не думаю, что повторы загрузки с RS причастны к атакам RIDL. Поэтому вместо того, чтобы объяснять, что такое повторы нагрузки (ответ @ Peter является хорошей отправной точкой для этого), я расскажу о том, что, по моему мнению, происходит, основываясь на моем понимании информации, представленной в документе RIDL, Intel анализ этих уязвимостей и соответствующих патентов. .
Буферы заполнения строк - это аппаратные структуры в кэше L1D, используемые для хранения запросов памяти, которые отсутствуют в кэше, и запросов ввода-вывода до тех пор, пока они не будут обработаны. Кэшируемый запрос обслуживается, когда требуемая строка кэша заполняется в массив данных L1D. Запись с объединением записи обслуживается, когда возникает какое-либо из условий удаления буфера объединения записи (как описано в руководстве). Запрос UC или ввода-вывода обслуживается, когда он отправляется в кэш L2 (что происходит при первой возможности).
См. Рисунок 4 в документе RIDL. Эксперимент, использованный для получения этих результатов, работает следующим образом:
- Поток-жертва записывает известное значение в одну ячейку памяти. Тип ячейки памяти - WB, WT, WC или UC.
- Поток-жертва циклически читает ту же самую ячейку памяти. За каждой операцией загрузки следует
MFENCE
и необязательный CLFLUSH
. Из статьи мне неясен порядок CLFLUSH
по отношению к двум другим инструкциям, но, вероятно, это не имеет значения. MFENCE
сериализует операцию очистки строки кэша, чтобы увидеть, что происходит, когда каждая загрузка отсутствует в кэше. Кроме того, MFENCE
уменьшает конкуренцию между двумя логическими ядрами на портах L1D, что увеличивает пропускную способность злоумышленника.
- Поток злоумышленника, работающий на логическом ядре-близнеце, выполняет код, показанный в листинге 1, в цикле. Адрес, используемый в строке 6, может быть любым. Единственное, что имеет значение, это то, что загрузка в строке 6 либо дает сбой, либо вызывает обход страницы, требующий помощи микрокода (для установки бита доступа в записи таблицы страниц). Обход страницы также требует использования LFB, и большинство LFB совместно используются логическими ядрами.
Мне не ясно, что представляет собой ось Y на рисунке 4. Насколько я понимаю, он представляет собой количество строк из скрытого канала, которые были извлечены в иерархию кеша (строка 10) в секунду, где индекс строки в массиве равен значению, записанному жертвой.
Если ячейка памяти относится к типу WB, когда поток-жертва записывает известное значение в эту ячейку памяти, строка будет заполнена в кэш L1D. Если ячейка памяти относится к типу WT, когда поток-жертва записывает известное значение в эту ячейку памяти, строка не будет заполнена в кэш L1D. Однако при первом чтении из строки он будет заполнен. Таким образом, в обоих случаях и без CLFLUSH
большинство загрузок из потока-жертвы попадут в кеш.
Когда строка кэша для запроса загрузки достигает кеша L1D, она сначала записывается в LFB, выделенный для запроса. Запрошенная часть строки кэша может быть напрямую передана в буфер загрузки из LFB, не дожидаясь заполнения строки в кэше. Согласно описанию уязвимости MFBDS, в определенных ситуациях устаревшие данные из предыдущих запросов могут быть перенаправлены в буфер загрузки, чтобы удовлетворить нагрузку uop. В случаях WB и WT (без сброса) данные жертвы записываются не более чем в 2 разных LFB. Переход страницы из потока злоумышленника может легко перезаписать данные жертвы в LFB, после чего эти данные никогда не будут найдены там потоком злоумышленника. Все запросы загрузки, попадающие в кэш L1D, не проходят через LFB; для них есть отдельный путь, который мультиплексируется с путем от LFB. Тем не менее, есть некоторые случаи, когда устаревшие данные (шум) от LFB спекулятивно перенаправляются в логическое ядро злоумышленника, которое, вероятно, происходит из обхода страниц (и, возможно, обработчиков прерываний и аппаратных программ предварительной выборки).
Интересно отметить, что частота пересылки устаревших данных в случаях WB и WT намного ниже, чем во всех других случаях. Это можно объяснить тем, что пропускная способность жертвы в этих случаях намного выше, и эксперимент может закончиться раньше.
Во всех остальных случаях (WC, UC и все типы с промывкой) каждая загрузка отсутствует в кэше, и данные должны быть извлечены из основной памяти в буфер загрузки через LFB. Происходит следующая последовательность событий:
- Доступы от жертвы попадают в TLB, потому что они относятся к одной и той же действительной виртуальной странице. Физический адрес получается из TLB и предоставляется L1D, который выделяет LFB для запроса (из-за промаха), а физический адрес записывается в LFB вместе с другой информацией, описывающей запрос загрузки. На данный момент запрос от жертвы ожидает обработки в LFB. Поскольку жертва выполняет
MFENCE
после каждой загрузки, в LFB может быть не более одной невыполненной нагрузки в любом заданном цикле от жертвы.
- Злоумышленник, работающий на логическом ядре-близнеце, отправляет запрос загрузки на L1D и TLB. Каждая загрузка выполняется на несопоставленную пользовательскую страницу, поэтому это вызовет ошибку. Когда он отсутствует в TLB, MMU сообщает буферу загрузки, что загрузка должна быть заблокирована до завершения трансляции адреса. Согласно параграфу 26 патента и другим патентам Intel, именно так обрабатываются промахи TLB. Преобразование адреса еще продолжается, загрузка заблокирована.
- Запрос на загрузку от жертвы получает свою строку кэша, которая записывается в LFB, покрытый слоем загрузки. Часть строки, запрошенная загрузкой, пересылается в MOB, и в то же время строка записывается в кэш L1D. После этого с LFB можно снять покрытие, но ни одно из полей не очищается (кроме поля, которое указывает, что он свободен). В частности, данные все еще находятся в LFB. Затем жертва отправляет еще один запрос на загрузку, который также не попадает в кеш либо потому, что он не кэшируется, либо потому, что строка кеша была очищена.
- Процесс трансляции адресов загрузки злоумышленника завершается. MMU определяет, что необходимо вызвать ошибку, потому что физическая страница отсутствует. Однако неисправность не возникает до тех пор, пока нагрузка не выйдет из строя (когда она достигнет верха ROB). Недействительные переводы не кэшируются в MMU на процессорах Intel. MMU по-прежнему должен сообщить MOB, что преобразование завершено, и в этом случае устанавливает код ошибки в соответствующей записи ROB. Кажется, что когда ROB видит, что один из мопов имеет действительный код ошибки / помощи, он отключает все проверки, связанные с размерами и адресами этого мупа (и, возможно, всех последующих мопов в ROB). Эти проверки больше не имеют значения. Предположительно, отключение этих проверок экономит динамическое потребление энергии. Логика вывода из эксплуатации знает, что, когда нагрузка вот-вот спадет, неисправность все равно возникнет. В то же время, когда MOB информируется о завершении перевода, он, как обычно, воспроизводит нагрузку злоумышленника. Однако на этот раз в кэш L1D предоставляется недопустимый физический адрес. Обычно физический адрес необходимо сравнивать со всеми ожидающими в LFB запросами от одного и того же логического ядра, чтобы гарантировать, что логическое ядро видит самые последние значения. Это делается до или параллельно с поиском кеша L1D. Физический адрес на самом деле не имеет значения, потому что логика сравнения отключена. Однако результаты всех сравнений ведут себя так, как будто результат указывает на успех. Если есть хотя бы один выделенный LFB, физический адрес будет соответствовать некоторому выделенному LFB. Поскольку есть невыполненный запрос от жертвы и поскольку секрет жертвы, возможно, уже был записан в том же LFB из предыдущих запросов, та же часть строки кэша, которая технически содержит устаревшие данные, и в этом случае (устаревшие данные - это секрет), будет перенаправлен злоумышленнику. Обратите внимание, что злоумышленник может контролировать смещение в строке кэша и количество байтов, которые нужно получить, но не может контролировать, какой LFB. Размер строки кэша составляет 64 байта, поэтому только 6 младших битов виртуального адреса нагрузки злоумышленника имеют значение вместе с размером нагрузки. Затем злоумышленник использует данные для индексации в своем массиве, чтобы раскрыть секрет, используя атаку по боковому каналу кеша. Это поведение также объясняет MSBDS, где, по-видимому, отключены проверки размера данных и STD uop (т. Е. Проверки проходят тривиально).
- Позже неисправная / вспомогательная нагрузка достигает вершины ROB. Нагрузка не снимается, и трубопровод промывается. В случае неисправной нагрузки возникает неисправность. В случае вспомогательной загрузки выполнение перезапускается с той же инструкции загрузки, но с помощью установки требуемых флагов в структурах подкачки.
- Эти шаги повторяются. Но злоумышленник не всегда может раскрыть секрет жертвы. Как видите, может случиться так, что запрос загрузки от злоумышленника попадет в выделенную запись LFB, содержащую секрет. LFB, выделенные для обходов страниц и аппаратной предварительной выборки, могут затруднить выполнение успешной атаки.
Если загрузка злоумышленника не сработала / не помогла, LFB получат действительный физический адрес от MMU, и будут выполнены все необходимые проверки на правильность. Вот почему нагрузка должна отказывать / помогать.
Следующая цитата из статьи обсуждает, как выполнить атаку RIDL в том же потоке:
мы выполняем атаку RIDL без SMT, записывая значения в наш собственный поток и наблюдая за значениями, которые мы утекаем из того же потока. На рисунке 3 показано, что если мы не записываем значения («без жертвы»), мы утекаем только нули, но когда жертва и злоумышленник работают в одном аппаратном потоке (например, в песочнице), мы утекаем секретное значение почти во всех случаях. .
Я думаю, что в этом эксперименте нет изменений уровня привилегий. Жертва и злоумышленник работают в одном потоке ОС на одном аппаратном потоке. При возврате от жертвы к злоумышленнику в LFB все еще могут быть некоторые невыполненные запросы (особенно из магазинов). Обратите внимание, что в статье RIDL KPTI включен во всех экспериментах (в отличие от статьи Fallout).
В дополнение к утечке данных из LFB, MLPDS показывает, что данные также могут быть утечкой из буферов порта загрузки. К ним относятся буферы с разделением строк и буферы, используемые для нагрузок размером более 8 байтов (которые, я думаю, необходимы, когда размер uop загрузки больше, чем размер порта загрузки, например, AVX 256b на SnB / IvB которые занимают порт на 2 цикла).
Случай WB (без промывки) на Рисунке 5 также интересен. В этом эксперименте поток жертвы записывает 4 разных значения в 4 разные строки кэша вместо чтения из одной и той же строки кэша. На рисунке показано, что в случае WB злоумышленнику попадают только данные, записанные в последнюю строку кэша. Объяснение может зависеть от того, отличаются ли строки кэша на разных итерациях цикла, что, к сожалению, не ясно в статье. В документе говорится:
Для WB без сброса есть сигнал только для последней строки кэша, который предполагает, что ЦП выполняет объединение записи в одной записи LFB перед сохранением данных в кэше.
Как можно объединить записи в разные строки кэша в одном LFB перед сохранением данных в кеше? В этом нет никакого смысла. LFB может содержать одну строку кэша и один физический адрес. Так совмещать записи просто невозможно. Что может происходить, так это то, что записи WB записываются в LFB, выделенные для их запросов RFO. Когда недопустимый физический адрес передается в LFB для сравнения, данные всегда могут быть предоставлены из LFB, который был назначен последним. Это могло бы объяснить, почему утекает только значение, записанное четвертым хранилищем.
Для получения информации о смягчении последствий MDS см .: Что представляют собой новые MDS-атаки и как их уменьшить?. В моем ответе обсуждаются только меры по снижению рисков, основанные на обновлении микрокода Intel (не очень интересные «программные последовательности»).
На следующем рисунке показаны уязвимые структуры, использующие спекуляцию данными.
![введите здесь описание изображения](https://i.stack.imgur.com/XsWIn.png)
person
Hadi Brais
schedule
18.05.2019