首先,让我们处理一下你有点不清楚的术语
TCS 启用的 SGX 线程和 SDK 提供的不受信任的线程。
在飞地内,只有“受信任的”线程可以执行。飞地内没有“不受信任的”线程。可能 SDK 指南 [1] 中的下面这句话误导了你:
不支持在 enclave 内创建线程。在 enclave 内运行的线程是在(不受信任的)应用程序中创建的。
不受信任的应用程序必须设置 TCS 页面(有关 TCS 的更多背景信息,请参阅 [2])。那么不受信任的应用程序设置的 TCS 如何成为 enclave 内受信任线程的基础呢?[2]给出了答案:
如果测量了所有 TCS 页面的内容,则 EENTER 仅保证在 enclave 的代码内执行受控跳转。
通过测量 TCS 页面,可以通过 enclave 证明来验证线程的完整性(TCS 定义了允许的入口点)。因此,只有已知良好的执行路径才能在 enclave 内执行。
其次,让我们看看同步原语。
SDK 确实提供了同步原语,您说这些原语不可信,因为它们最终由操作系统提供服务。让我们看一下 [1] 中对这些原语的描述:
- sgx_spin_lock() and unlock operate solely within the enclave (using atomic operations), with no need for OS interaction (no OCALL). Using a spinlock, you could yourself implement higher-level primitives.
- sgx_thread_mutex_init() also does not make an OCALL. The mutex data structure is initialized within the enclave.
- sgx_thread_mutex_lock() and unlock potentially perform OCALLS. However, since the mutex data is within the enclave, they can always enforce correctness of locking within the secure enclave.
Looking at the descriptions of the mutex functions, my guess is that the OCALLs serve to implement non-busy waiting outside the enclave. This is indeed handled by the OS, and susceptible to attacks. The OS may choose not to wake a thread waiting outside the enclave. But it can also choose to interrupt a thread running inside an enclave. SGX does not protect against DoS attacks (Denial of Service) from the (potentially compromised) OS.
To summarize, spin-locks (and by extension any higher-level synchronization) can be implemented securely inside an enclave. However, SGX does not protect against DoS attacks, and therefor you cannot assume that a thread will run. This also applies to locking primitives: a thread waiting on a mutex might not be awakened when the mutex is freed. Realizing this inherent limitation, the SDK designers chose to use (untrusted) OCALLs to efficiently implement some synchronization primitives (i.e. non-busy waiting).
[1] SGX SDK Guide
[2] SGX Explained