Meltdown для самых маленьких

TJournal

Коротко о природе одной из половин Чипокалипсиса — без всякого кода.

Поделиться

В избранное

В избранном

Недавно открытые уязвимости в процессорах на слуху уже почти у каждого, даже отдаленного от IT-темы человека. Однако далеко не все понимают, как работают эти уязвимости, а объяснения на российских и зарубежных сайтах в основном нацелены на подготовленную аудиторию. Я же постараюсь совсем просто объяснить, как работает уязвимость известная как Meltdown.

Если вы не пугаетесь терминов и примерно знакомы с программированием, почитайте эту статью — там всё подробнее и профессиональнее.

Сразу попрошу знающих людей не относиться излишне критично к примерам. Автор в курсе, что реальные процессы работают не совсем так, как они описаны в этом тексте. Я опустил всё, что усложняет понимание, ничего не исказив и оставив возможность спроецировать эту модель на реальные алгоритмы работы процессоров.

Итак, уязвимость Meltdown нарушает одну условность, на которую полагаются все разработчики и администраторы ПО: центральный процессор (ЦП) полностью изолирует друг от друга выполняемые на нем программы. Этот принцип — фундамент всей информационной безопасности.

В используемой большинством компьютеров архитектуре x86 защищённый режим существует ещё с 80-х годов. Первой доработанной реализацией этой «фишки» мог похвастаться легендарный процессор Intel 80386 (i386).

Обычно в ЦП встроен блок управления памятью (MMU), который:

  • контролирует доступ к ней;
  • запоминает местонахождение выделенных под приложения участков памяти после того, как их определяет операционная система;
  • может впоследствии отвечать на запросы процессора вроде «может ли конкретная программа работать с памятью по конкретному адресу»

Допустим, я запустил на своём компьютере программы «Калькулятор» и «Вирус» — без root-привилегий и прав администратора. Затем я ввёл в программе «Калькулятор» выражение «20+3» и получил ответ — «23».

Что произошло?

  • Операционная система выделила программе «Калькулятор» ячейки памяти с первой по десятую, а программе «Вирус» — с двадцатой по тридцатую.
  • «Калькулятор», получив вводные данные «20+3» просит процессор: «посчитай, сколько будет „20+3” и запиши ответ в ячейку памяти №1».
  • Процессор считает „20+3” и обращается к блоку MMU: «имеет ли программа „калькулятор” доступ к ячейке памяти №1?».
  • Получив положительный ответ, процессор продолжает выполнение задачи и просит оперативную память записать в ячейку №1 число 23.
  • Программа «Вирус» хочет украсть из памяти то число, которое считали в «Калькуляторе», и спрашивает у процессора: «скажи, что лежит в ячейке памяти №1?».
  • Процессор обращается к блоку MMU: «имеет ли программа „Вирус“ доступ к ячейке памяти №1?».

Но мы знаем, что программе «Вирус» принадлежат совсем другие ячейки, и она не имеет прав для такого запроса. Это знает и блок MMU, который даёт процессору отрицательный ответ. Выполнение команды прерывается, а «Вирус» получает сообщение вроде «ай-яй-яй, вам туда нельзя».

Разобравшись с безопасностью, взглянем на не менее важную характеристику процессора и памяти — скорость.

Допустим, программа «Калькулятор» очень часто спрашивает процессор о содержимом ячейки №1. Неужели процессор каждый раз запрашивает эту ячейку из оперативной памяти? Это очень долго, и чтобы работать быстрее, процессор сохраняет в кэш-памяти содержимое ячеек, про которые его часто спрашивают — для обеспечения скоростного доступа к ним.

Разумеется, он обратится к блоку MMU для проверки в следующий раз, когда «Калькулятор» в спросит о содержимом ячейки №1, но затем сразу отдаст ответ из своей кэш памяти, не обращаясь к оперативной. Этот способ очень ускоряет работу программ: процессор отвечает на их запросы почти мгновенно. Однако люди всегда хотят большего.

Алгоритм предсказания ветвлений

За страшным на первый взгляд названием скрывается незамысловатый принцип работы. Представим, что у нас есть программа, которая просит процессор выполнить команду: «X=100; если X не равен нулю, то отними от него единицу; повтори заново всё, начиная с „если“». Из текста ясно, что при выполнении процессору придётся сначала проверить значение X, и только потом отнимать единицу. И сделать все это ему придется сто раз подряд.

Условие будет выполняться сто раз подряд — пока Х не станет равен нулю. Но ведь для этого нужно каждый раз доставать Х из кэш-памяти сравнивать его с нулём. А ещё обращаться к MMU и запрашивать у него разрешение на чтение из ячейки памяти, в которой хранится Х. Это слишком долго.

А почему бы не забежать вперёд? Если X двадцать раз подряд не равен нулю, то и на двадцать первый, скорее всего, тоже не равен. Пока идут все проверки, лучше заранее посчитать „X-1“ и сэкономить время. Если условие не выполнится — просто не отдадим подготовленный результат

Хитрые инженеры

Так появился алгоритм предсказания ветвлений: процессор запоминает, какие условия часто выполняются и начинает сразу выполнять следующие команды, отдавая результат только после окончания проверки.

Круто? Конечно, ведь процессор теперь не простаивает, ожидая ответа от памяти и MMU, а успевает за это время посчитать результат.

Безопасно? Казалось бы, да. Даже условие не выполнилось, процессор просто отбросит предварительно полученный результат, а программа никогда о нём и не узнает.

В чём же подвох и просчёт инженеров?

