Search
Write a publication
Pull to refresh

RISC-V и безопасность: анализ методов защиты открытой архитектуры

Level of difficultyEasy
Reading time19 min
Views1.2K

Предисловие

Информации в данной статье не стоит стопроцентно и безоговорочно доверять. Я и мой товарищ, который помогал мне со сбором информации, только изучаем тему микроэлектроники не являемся экспертами в отрасли процессорных архитектур, в особенности RISC-V, отчего в данной статье могут быть ошибки, в виду не полного понимания темы. Всю информацию мы брали из открытых источников, документаций и статей с нашего любимого Хабра, Гит-хаба и подобных, поэтому для погруженных в тему людей данная статья, скорее всего, ничего нового и полезного не даст. Однако, я был бы рад получить конструктивную критику от знающих людей, чтобы разобраться в этой теме лучше.

P.S. Огромное спасибо за помощь в сборе информации моему товарищу Елфимову Артёму Андреевичу

Введение

В настоящее время цифровая инфраструктура очень быстро растет и развивается, вместе с ней должна развиваться и защита информации, используемая в той или иной технологии. Чаще всего основное внимание уделяют защите программных уязвимостей, тогда как аппаратный уровень остается в тени, хотя именно через него проходят все данные. Классические программные методы защиты — антивирусы, фаерволы, изоляция процессов, не всегда могут предотвратить утечку информации, ведь если в аппаратном уровне допущены механизмы, которые позволяют добраться до защищенной памяти, то никакие программные методы не помогут избежать утечек данных. Именно поэтому производители и разработчики всё чаще закладывают элементы безопасности непосредственно в архитектуру микропроцессора.

Разработка аппаратной безопасности включает в себя множество различных механизмов, такие как: разграничение уровней доступа, изоляция памяти, контроль выполнения привилегированных команд, использование доверенных сред исполнения. Важно понимать, что безопасность в процессорах — это не просто возможность дополнительной защиты, а необходимость, которая обхватывает не только микроархитектуру, но и программную инфраструктуру, взаимодействующую с ней. При правильном проектировании аппаратная безопасность позволяет предотвращать атаки.

Исторически считалось, что закрытые архитектуры, такие как x86 (Intel, AMD) и ARM, обладают встроенной безопасностью, благодаря контролю производителя над всеми составляющими в процессоре. Однако, с ростом сложности микропроцессоров, оказалось, что даже они не являются безопасными.

Яркий пример — атаки Spectre и Meltdown, позволившие извлекать данные из защищённой памяти [1]. Эти атаки затронули почти все современные процессоры, включая Intel, AMD и ARM.

В этом контексте особое внимание вызывает RISC-V — открытая архитектура команд, предоставляющая гибкость и прозрачность во всех своих аспектах. Но возникает вопрос: если даже закрытые архитектуры уязвимы, как обеспечивается безопасность в открытой архитектуре RISC-V? Но для начала, нам нужна небольшая историческая справочка в истории архитектур

1 Эволюция архитектур: от CISC к RISC

1.1 CISC-процессоры

В 1970-1980-ых годах на рынке микроэлектроники доминировали CISC-процессоры (Complex Instruction Set Computer - компьютер с полным набором команд), архитектуры x86. Главная особенность подобных процессоров была в том, что сложные операции выполнялись одной инструкцией длиной от 1 до 15 байт. Инструкция – это закодированная команда, определяющая операцию, которую должен выполнить процессор. Данный подход хоть и был неплохим, но имел в себе много недостатков:

  • Так как инструкции могли быть очень длинными, они требовали больше транзисторов, что повышало энергопотребление процессора, что было большой проблемой для отрасли 3д-моделирования и рендеринга того времени;

  • Для декодирования и выполнения нескольких сложных операций процессору требовалось много памяти, которая на тот момент стоила очень дорого (к примеру, один мегабайт оперативной памяти стоил около 5000 долларов). Также при обращении декодера к памяти скорость обработки инструкций становилась меньше;

  • Большинство возможностей CISC (например, строковые операции) редко использовались, но усложняли декодер.

