SGX in-tree驱动的内幕

2020-08-12 · 乾越 ·

故事背景

众所周知,由于upstream对SGX in-tree驱动的实现存在很多争议并引发了诸多讨论,其中较大的一个关于FLC的争议最终导致SGX in-tree驱动不得不放弃基于Lauch Control的launch enclave生成token”的机制。这里对这个故事背景进行一下复盘。

事情出自v22 SGX in-tree驱动

Reviewer Borislav对作者的这段SGX Lauch Control特性的检测逻辑进行了“批判”:

+static void __maybe_unused detect_sgx(struct cpuinfo_x86 *c)
+{
+   unsigned long long fc;
+
+   rdmsrl(MSR_IA32_FEATURE_CONTROL, fc);
+   if (!(fc & FEATURE_CONTROL_LOCKED)) {
+       pr_err_once("sgx: The feature control MSR is not locked\n");
+       goto err_unsupported;
+   }
+
+   if (!(fc & FEATURE_CONTROL_SGX_ENABLE)) {
+       pr_err_once("sgx: SGX is not enabled in IA32_FEATURE_CONTROL MSR\n");
+       goto err_unsupported;
+   }
+
+   if (!cpu_has(c, X86_FEATURE_SGX1)) {
+       pr_err_once("sgx: SGX1 instruction set is not supported\n");
+       goto err_unsupported;
+   }
+
+   if (!(fc & FEATURE_CONTROL_SGX_LE_WR)) {
+       pr_info_once("sgx: The launch control MSRs are not writable\n");
+       goto err_msrs_rdonly;
+   }
+
+   return;
+
+err_unsupported:
+   setup_clear_cpu_cap(X86_FEATURE_SGX);
+   setup_clear_cpu_cap(X86_FEATURE_SGX1);
+   setup_clear_cpu_cap(X86_FEATURE_SGX2);
+
+err_msrs_rdonly:
+   setup_clear_cpu_cap(X86_FEATURE_SGX_LC);
+}

可以看出,如果BIOS锁死了FEATURE_CONTROL_SGX_LE_WR位并且设为0的话,内核就无法写MSR_IA32_SGXLEPUBKEYHASH{0, 1, 2, 3}这四个寄存器,进而无法达成“内核控制Enclave的初始化和运行”这个目的;也就是说,加载和运行一个Enclave就需要持有合法的token才可以,而负责颁发token的Launch Enclave则可以制定自己的策略来决定是否给一个Enclave颁发token,这就是所谓的Launch Control机制。作者在这里针对这种情况,仅仅是清除了X86_FEATURE_SGX_LC特性位,而保留了SGX的其他特性。

但Reviewer发现了这个问题,并敏锐地提了出来: 屏幕快照 2020-07-29 下午10.54.57.png

然后作者开始摆事实讲道理: 屏幕快照 2020-07-29 下午11.01.25.png

Reviewer依旧不依不饶,并且开始喷起BIOS是多么的“糟糕”(还有更糟糕的词汇,自己搜吧): 屏幕快照 2020-07-29 下午11.06.19.png

好吧,这个决定导致从v25开始,如果处理器不支持FLC(包括SGX1这种完全不支持FLC的系统,以及虽然支持但BIOS把X86_FEATURE_SGX_LC特性位清0的系统),所有SGX特性都将无法使用

+update_sgx:
+   if (!cpu_has(c, X86_FEATURE_SGX) || !cpu_has(c, X86_FEATURE_SGX_LC)) {
+       clear_sgx_caps();
+   } else if (!(msr & FEAT_CTL_SGX_ENABLED) ||
+          !(msr & FEAT_CTL_SGX_LC_ENABLED)) {
+       if (IS_ENABLED(CONFIG_INTEL_SGX))
+           pr_err_once("SGX disabled by BIOS\n");
+       clear_sgx_caps();
+   }

好吧。其实reviewer的观点一开始就说了: 屏幕快照 2020-07-29 下午11.06.45.png

Linux以及开源社区一向反感各种lockdown和DRM,我印象中早些年Win7刚出来时强行默认开UEFI Secure Boot且BIOS setup中不提供关闭选项导致无法安装Linux,这让Linux社区震怒,最后社区和微软交涉才有了今天的shim bootloader(当然,终端用户不用自己去找微软签名bootloader,这是每个Linux发行版本自己找微软签名的事情了,而且这个默契也已经持续很久了)。


个人观点

对此我的观点是:务实。

首先,即使具备大量EPC内存的SGX2机器已经上线了,我们测试网内的开发机一般都是老旧淘汰机型,SGX1就属于这种,难道就只能用着不再维护的SGX OOT驱动了(OOT驱动支持没有FLC的SGX1机型)?

其次,况且现在SGX2机器还没有上线,样机也要晚些时候才ready,而目前我手上有很高优先级的任务需要做SGX in-tree驱动的适配,因此急需SGX in-tree驱动能够支持SGX1机型。

最后,在云场景中,对于云租户来说,即使CSP在BIOS里将Lauch Control锁定了,只要CSP在自己定制的Launch Enclave中确保合法的云租户能正常运行该租户自己签的enclave就可以了,其实这反倒是增加了一重保护。如果像现在SGX in-tree驱动的这种实现模式,等于任何非特权用户(包括成功入侵的攻击者)都可以任意运行自己编写的Enclave了(包括恶意Enclave)。

所以根据目前实际情况,我编写了两个补丁,希望能让目前在手头上不支持FLC的SGX1系统上能够运行SGX in-tree驱动,并基于该驱动实现自己需要的上层特性。


补丁使用方法


补丁功能验证方法

在不支持FLC的SGX1机型上安装并运行打过patch的内核和aesm service。

目前我们已经在SGX1机型中成功部署了这种运行方式,并用于Inclavare Containers开源项目的社区release测试中。


后续工作

  • 希望能将PSW的patch推进到upstream中(还需要加入自动检测代码来动态设置no_sgx_flc这个flag)。
  • 希望能把内核patch合入AliOS内核中。
  • 在用户态把FLC的检测做了,免去还要手动指定参数的麻烦。

参考