Представим ситуацию: на компьютере запущены «Вирус» и «Калькулятор», который всё ещё хранит в своей первой ячейке «23».

  • «Вирус» просит у процессора: «Запиши в ячейку памяти №20 число „2”».
  • Процессор делает запрос блоку MMU, который отвечает, что «Вирус» имеет право на запись в ячейку 20 — ведь ему давались ячейки с двадцатой по тридцатую.
  • «Вирус» сообщает процессору: «X=20; скажи, что лежит в ячейке памяти под номером X; повтори 100 раз».
  • Процессор обращается к MMU с запросом о правах доступа, а затем отдает содержимое ячейки №20.

Спустя несколько «проходов» срабатывает алгоритм предсказания ветвлений: «мы уже достаточно много раз получили положительный ответ, когда спрашивали у MMU, имеет ли "вирус" право на доступ к ячейке №X, значит, для ускорения можно заранее готовить ответ, не дожидаясь проверки, а после окончания проверки сразу же его отдавать».

Тут и начинается самое интересное.

  • «Вирус» задаёт процессору такую задачку: «X=1; прочитай содержимое ячейки, номер которой — значение ячейки №X». Вдумчиво перечитайте это несколько раз, чтобы понять.
  • Процессор сначала спрашивает, имеет ли «вирус» доступ к ячейке №X.
  • Ответ на этот вопрос уже сто раз был утвердительный, а значит процессор не дожидается окончания проверки, и читает содержимое ячейки №1 — в ней лежат наши «23» из «Калькулятора».
  • Процессор обращается к ячейке №23, которая принадлежит «Вирусу» и читает ее содержимое.
  • От MMU приходит ответ: у «Вируса» нет доступа к ячейке №1.
  • Процессор сбрасывает все результаты своей деятельности, не выдавая вирусу ничего.

Но где же уязвимость? На моменте, выделенным жирным шрифтом. Процессор не отдал «Вирусу» никаких результатов вычислений, однако все же прочитал содержимое ячейки №23, а значит закинул его в кэш. Как «Вирусу» узнать, что номер ячейки был именно 23?

Просто спросить у процессора, что лежит во всех принадлежащих ему ячейках, замерив время ответа. Для ячейки №23 оно куда меньше, чем для остальных. Потому что процессор уже обращался к ней и сохранил её в кэше.

То есть в ячейке №1 лежит число «23». Так «Вирусу» удалось его украсть.

Это и есть Meltdown.

Теперь вопросы

В: Подвержены ли этой уязвимости смартфоны и планшеты?

О: Компания ARM — разработчик архитектуры большинства мобильных процессоров — заявила об уязвимости ядер Cortex A15, A57 и A72 (используются в гаджетах 2014-2016 годов), которые подвержены одному из вариантов Meltdown. Он сложнее воспроизводится и не может получить доступ к произвольным областям памяти. То есть, и да, и нет.

В: Правда ли, что процессоры AMD не подвержены Meltdown?

О: Хотя в AMD говорят, что на их процессорах нельзя использовать эту уязвимость, в теории это возможно — просто пока не получалось на практике. То есть, процессоры AMD защищены лучше аналогов от Intel, но это не точно: позже кто-нибудь может обнаружить Meltdown и у них.

В: А Intel? Там плохо вообще всё?

О: Да, эти процессоры подвержены Meltdown в полной мере — все выпускаемые и большинство используемых. Кроме линейки Intel Atom, выпущенных до 2013 года и в основном использовавшихся в нетбуках.

В: А что с отечественными процессорами?

О: Элвис и Эльбрус находятся в том же положении, что и процессоры AMD. Так же, как и Байкал-Т1. А вот Байкал-М построен на базе Cortex-A57, а значит всё-таки подвержен одному из вариантов Meltdown.

В: Как защититься?

О: Большинство поддерживаемых ОС уже защищены — достаточно просто обновиться до актуальной версии.

В: Я слышал, что эти обновления замедляют систему. Мой старый компьютер будет тормозить?

О: Замедление заметно лишь в узком кругу задач. Для интернета, текстовых редакторов и большинства игр не будет никакой разницы в производительности. Личный пример: обновив ядро Linux на своем стареньком нетбуке на базе Intel Atom N550 (который хоть и не уязвим к Meltdown, не добавлен в «исключения» патча), я не заметил замедления.

В: Эту закладку сделали проклятые ГБшники в обнимку с ФБРовцами?

О: Вряд ли. Современные ядра настолько сложны, что можно встроить лазейку в менее заметное место. Например отдельным модулем, который никто никогда бы не разглядел.

В: Может быть это подстроили производители процессоров, которые хотят поддержать спрос?

О: По этому поводу есть основательные сомнения: закладывать уязвимость, а потом 20 лет надеяться, что её никто не обнаружит — похоже на фантастику. К тому же им сейчас придётся наспех выпускать «исправленные» процессоры, а это сильно ударит по продажам текущего поколения. Да и репутация не восстанавливается по щелчку.

В: Хакер может использовать эту уязвимость на моём компьютере?

О: Да, достаточно просто зайти на сайт злоумышленника. И он сможет получить через ваш браузер получить доступ к вашим данным с сайта банка, открытого в соседней вкладке. Поэтому нужно однозначно обновлять браузер и операционную систему, особенно у вас процессор от Intel.

В: Но ведь есть ещё одна уязвимость — Spectre.

О: К сожалению, просто описать принцип ее действия так же едва ли получится. Хотя ей подвержены почти все процессоры, воспроизвести её в реальных условиях затруднительно — особенно не зная некоторых данных конкретного атакуемого устройства. Хакеры вряд ли будут к ней прибегать.

Надеюсь, было понятно. Готов ответить на ваши вопросы в комментариях :) Если вы заметили какие-то логические неточности, то тоже пишите в комменты.

Материал написан под редакцией Александра Фаста. Большое ему спасибо.

#технологии #чипокалипсис