1.2 Возникновение архитектуры RISC

В середине 1980-ых стали появляться процессоры на новом архитектурном подходе RISC (reduced instruction set computer - вычислитель с сокращённым набором команд). Его отличием от CISC было:

  1. Фиксированная длина инструкции - всего 4 байта, что снизило энергопотребление.

  2. Минимально необходимый набор команд, без лишней нагрузки на декодер.

  3. Большое количество регистров, куда часть необходимых команд могли сохраняться, не прибегая к использованию памяти.

Но главным преимуществом RISC стала конвейеризация процессора - выполнение несколько инструкций одновременно. К примеру, для исполнения инструкции, она проходит 5 этапов:

  1. Fetch (чтение инструкции).

  2. Decode (декодирование).

  3. Execute (выполнение).

  4. Memory Access (работа с памятью).

  5. Writeback (запись в регистр).

Каждый из этих этапов выполняется в один такт. В CISC процессорах пока одна инструкция проходит эти 5 этапов, вторая ждёт полного исполнения инструкции, чтобы начинать первый этап, когда как в RISC вторая инструкция может приступать первому этапу сразу, как первая инструкция перешла на второй. Если в CISC первая инструкция выполняется за 5 тактов, то вторая уже за 10, а третья за 15, в то время как в RISC все три выполнялись за 5 тактов. Архитектура оказалась успешной и производительной: любой процессор на базе RISC был в разы эффективнее в работе, чем его аналог на CISC[2].

1.3 Распространение RISC-архитектур

В дальнейшем началось сильно развитие архитектур на основе подхода RISC: в последнее время популярная архитектура ARM, процессоры которой стоят в каждом смартфоне и современных ноутбуках, и персональных компьютерах от Apple, нынче почившая MIPS, на базе которой делали процессор для PlayStation 1 и 2, а также появившаяся в 2010 году открытая архитектура RISC -V.

Основной особенностью RISC-V является её открытость и персонализированность в настройках. Если процессоры на архитектуре ARM хоть и являются производительными и современными, их нужно лицензировать, когда как RISC -V, несмотря на то, что подобен процессорам RISC 80-х и 90-х годов и во многом сильно проигрывает ARM, является открытой, и имеет возможность добавить собственные инструкции и декодер, настроить опциональные расширения для команд и также инструменты для информационной защиты процессора [3].

2 PMP: Защита памяти в RISC-V

2.1 Зачем нужна защита памяти

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

2.2 Защита памяти в архитектуре RISC-V

В архитектуре RISC-V есть такой механизм защиты памяти, как PMP (Physical Memory Protection). С помощью него можно задать участки физической памяти, записав его в один из регистров, доступ к которым будет запрещен. Например, можно сделать запрет на чтение, запись или выполнение программ. Это полезно, если программа в пользовательском режиме, то она не сможет прочитать или изменить память, доступ к которой запрещён в настройках PMP. Его главным отличие от аналогов в x86 и ARM является использование физической памяти, а не виртуальной, благодаря чему PMP в выбранной области памяти будет осуществлять защиту лучше, чем методы, использующие виртуальную память. Но из-за небольшого количества регистров (от 8 до 16), метод не подходит для сложных ОС (например, Linux), так как не сможет защитить все области системы, поэтому PMP более эффективен для встраиваемых систем и устройств без полноценной операционной системы.

Основной принцип работы PMP поделен на два типа регистров:

  1. Регистры pmpaddr0–pmpaddrN: Определяют границы защищаемых областей памяти. Количество регистров зависит от конкретной реализации (обычно от 8 до 16). Формат адреса зависит от режима адресации (TOR, NAPOT).

  2. Регистры pmpcfg0–pmpcfgN: Задают права доступа для соответствующих областей. Каждый регистр pmpcfg содержит 8 бит, которые определяют:

    • Разрешение на чтение (R), запись (W) и выполнение (X);

    • Режим блокировки (L), предотвращающий изменение правил до перезагрузки системы.

Данные регистры важно настроить правильно, ведь при неверных ограничениях областей памяти может произойти утечка данных [4].

