Intel SGX Threading и против TCS
Я пытаюсь понять разницу между потоками SGX, включенными TCS, и ненадежными потоками, предоставляемыми SDK.
Если я правильно понимаю, TCS позволяет нескольким логическим процессорам входить в один и тот же анклав. Каждый логический процессор будет иметь свой собственный TCS и, следовательно, свою собственную точку входа (OENTRY
поле в ТКС). Каждый поток выполняется до тех пор, пока не произойдет AEX или не достигнет конца потока. Однако эти потоки, включенные TCS, пока не имеют возможности синхронизироваться друг с другом. По крайней мере, нет инструкции SGX для синхронизации.
Затем, с другой стороны, SGX SDK предлагает набор Примитивов синхронизации потоков, в основном мьютекс и переменную условия. Этим примитивам не доверяют, так как они в конечном итоге обслуживаются ОС.
Мой вопрос заключается в том, предназначены ли эти примитивы синхронизации потоков для потоков TCS? Если так, не ухудшит ли это безопасность? ОС может играть с расписанием по своему усмотрению.
2 ответа
Во-первых, давайте разберемся с вашей несколько неясной терминологией
Потоки SGX, включенные TCS, и ненадежные потоки, предоставляемые SDK.
Внутри анклава могут выполняться только "доверенные" потоки. Внутри анклава нет "ненадежных" потоков. Возможно, следующее предложение в Руководстве по SDK [1] ввело вас в заблуждение:
Создание потоков внутри анклава не поддерживается. Потоки внутри анклава создаются внутри (ненадежного) приложения.
Ненадежное приложение должно настроить страницы TCS (более подробную информацию о TCS см. В [2]). Так как же TCS, установленный ненадежным приложением, может стать основой для доверенных потоков внутри анклава? [2] дает ответ:
EENTER гарантированно выполняет контролируемые переходы внутри кода анклава только в том случае, если измерено содержимое всех страниц TCS.
Измеряя страницы TCS, целостность потоков (TCS определяет разрешенные точки входа) может быть проверена посредством аттестации анклава. Таким образом, в анклаве могут быть выполнены только хорошо известные пути выполнения.
Во-вторых, давайте посмотрим на примитивы синхронизации.
SDK предлагает примитивы синхронизации, которым, как вы говорите, нельзя доверять, потому что они в конечном итоге обслуживаются ОС. Давайте посмотрим на описание этих примитивов в [1]:
- sgx_spin_lock () и unlock работают исключительно внутри анклава (с использованием атомарных операций), без необходимости взаимодействия с ОС (без OCALL). Используя спин-блокировку, вы можете сами реализовать примитивы более высокого уровня.
- sgx_thread_mutex_init () также не создает OCALL. Структура данных мьютекса инициализируется внутри анклава.
- sgx_thread_mutex_lock () и unlock потенциально выполняют OCALLS. Однако, поскольку данные мьютекса находятся внутри анклава, они всегда могут обеспечить правильность блокировки в безопасном анклаве.
Глядя на описания функций мьютекса, я предполагаю, что OCALL служат для реализации незанятого ожидания вне анклава. Это действительно обрабатывается операционной системой и подвержено атакам. ОС может решить не будить поток, ожидающий за пределами анклава. Но он также может прервать поток, работающий внутри анклава. SGX не защищает от DoS-атак (отказ в обслуживании) со стороны (потенциально скомпрометированной) ОС.
Подводя итог, можно сказать, что спин-блокировки (и, следовательно, любая синхронизация более высокого уровня) могут быть надежно реализованы внутри анклава. Однако SGX не защищает от DoS-атак, и поэтому вы не можете предполагать, что поток будет работать. Это также относится к блокирующим примитивам: поток, ожидающий мьютекс, может не проснуться, когда мьютекс освобожден. Осознавая это внутреннее ограничение, разработчики SDK решили использовать (недоверенные) OCALL для эффективной реализации некоторых примитивов синхронизации (т. Е. Ожидание незанятости).
[1] SGX SDK Guide
[2] Объяснение SGX
qweruiop, относительно вашего вопроса в комментарии (мой ответ слишком длинный для комментария):
Я бы все еще считал это атакой DoS: ОС, которая управляет ресурсами анклавов, отказывает в доступе T к времени обработки ресурсов ЦП. Но я согласен, вам нужно спроектировать другие потоки, работающие в этом анклаве, осознавая, что T никогда не сможет работать. Семантика отличается от запуска потоков на платформе, которой вы управляете. Если вы хотите быть абсолютно уверены, что проверяется переменная условия, вы должны делать это на платформе, которой вы управляете.
Sgx_status_t, возвращаемое каждой прокси-функцией (например, при превращении ECALL в анклав), может возвращать SGX_ERROR_OUT_OF_TCS
, Таким образом, SDK должен обрабатывать все потоки за вас - просто создайте ECALL из двух разных ("ненадежных") потоков A и B вне анклава, и поток выполнения должен продолжаться в двух ("доверенных") потоках внутри анклава, каждый из которых связан с отдельный TCS (при условии, что доступны 2 неиспользованных TCS).