ADG Оставить заявку
Блог Информационная безопасность 5 мин чтения

Retpoline в ядре Linux против Spectre v2: замеряем деградацию на гипервизорах

Retpoline-патчи ядра Linux вошли в дистрибутивы в 2018 году. Обновили гипервизоры и замерили: 3-5% деградации на вычислительных задачах - приемлемая цена за закрытие Spectre v2.

Контекст момента

Retpoline-патчи ядра Linux против Spectre v2 вошли в основные дистрибутивы в 2018 году и стали базовым способом программного митигейшна CVE-2017-5715

В январе мы патчили ядра против Meltdown и первый раз смотрели на Spectre v2. Тогда история закончилась на полуслове: микрокод Intel для Broadwell/Haswell оказался нестабильным, катить его было нельзя, а retpoline упоминался как частичная мера - «помогает, но не закрывает всё». Прошло полгода. За это время retpoline осел в апстриме ядра Linux (с версии 4.15), прошёл в стабильные ветки и добрался до дистрибутивных ядер - RHEL 7, Ubuntu 16.04 LTS, Debian 9. Настало время обновить гипервизоры и посмотреть что получилось.

Что такое retpoline и почему это не просто патч компилятора

Spectre v2 (CVE-2017-5715) атакует branch predictor - блок предсказания переходов в процессоре. Классическое решение через IBRS (Indirect Branch Restricted Speculation) требует микрокода и имеет ощутимый overhead из-за того, что при каждом входе в ядро нужно запрещать непрямые переходы. На Broadwell/Haswell с тем самым нестабильным микрокодом эта история зависла.

Retpoline - компиляторный трюк, предложенный Google. Суть: каждый непрямой переход (indirect call, indirect jmp) заменяется конструкцией, которая заставляет предиктор всегда «думать» что переход пойдёт в бесконечный цикл - и никогда не делает спекулятивный переход туда, куда хочет атакующий. Работает без изменения микрокода. Ядро Linux перекомпилируется с retpoline-поддержкой, и гостевые VM получают защиту через гипервизор.

Проверить что retpoline активен на Linux:

cat /sys/devices/system/cpu/vulnerabilities/spectre_v2

Ожидаемый ответ на свежем ядре с retpoline выглядит примерно так:

Mitigation: Full generic retpoline

Если видите Vulnerable - ядро устаревшее или retpoline не собран.

Как обновляли гипервизоры

У нас несколько KVM-кластеров под разные задачи клиентов. Гипервизоры на Ubuntu 16.04 HWE и RHEL 7. На Ubuntu 16.04 retpoline-ядро пришло с HWE-стеком версии 4.15 (пакет linux-generic-hwe-16.04). На RHEL 7 - backport в 3.10 с соответствующими CVE-патчами.

Порядок обновления стандартный для KVM-инфраструктуры:

  • Сначала один хост в каждом кластере. Мигрируем VM на соседние ноды, обновляем ядро, перезагружаем, проверяем что VM поднялись, смотрим на dmesg - нет ли проблем с IOMMU или сетевыми драйверами.
  • Затем остальные хосты по одному. Без спешки, с окном между перезагрузками.
  • Проверка через Ansible. Инвентаризируем версии ядра по всем хостам после обновления, убеждаемся что нигде не осталось старых версий.

Неожиданных проблем не было. На паре хостов с нестандартными сетевыми картами пришлось поднять версию драйвера - не связано с retpoline, просто HWE-ядро новее.

Деградация производительности: мерим на гостевых VM

Это был главный вопрос - и он предметный. Retpoline защищает гипервизор и гостевые VM, но не бесплатно. Мы прогнали несколько синтетических тестов на гостевых VM до и после обновления хоста.

Что использовали:

  • sysbench CPU - нагрузка чистыми вычислениями, минимум syscall'ов
  • sysbench fileio - дисковая нагрузка с большим количеством системных вызовов
  • pgbench на PostgreSQL 10 - OLTP-нагрузка, умеренное количество syscall'ов

Наблюдения:

sysbench CPU - деградация минимальная, укладывается в погрешность измерения. Retpoline здесь почти не виден: вычислительные задачи без активного ввода-вывода не делают много непрямых переходов через границу ядра.

sysbench fileio - вот тут разница заметна. На тесте с random reads/writes просадка была в диапазоне 3-5% по throughput. Дисковые операции - это системные вызовы, а системные вызовы - это та самая граница, которую retpoline патчирует.

pgbench - похоже на fileio, 3-5% на транзакционной нагрузке с короткими транзакциями. Тяжёлые аналитические запросы просаживаются меньше - те же 1-2% в районе погрешности.

Итого: на вычислительных задачах - практически нет потерь, на IO-интенсивных - 3-5%. Это сопоставимо с тем, что публиковали другие команды в сети. Цифры не сенсационные и не катастрофические.

Что это значит для гостевых VM на KVM

Важный момент: retpoline на гипервизоре - это защита самого гипервизора и изоляция между VM. Гостевая VM с устаревшим ядром внутри себя остаётся уязвимой - retpoline хоста не просачивается внутрь гостя автоматически. Обновлять ядра нужно на всех уровнях: гипервизор и каждая гостевая VM отдельно.

Для клиентских VM под нашим управлением - обновляем через тот же Ansible-пайплайн что и хосты, только по другому инвентарю. Для VM, где у клиента свой доступ и своя ответственность за ОС внутри - информируем и даём инструкцию.

Это та же логика что и при Meltdown: патч ядра закрывает один уровень, но полная защита - это стек изменений на нескольких уровнях одновременно.

Где мы сейчас

Все гипервизоры под нашим управлением обновлены, retpoline активен. По Spectre v2 картина такая: programmatic-митигейшн через retpoline работает, микрокодный IBRS для Broadwell/Haswell Intel в итоге выпустил revised patch, но мы к нему отнеслись осторожно - катим только на платформах, где updated microcode прошёл через вендора или дистрибутив с нормальным QA.

3-5% деградации на IO - приемлемо. Это не повод откладывать обновление и жить с открытой CVE-2017-5715. Организации, у которых гипервизоры до сих пор не обновлены по соображениям «а вдруг производительность упадёт» - рискуют больше, чем теряют.

Если хотите понять реальную картину уязвимостей своей инфраструктуры - аудит как раз про это: инвентаризация, проверка статуса митигейшнов, оценка рисков по слоям.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.