Пример записи длины защищаемой области в регистр pmpaddr
Пример записи длины защищаемой области в регистр pmpaddr
Схема записи байтов в регистр pmpcgf0
Схема записи байтов в регистр pmpcgf0

2.3 Защита памяти в архитектуре x86

В архитектуре x86 механизм защиты памяти устроен иначе, через метод страничной организации (paging), который использует виртуальную память. Механизм так и называет - Paging Protection. Он позволяет:

  • Изолировать процессы друг от друга;

  • Контролировать доступ к памяти на уровне страниц (обычно 4 КБ);

  • Реализовывать разграничения по уровню привилегий Ring levels (0–3) для разных участков памяти.

Данный механизм отлично подойдёт для сложный систем, ведь имеет многоуровневую структуру регистров (PML4 - Page Map Level 4, PDP - Page Directory Pointer, PD - Page Directory, PT - Page Table), благодаря чему охватывает всю ОС, но из-за сложности настройки не подойдёт для простых устройств [5].

2.4 Защита памяти в архитектуре ARM

Архитектура ARM использует комбинацию MMU (Memory Management Unit) и бита PXN (Privileged Execute Never):

  • MMU: Управляет трансляцией виртуальных адресов в физические;

  • PXN: Запрещает выполнение кода в пользовательском режиме для определенных страниц.

Данный механизм больше нацелен на энергоэффективность, поэтому имеет меньше регистров и более прост в настройке, чем Paging, но также пригоден для работы со сложными ОС [6]. Для корректной работы механизма потребуется настроенный TrustZone, о котором мы расскажем далее.

Критерий 

RISC-V (PMP)

x86 (Paging)

ARM (MMU+PXN)

Работа без ОС

Да

Нет

Нет

Гранулярность

8–16 регистров

4 КБ–1 ГБ

4 КБ–1 ГБ

Сложность    настройки 

Простая (регистры)

Сложные таблицы страниц

Для настройки требуется TrustZone

3. Доверенная среда исполнения в RISC-V

3.1 Что такое TEE (Trusted Execution Environment)

Методы безопасности нужны не только памяти процессора, но и код и его корректное исполнения. Для такого типа информации есть TEE (Trusted Execution Environment - доверенная среда исполнения) – это среда внутри процессора, предназначенная для безопасного исполнения кода и хранения чувствительных данных. Данная среда обеспечивает изоляцию от основной операционной системы и приложений. Даже если хост-система скомпрометирована, код внутри TEE остаётся защищённым [7].

3.2 Подход к TEE в архитектуре RISC-V

В RISC-V нет встроенного TEE на уровне архитектуры, но есть множество внешних решений, которые пользователь по предпочтению может поставить сам: Keystone Enclave, OpenTitan, Hex-Five MultiZone Security, Bao Hypervisor, Silicon Labs Secure Vault и другие. Из них всех возьмём лишь самый популярный - Keystone Enclave [8].

Keystone — это платформа открытого исходного кода (open-source), предназначенная для реализации TEE (Trusted Execution Environment) на базе архитектуры RISC-V.

Концепция Keystone базируется на технологиях Intel SGX, то есть доверенная среда реализуется через анклав - защищённую область памяти, которая позволяет выполнять код и хранить данные так, что даже операционная система или привилегированный пользователь не могут получить к ним доступ без соответствующих прав, и данная защищённая область в Keystone выделяется с помощью PMP. Но несмотря на заимствования идей у Intel и ARM, построена данная TEE с учётом всех их слабостей. Сам Keystone, подобно RISC-V, также открыт и гибок в настройках, его можно проанализировать на уязвимости, улучшить или адаптировать под себя, чего нельзя сказать про SGX и TrustZone. Так же и сама доверенная среда построена модульно, и разработчик может самостоятельно настроить, какие компоненты попадут в доверенную базу, а какие останутся за пределами защищённой области. Но для данного метода нужна точная и правильная настройка, ведь при неверных параметрах может произойти утечка данных и потеря конфиденциальной информации[9]. Keystone — это гибкий, программный и открытый аналог, реализующий TEE поверх минимального набора аппаратных расширений.

Работа анклавов Keystone
Работа анклавов Keystone

3.3 Сравнение Keystone Enclave с аналогами других архитектур

Intel SGX — это набор инструкций на x86 от Intel, позволяющий создавать анклавы внутри адресного пространства процесса. В отличии от Keystone, анклав в SGX находится в пределах одного процесса, но область памяти анклава шифруется и аппаратно защищена от остальной ОС. Работает SGX на уровне пользовательского режима (Ring 3), в качестве самого анклава реализует защищённую область DRAM, и данный TEE широко используется в облачных решениях, таких как Azure Confidential Computing. Из недостатков выделяют сложность программирования и отладки SGX, а так наличие серьёзных уязвимостей, которые невозможно проанализировать из-за проприетарности метода [10].

Работа анклава Intel SGX
Работа анклава Intel SGX

TrustZone – аппаратная технология от ARM, которая делит систему на два "мира":

  1. Secure World — по сути является той самой доверенной средой.

  2. Normal World — основная операционная система и приложения.

Между этими “мирами” переключение осуществляется через инструкции SMC (Secure Monitor Call). Secure World имеет доступ к ресурсам Normal World, но не наоборот. Обычно эта технология используется в Android для реализации Trusty OS, а также в чипах с DRM (Технические средства защиты авторских прав). Минусом у TrustZone является его закрытая реализация, и разработчики не могут свободно адаптировать TEE под необходимые задачи [11].

Пример работы TrustZone
Пример работы TrustZone

Параметр

Keystone  (RISC-V)

Intel SGX (x86)

TrustZone (ARM)

Открытость

Полностью открытый код и спецификации

Закрытая реализация

Закрытая реализация

Изоляция

На основе PMP и привилегий

Аппаратная изоляция в CPU

Аппаратный делитель мира

Гибкость

Пользователь может адаптировать архитектуру под нужды

Жёстко привязан к Intel чипам

Жёстко привязан к ARM Cortex

Применение

IoT, edge-серверы, исследовательская среда

Облачные сервисы, DRM

Мобильные устройства, криптооперации

4. Контроль привилегий в процессорах

4.1 Зачем нужен контроль привилегий

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

4.2 Механизм привилегий в архитектуре RISC-V и ее аналогах

В RISC-V существует три уровня привилегий:

  • Machine mode (M-mode) — самый высокий, доступ ко всей памяти, как виртуальной, так и физической;

  • Supervisor mode (S-mode) — для операционной системы, может управлять виртуальной памятью и процессами;

  • User mode (U-mode) — для обычных приложений.

Для каждого режима разрешен только определенный набор действий [12].

Если сравнивать с архитектурой x86, то там контроль привилегий действует иначе, есть кольца (Ring 0 — Ring 3), где Ring 0 - это самый высокий уровень, а Ring 3 - это обычные приложения [13].

Уровни привилегий в x86
Уровни привилегий в x86

У ARM тоже своя система и в старых версиях она была схожа с RISC-V, но в более новых появился механизм TrustZone, который делит систему на обычную и защищённую, что позволяет выполнять важные задачи отдельно от основной операционной системы.

Уровни привилегий в ARM
Уровни привилегий в ARM

5. Защита от спекулятивных атак в процессорах

5.1 Что такое спекулятивное выполнение

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

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

  1. Атакующий многократно вызывает код с корректным индексом x, чтобы процессор «привык» выполнять эту ветку.

  2. Теперь он передаёт нужный ему индекс, выходящий за границы массива и указывающий на защищённые данные (к примеру, пароли и ключи шифрования). Тем временем процессор:

    • Спекулятивно загружает array[x] (например, секретный ключ);

    • Проверяет условие и понимает, что доступ запрещён;

    • Отменяет операцию, но следы остаются в кэше;

  3. Атакующий измеряет время доступа к ячейкам памяти:

    • Если данные были в кэше (значит, они спекулятивно загружались) — доступ быстрый;

    • Если не были — доступ медленный.

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

  1. Spectre — манипулирование ветвлениями, обход изоляции между процессами.

  2. Meltdown — доступ к защищённой памяти через спекулятивное выполнение.

Эти уязвимости затронули почти все современные процессоры на x86 и ARM, и возникла необходимость в их архитектурных изменениях [14].

Пример работы Spectre-атаки
Пример работы Spectre-атаки
Пример работы Spectre-атаки
Пример работы Spectre-атаки

5.2 Реализация защиты в RISC-V и других архитектурах

RISC-V, в отличие от x86 и Arm, не требует спекулятивного выполнения для высокой производительности. Однако некоторые ядра поддерживают эту оптимизацию, что делает их потенциально уязвимыми. К примеру, 64-битное ядро CVA6 поддерживает спекулятивное выполнение, и несмотря на то, что это ускоряет доступ к памяти, повышая эффективность ядер, появляется потенциальная уязвимость Spectre-атаки. Для защиты ядра была создана fence инструкция - принудительный барьер, который сбрасывает спекулятивные операции при смене контекста. И всё равно, если от атак Spectre-V2 fence защищает, то Spectre-V1 все ещё возможен, если ядро спекулятивно выполнит инструкции после условного перехода. Но ядро Ariane не имеет поддержки спекулятивного выполнения, что хоть и понижает их производительность, по сравнению с CVA6, но делает его абсолютно неуязвимым к любым спекулятивным атакам [15].

Intel и AMD выпускают обновления для своих x86 процессоров, которые добавляют новые механизмы защиты:

  • IBRS (Indirect Branch Restricted Speculation) – ограничивает спекулятивное выполнение косвенных переходов;

  • STIBP (Single Thread Indirect Branch Predictors) – защищает от атак между потоками (например, в облаке).

Данные механизмы запрещают использование истории предсказаний ветвлений инструкций, что защищает от Spectre-атак, но уязвима к Meltdown и понижает производительность процессора на 5–15%. В качестве альтернативы этим механизмам есть LFENCE-барьер, который принудительно останавливает спекулятивное выполнение последующих команд. Данный метод помимо неуязвимости к Spectre даёт частичную защиту к Meltdown, и понижает производительно всего на 5%.

Процессорные ядра у ARM более уязвимые к Spectre, чем x86[16], поэтому был создан аналог LFENCE в ARM - инструкция CSDB. Принципиально, они ничем друг от друга не отличаются, и CSDB, так же как LFENCE, блокируют большинство Spectre-атак, но в отличии от x86, армовский аналог понижает производительность до 10%. Также, из аппаратных методов у ARM есть SSBS (Speculative Store Bypass Safe)[17], который отключает спекулятивный обход проверок памяти, защищает от большинства Spectre-атак и понижает производительность на 5-10%. Но данный метод включается через регистр SCTLR_ELx.SSBS, по умолчанию включён только CSDB[18].

6. Экспериментальная часть, с целью проверки методов безопасности процессоров RISC-V на практике

К сожалению, у меня нет системы с процессором на архитектуре RISC-V, поэтому эксперименты были проведены в программе для эмуляции аппаратного обеспечения различных платформ QEMU, так как он поддерживает эмуляцию процессоров на архитектуре RISC-V, на виртуальной операционной системе Ubuntu. В программировании на ассемблере я чайник, поэтому в помощь мне приходили некоторые форумы и нейронный товарищ в лице ChatGPT. Прошу сильно не сердиться)

6.1 Эксперимент 1: Настройка PMP

Цель эксперимента: проверить, как механизм PMP настраивается и ограничивает доступ программ к определённым физическим адресам, особенно при переходе из режима привилегий M-mode (Machine) в U-mode (User).

Для начала попробуем корректную настройку PMP.

Структура проекта:

  1. main.c - основной код (настройка PMP + тест записи).

  2. start.S - ассемблерный код, который выполняется самым первым после загрузки программы. Его задачи:

    • инициализировать стек (sp);

    • подготовить окружение для запуска main() (например, очистить .bss);

    • переключиться в нужный режим.

  3. linker.ld - конфигурационный файл, который указывает компоновщику:

    • где в памяти размещать код (text), данные (data, bss) и другие секции;

    • как выравнивать секции;

    • какие симоволы (например, _start) считать точками входа.

Корректная настройка PMP:

Файл main.c
Файл main.c
  1. configure_pmp() настраивает pmpaddr0 на область 4К от 0x80000000.

  2. Устанавливается pmpcfg0 на RWX (команда для изменения прав доступа).

  3. Данные регистров pmpaddr0 и pmpcfg0 записываются в allowed.

  4. Запись регистров в forbidden — выходит за пределы и вызывает trap (в QEMU просто "виснет").

Файл linker.ld
Файл linker.ld

Файл linker.ld размещает код по адресу 0x80000000, так как PMP настраивается на этот же адрес.

Файл start.S
Файл start.S

Минимальный стартовый код:

  • устанавливает стек (sp);

  • Вызывает main;

  • Бесконечный цикл после выхода из main.

Ожидаемое поведение:

  • если QEMU с поддержкой PMP — trap при второй записи;

  • если PMP не эмулируется — запись произойдёт (плохой результат);

  • если всё настроено верно — QEMU зависнет или покажет trap (в зависимости от настроек).

Запуск:

Компиляция start.S и main.c в нужные форматы

Запуск QEMU с файлом формата .elf

Видим, что QEMU – завис. Чтобы в этом удостовериться используем команду «ps aux | grep qemu», если увидим, что сеанс программы не завершён – QEMU зависла. QEMU действительно зависла, следовательно, произошёл вызов «trap», PMP заблокировал доступ к выделенной области, и эксперимент прошёл успешно.

Некорректная настройка PMP:

Дальше попробуем намеренно настроить PMP неправильно. Изменим файл main.c

Файл main.c
Файл main.c
Файл main.c
Файл main.c

PMP настроен на 0x80200000, но ошибочно: разрешены все доступы. Происходит переход в U-mode. U-код обращается по адресу 0x80200000, и это срабатывает. Выводится «[U-MODE] Write succeeded! PMP failed!»

Файл linker.ld
Файл linker.ld

Добавляет секцию .rodata для смены уровня привилегий, а также исключает лишнее. Файл start.S остаётся без изменений.

Программа должна вывести:

«[M-MODE] PMP incorrectly configured. Should block, but doesn't.

[U-MODE] Attempting to write to protected memory...

[U-MODE] Write succeeded! PMP failed!»

Запуск. Компилируем файлы и запускаем QEMU

Программа зависла – следовательно PMP сработал или произошла проблема при переходе в другой уровень привилегий. Попробуем добавить в код настройку mstatus перед mret, для корректного перехода по уровням привилегий.

Добавление настройки mstatus

Запуск эмулятора через интерфейс OpenSBI

Эмулятор снова завис, вероятнее всего это связано с ошибкой во время смены уровня привилегии из-за некорректной эмуляции PMP на виртуальных эмуляторах, и мой низкий навык владения ассемблером. Эксперимент неудачный.

6.2 Эксперимент 2: Моделирование Spectre-подобной атаки в RISC-V

Цель эксперимента: Смоделировать условия для Spectre-атаки в эмуляторе RISC-V. В RISC-V QEMU обычно нет поддержки спекуляции, но мы имитируем её поведение: покажем, как потенциально могла бы произойти утечка через побочный канал, даже если реально спекуляции нет.

Суть нашей Spectre-атаки:

  • есть секретный массив, который мы должны достать: secret[];

  • есть проверка границы доступа к array[index], которая должна ограничить доступ;

  • но при спекуляции CPU может временно проигнорировать проверку границы и начать выполнять следующую команду (например, доступ к secret);

  • даже если потом выполнение отменяется, побочные эффекты (например, кэш) остаются — их можно "заметить";

  • именно этой уязвимостью мы и воспользуемся.

Структура проекта:

  • main.c - основной код — имитация Spectre;

  • start.S - инициализация и запуск main;

  • linker.ld - разметка памяти.

Файл main.c
Файл main.c
Файл main.c
Файл main.c

Пояснение кода: есть массив unused_array — безопасный буфер. Есть секретный байт secret, расположенный сразу за unused_array. Функция victim_function получает индекс, проверяет, что он внутри unused_array и читает значение из этого массива, а затем обращается к probe_array по индексу, зависящему от прочитанного байта. В норме выход за пределы массива невозможен, но в спекулятивном исполнении процессор мог бы "спекулятивно" выполнить код с неправильным индексом, косвенно раскрывая значение secret. Функция spectre_attack пытается вызвать victim_function с индексом, указывающим на секретный байт, и затем анализирует изменения в probe_array, чтобы "угадать" секрет. В выводе показывается угаданное значение секретного байта (в данном случае — D0 в шестнадцатеричном виде).

Файл linker.ld
Файл linker.ld
Файл start.S
Файл start.S

Почему это не реальная спекулятивна атака:

  • нет спекуляции в QEMU;

  • нет реального кэша, а значит и времени доступа;

  • это учебная симуляция: мы "предполагаем", что доступ по неверному индексу всё же произошёл и повлиял на поведение.

Программа должна вывести:

«[SPECTRE] Starting simulation...

Guessed secret: D0»

Запуск. Компилируем start.S и main.c в нужные для работы форматы

Запуск QEMU с файлом формата .elf

В выводе мы видим секретный байт, следовательно, Spectre атака прошла успешно – эксперимент удачный.

6.3 Эксперимент 3: Демонстрация Keystone Enclave в QEMU

Цель эксперимента: Запустить защищённое исполняемое окружение (TEE) с помощью Keystone и продемонстрировать его работу на RISC-V через эмулятор QEMU. Несмотря на то, что вариантов механизма TEE в архитектуре RISC-V достаточно, мы решили так же взять Keystone, так как он позволяет:

  • создавать и запускать энклавы — приложения в изолированной защищённой среде;

  • использовать SDK для их написания;

  • запускать всё это в QEMU, даже без физического RISC-V железа.

Запуск. Установка зависимостей

Так как Keystone — это внешняя open-source система, её нужно клонировать вручную с GitHub [20].

Далее идет сборка собственного RISC-V компилятора, настроенного для работы с Keystone

Переходим в директорию папки sdk. Запускаем скрипт init.sh. Скрипт init.sh подготовит окружение и необходимые зависимости

Далее производим сборку тестовой энклавы (HelloWorld)

После сборки появились два бинарных файла:

  • host_helloworld — программа на стороне хоста;

  • eapp_helloworld — исполняемый код в энклаве.

Производим запуск через QEMU. Переходим в директорию scripts – ближе к «сердцу» Keystone и запускаем скрипты

На консоль выводится запуск системы и выполнение защищённого кода. Энклава демонстрирует базовую функциональность TEE: код исполняется в изолированном пространстве, доступ к нему ограничен со стороны основной ОС.

Данный вывод означает что:

  • хост-приложение запустило энклаву;

  • код внутри энклавы выполнен изолированно;

  • доверительная среда (TEE) работает.

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

7. Заключение

Архитектура RISC-V, несмотря на свою относительную молодость и моральную устарелость, демонстрирует высокую степень возможности глубокой настройки систем безопасности. В отличие от закрытых архитектур x86 и ARM, она предлагает разработчикам возможность гибко настраивать уровни доступа, расширять набор инструкций и интегрировать механизмы защиты по своему вкусу. Такие технологии, как PMP, Keystone и трёхуровневая модель привилегий, позволяют реализовать надёжную защиту данных и изоляцию процессов на уровне встраиваемых систем.

Однако RISC‑V имеет и определённые ограничения. Архитектура не имеет полноценной защиты от спекулятивных атак в общедоступных ядрах, а PMP ограничен по количеству регионов и подходит в первую очередь для встраиваемых решений, а не для полноценных операционных систем. Архитектуры x86 и ARM имеют более зрелые аппаратные защиты, но их сложность и закрытость осложняют аудит, доверие и анализ уязвимостей.

RISC‑V обеспечивает удобную площадку для создания систем с расширяемой и проверяемой моделью защиты, что особенно важно для критических сфер и встраиваемых систем.

Сравнение с архитектурами x86 и ARM показывает, что закрытость не является гарантией защищённости. Примеры атак Spectre и Meltdown затронули многие устройства, преимущественно на закрытых архитектурах.

Открытость RISC‑V даёт возможность независимым исследователям и организациям самостоятельно изучать и расширять защитные механизмы, и главное — доверять тому, что их процессор действительно делает. Примеры Keystone Enclave показывают, что открытые TEE‑решения могут быть не менее сильными, чем закрытые TrustZone и SGX.

Таким образом, открытые архитектуры, при грамотной настройке и сообществе разработчиков, способны обеспечивать более надёжную и контролируемую защиту, чем проприетарные.

Список использованных источников

  1. Статья об атаках Spectre и Meltdown на сайте Касперского URL: https://www.kaspersky.ru/blog/spectre-meltdown-in-practice/32334/

  2. «Ретроспективный взгляд на развитие микропроцессоров CISC, RISC, MIPS, ARM» URL: https://habr.com/ru/companies/first/articles/798635/ 

  3. «Гениальность микропроцессоров RISC-V» URL: https://habr.com/ru/companies/vdsina/articles/534542/ 

  4. Официальная документация про PMP на сайте проекта «RISC-V» URL: https://riscv.org/blog/2024/03/adding-physical-memory-protection-to-the-veer-el2-risc-v-core-2/

  5. Страница на OSDev Wiki про механизм защиты Paging URL: https://wiki.osdev.org/Paging

  6. Страница на DeepWiki про меры безопасности архитектуры ARM URL: https://deepwiki.com/nccgroup/exploit_mitigations/4.1-arm-architecture-security-mitigations

  7. Статья про Trusted Execution Environment на сайте Microsoft URL: https://learn.microsoft.com/ru-ru/azure/confidential-computing/trusted-execution-environment

  8. Статья про особенности TEE Xuantie на сайте проекта «RISC-V» URL: https://riscv.org/blog/2023/01/xuantie-risc-v-tee-solution-for-mcu/ 

  9. «Проект Keystone: доверенная среда для запуска приложений на базе RISC-V» URL:  https://habr.com/ru/companies/mws/articles/423777/

  10. «Trusted Execution Environment на примере Intel SGX. Основные принципы простыми словами. «Hello World!»» URL: https://habr.com/ru/articles/518004/

  11. «TrustZone: доверенная ОС и ее приложения» URL: https://www.aladdin-rd.ru/company/pressroom/articles/trustzone-doverennaa-os-i-ee-prilozenia/

  12. Руководство по набору инструкций RISC-V, Том II: Привилегированная архитектура URL: https://www.five-embeddev.com/riscv-priv-isa-manual/latest-latex/priv-intro.html

  13. «Кольца, уровни привилегий и защита в x86» URL: https://habr.com/ru/companies/smart_soft/articles/184174/

  14. «Новая техника атак на основе Meltdown. Использование спекулятивных инструкций для детектирования виртуализации» URL: https://habr.com/ru/companies/bizone/articles/359110/

  15. «Программное обеспечение для защиты от атак Spectre в RISC-V» URL: https://link.springer.com/chapter/10.1007/978-3-031-52947-4_5 

  16. Статья «Новая атака обходит аппаратную защиту от уязвимостей Spectre в процессорах Intel и ARM» URL: https://www.csoonline.com/article/572191/new-attack-bypasses-hardware-defenses-for-spectre-flaw-in-intel-and-arm-cpus.html

  17. SSBS, Speculative Store Bypass Safe Documentation URL: https://developer.arm.com/documentation/ddi0601/2025-03/AArch64-Registers/SSBS--Speculative-Store-Bypass-Safe

  18. CSDB, Consumption of Speculative Data Barrier Documentation URL: https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/CSDB--Consumption-of-Speculative-Data-Barrier-

  19. QEMU User space emulator URL: https://www.qemu.org/docs/master/user/main.html

  20. Keystone Enclave (QEMU + HiFive Unleashed) URL:  https://github.com/keystone-enclave/keystone

Tags:
Hubs:
+3
Comments25

Articles