乐趣区

关于内核:谁来拯救存量SGX1平台又一个内核特性合并的血泪史

简介:明天的故事配角,是一个被称为 Flexible Launch Control 的 SGX 平台个性。

前言

自从 Intel 内核开发人员 Jarkko Sakkinen 于 2017 年 9 月 2 日在 intel-sgx-kernel-dev@lists.01.org 邮件列表上收回 v1 版的 SGX in-tree 驱动以来,工夫曾经过来了 3 年多了。这期间这个驱动前前后后共批改了 41 个版本,终于在 2020 年 11 月 13 日,v41 版本的补丁合入了 5.11-rc1 内核。Jarkko 松了一口气,工作实现啦!不过,为什么合并一个一般的驱动模块会这么难?

事实上,因为 SGX 所代表的新的秘密计算畛域的特殊性,围绕着它的争议和探讨就从未进行过。甚至在最终的 v41 补丁中,也没能看到大佬们整齐划一的 LGTM(社区黑话,Looks Good To Me 的缩写,示意本人认可这个补丁),它仍旧存在一些问题,同时还有人在一直提出批改倡议。这不禁让人联想到另一个 x86 处理器个性 FSGSBASE 合入 upstream 时的命运多舛:后者的合入前后花了 5 年工夫,甚至最初都不是 Intel 的人合入的(当然也不是 AMD 的人合入的😂,大家能够猜猜是谁)。

明天的故事配角,是一个被称为 Flexible Launch Control(简称 FLC)的 SGX 平台个性。对这个个性的争议,最终导致 SGX in-tree 驱动无奈反对不具备 FLC 个性或敞开了 FLC 个性的所有 SGX 零碎。大白话是啥意思呢?意思就是一批较早的反对 Intel SGX 的机器用 Linux 内核自带的官网驱动是无奈加载和应用 SGX 的 …… 纳尼!这个驱动居然不向下兼容!哎,当初让咱们先对 FLC 技术背景进行一个简略的介绍,而后再对其被社区摈弃的故事简略做个复盘,最初再给出咱们的思考,以及咱们的解决方案。

FLC 的技术背景

情谊揭示:想听故事不想理解技术细节的同学请间接跳到下一节。

在执行 SGX EINIT 指令初始化 enclave 的时候,被初始化的 enclave 必须通过 Launch Control 机制的查看,因而 Launch Control 是一种用于管制 enclave 是否启动的安全检查机制。

被初始化的 enclave 分为两类:Launch Enclave 和一般 enclave。Launch Enclave 与一般的 enclave 的不同之处在于其 SECS.ATTRIBUTES.EINITTOKEN_KEY == 1,即具备通过执行 SGX EGETKEY 指令派生出 einit token key 的权限。Einit token 实质上是一个带有 CMAC 签名的 token,其中的 CMAC 是 Launch Enclave 用 einit token key 生成的,意在对 einit token 自身提供完整性爱护;在执行 EINIT 初始化一般 enclave 的时候,从 Launch Enclave 处返回的 einit token 须要作为输出参数的一部分,而后 EINIT 指令的微码会将 einit token 作为派生出 einit token key 的输出因子,最初用派生出的 einit token key 来验证输出的 einit token 中的 CMAC,以确保 einit token 从生成到传给 EINIT 的过程中没有被篡改。

下面的流程中提到的 einit token 完整性检查实用于所有的一般 enclave,而对于 Launch Enclave,再执行 EINIT 初始化时有非凡解决。上面是在执行 EINIT 时残缺的 Launch Control 流程:

image.gifC05A1907-7AF2-47e3-B8C3-5F743C36AE8F.png

(下面的流程图是对 Intel SDM 手册中对于 EINIT 指令在微架构层的执行流程进行的总结;其中 Launch Enclave 验证两次 IA32_SGXLEPUBKEYHASH 的逻辑应该是冗余的,但咱们还是依照原始流程的逻辑把它给残缺地画进去了)

能够简略地将上述流程总结为以下两点规定:

1. 只有在初始化 enclave 时能提供非法的 einit token, 就能通过 Launch Control 的查看。

  1. 如果在初始化 enclave 时没有提供非法的 einit token, 则 enclave 的 MRSIGNER 必须与 IA32_SGXLEPUBKEYHASH 的值统一。

此外,还能够从第二点规定推导出实用于 Launch Enclave 的非凡规定:

  1. Launch Enclave 必须可能通过 IA32_SGXLEPUBKEYHASH 的校验能力被初始化。
  2. 通过 EINIT 初始化 Launch Enclave 的时候,能够不提供 einit token。

在处理器复位时,IA32_SGXLEPUBKEYHASH 的默认值是 Intel 的 MRSIGNER。如果处理器不反对 FLC,任何一般的 enclave 在初始化时,必须持有非法的 einit token,而负责颁发 einit token 的 Launch Enclave 则能够制订本人的策略来决定是否给一个一般 enclave 颁发 einit token。具体到 Intel 在不反对 FLC 的 SGX1 上施行的策略则是:用户运行的 enclave 必须是由 Intel 受权的密钥签过的,这样能力失去 Intel 开发的 Launch Enclave 的受权,并取得 einit token,否则用户无奈运行本人开发的一般 enclave(严格讲是无奈运行产品级的一般 enclave,debug 级的一般 enclave 还是能够运行的)。

这就是利用 Launch Control 达成的管制成果:谁把握 Launch Enclave,谁管制一般 enclave 的运行受权。

相同,如果处理器反对 FLC 且 BIOS 没有锁死 IA32_SGXLEPUBKEYHASH,IA32_SGXLEPUBKEYHASH MSRs 对系统软件不仅可见而且可写,配合 SGX in-tree 驱动就能够实现如下性能:每当加载任意 enclave 时,都无条件将其 MRSIGNER 写入到 IA32_SGXLEPUBKEYHASH 中,从而绕过 Launch Control 机制,也就是说所有一般 enclave 都能像 Launch Enclave 那样无需提供非法的 einit token。FLC 中的 F,指的就是 IA32_SGXLEPUBKEYHASH 寄存器在某些状况下是可写的。至于要不要利用它绕过 Launch Control 机制,则是具体的实现策略问题,而 SGX in-tree 驱动就恰好采取了绕过 Launch Control 的策略,起因是 Linux kernel 不心愿提供对配置锁定的零碎提供反对。

至于这种策略是否正确,咱们暂先不探讨。先劳动下,听听故事。

故事脉络

故事的导火索出自 v22 SGX in-tree 驱动。这里作者 Jarkko 定义了处理器是否反对 FLC 的 bit,并对 FLC 的作用进行了阐明。注意作者的最初一段话:

“内核不会对某种被锁定的配置提供反对,因为这夺走了内核(对启动 enclave)的启动控制权。”联合后面对于 FLC 的技术原理解说,这里的锁定指的就是如果 BIOS 锁死了 IA32_SGXLEPUBKEYHASH,那么一般 enclave 的运行形式就要被 Intel 的 Launch Enclave 的受权策略所管制。这段形容引起了 Reviewer Borislav 的警惕,并给出了硬核回复:如果 FEATURE_CONTROL_SGX_LE_WR 位决定了 IA32_SGXLEPUBKEYHASH 是否被锁死,那么谁管制的 FEATURE_CONTROL_SGX_LE_WR 位?内核可能管制吗?我可不想让该死的 BIOS 去管制,真出点啥问题咱们本人能搞定,用不着看 OEM 的脸色。

这时候另一个作者 Sean 站进去答复了 reviewer 的问题:

“是的,就是 BIOS 管制着 FEATURE_CONTROL_SGX_LE_WR 位。这个咱们都想好了,FEATURE_CONTROL_SGX_LE_WR 位如果为 0,那咱们就把 SGX 性能齐全禁止掉。这个想法在第四个补丁里有具体实现。”到目前看起来还是失常的社区 review 流程,大家也比拟温和,直到 reviewer 看过了第四个补丁的内容。首先咱们本人先看下第 4 个补丁到底干了什么:

+static void __maybe_unused detect_sgx(struct cpuinfo_x86 *c)
+{
+  unsigned long long fc;
+
+  rdmsrl(MSR_IA32_FEATURE_CONTROL, fc);
...
+  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);
+}

一句话形容这段代码的含意就是:如果 FEATURE_CONTROL_SGX_LE_WR 位为 0(一种状况是 BIOS 锁死了 IA32_SGXLEPUBKEYHASH,另一种状况是平台不反对 FLC)的话,意味着 MSR_IA32_SGXLEPUBKEYHASH{0, 1, 2, 3}这四个 MSR 寄存器对内核来说就是只读或者不可见的,那么内核也就无法控制一般 enclave 的启动,这是 Linux upstream 不想看到的状况。对此,代码会简略地分明掉 FLC 的 cpu feature flag,但会保留其余 SGX 相干的 cpu feature flag。

Borislav 此刻的情绪必定是:(⇀‸↼‶) 这和你后面说的不一样啊?这哪里是你所谓的“把 SGX 性能齐全禁止掉”了??你明明只是革除了 FLC cpu feature flag,没有齐全禁止 SGX 性能啊!!!难道是我的了解有问题吗?

作者 Sean 应该是晓得本人说错话了,没有回复这个问题;而 Borislav 此刻只想要一个货色:MSR_IA32_SGXLEPUBKEYHASH{0, 1, 2, 3}这四个 MSR 寄存器对内核来说必须可写!

而后作者 Sean 开始摆事实讲道理:还有好多不反对 FLC 或者禁用 FLC(即 BIOS 可能非故意地锁死了 IA32_SGXLEPUBKEYHASH)的 SGX 的平台啊!

Sean 说这句话的时候是在 2019 年 9 月 25 日,其实现在来看这句话仍旧正确。

Borislav 没有被压服,并且开始谈起 BIOS 是如许的“蹩脚”,并屡次提到不想提供对带有配置锁定的零碎的反对:

Linux 以及开源社区一贯恶感各种配置锁定和 DRM。笔者印象中早些年 Win7 刚进去时强行默认开 UEFI Secure Boot 且 BIOS setup 中不提供敞开选项导致无奈装置 Linux,这让开源社区十分不爽,通过 Linux Foundation、Intel 和微软的交涉,才最终有了明天的 shim bootloader。当然,终端用户不必本人去找微软签名 bootloader,这是每个 Linux 发行版本本人找微软签名的事件了,而且这个默契也曾经继续很久了。

最初作者 Sean 认了,并且说咱们原本就是那么想的:

一口老血喷了进去!合着后面的迷之发言逗咱们玩呢???显然作者 Sean 的逻辑呈现了矛盾,他说他的本意其实是这样的:

“即便 MSR_IA32_SGXLEPUBKEYHASH 不可写,但咱们仍旧保留其余 SGX cpu feature flag,好让用户明确到底是我的零碎不反对 SGX 硬件能力,还是因为短少 FLC 性能导致无奈运行一般的 enclave,当初看起来可能是我想多了。”对于 Sean 的这个论断,须要这样了解:尽管在不反对 FLC 或禁用 FLC 的平台上仍旧可能运,debug 级的一般 enclave,然而 debug 级的 enclave 是可能被 sgx-gdb 通过非凡的 enclave debug 指令拜访到 enclave 中的敏感数据的,因而 debug 级的 enclave 不适宜于生产环境;要运行不能被 debug 的产品级 enclave,就必须要恪守 Intel 的 Launch Enclave 的受权策略,但这须要施行一些对常人来说不具可施行性的操作,这与个别用户想简略地就能运行一般 enclave 的需要的确相悖,因而大多数状况下,不反对 FLC 或禁用 FLC 就等价于用户无奈运行一般 enclave,而 cpu feature flag 能够反映出起因。

最终,从 v25 开始,如果处理器不反对 FLC,所有 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();
+  }

不过这个做法真的对么?难道不反对 FLC 或禁用 FLC 的平台就不应该失去 SGX in-tree 驱动的反对吗?

思考

答复这个问题前,咱们先看下目前 Intel 对 SGX 驱动的反对状况。

除了 SGX in-tree 驱动,Intel 在开源社区还提供了 SGX Legacy 驱动。这个 SGX 驱动是因为漫长的 review 流程而逐步昌盛起来的副产物,目标是在规范内核尚不反对 SGX 的状况下满足用户对 SGX 平台的撑持需要。这个 SGX Legacy 驱动反对没有 FLC 的平台,也是目前反对 SGX1 平台的惟一抉择。能够预感,在 SGX in-tree 驱动合入到 upstream 后,这个驱动会逐渐退出历史的舞台,那么问题也来了。

首先,即便具备大量 EPC 内存的 SGX2 机器曾经上线了(能够参考阿里云的 SGX2 邀测申请链接:https://pages.aliyun.com/aliy…),然而仍有一批存量 SGX1 平台正在退役;此外,采纳 Intel client platform 的 CPU 很多都反对 SGX 但不反对 FLC,难道这些平台的用户未来就只能用着短少新个性反对的 SGX Legacy 驱动吗?

其次,有些人肯定曾经提前思考到须要将现有业务利用拿到基于 SGX in-tree 驱动的环境里跑一跑,测一测 SGX in-tree 驱动自身的性能和稳定性,因而在不足 SGX2 平台的状况下,也须要 SGX in-tree 驱动可能反对 SGX1 平台。

最初,不反对 FLC 和禁用 FLC 其实是两码事。被社区真正诟病的是老的 SGX1 平台不反对 FLC,进而只能被逼施行不具可施行性的 Launch Enclave 运行受权;到了反对 FLC 平台个性的时代,即使禁用了 FLC,但只有锁定的内容是用户可控的,或者是施行一种更为宽松的 Launch Enclave 运行受权,那么这种配置锁定也是无益的。就拿云租户应用裸金属服务器的场景为例:即便 CSP 在 BIOS 里禁用了 FLC,只有 CSP 在本人定制的 Launch Enclave 中确保非法的云租户能失常运行该租户本人签的 enclave 就能够了,而这其实这反倒是为租户多减少了一重爱护。如果像当初 SGX in-tree 驱动的这种实现形式,包含胜利入侵到零碎的攻击者都能够任意运行本人编写的歹意 Enclave 了。

那咱们该怎么办呢?

解决方案

咱们的观点还是想大家之所想,急大家之所急。依据目前的理论状况,Inclavare Containers 开源项目组(https://github.com/alibaba/in…)编写了几个补丁,目标就是让不反对 FLC 或禁用 FLC 的零碎可能运行 SGX in-tree 驱动。补丁的应用和验证办法详见:https://github.com/alibaba/in…

目前咱们曾经在 SGX1 机型中胜利部署了这种运行形式,并理论利用于 Inclavare Containers 开源我的项目的 CI/CD 测试中。

此外,Inclavare Containers 开源我的项目会研发一个反对用户自定义策略的 Launch Enclave;目标是晋升用户管制的平台的安全性,即只容许运行用户预期的一般 enclave,杜绝攻击者在用户平台上运行歹意 enclave 的状况呈现。

最初有几个要害概念的关系要再次廓清,重点揭示下大家:

  1. 是否反对 FLC 和 CPU 是否反对 SGX1/ 2 没有关系;SGX1/ 2 是处理器 SGX 架构的指令集个性;FLC 是平台个性。
  2. 之所以强调 SGX1 和 FLC 的关系,是因为 FLC 是在 SGX1 和 SGX2 之间呈现的平台个性,因而很多 SGX1 平台都短少 FLC 个性。
  3. 即便是在反对 FLC 的平台,只有在 BIOS 中禁用了 FLC(不论是出于平安起因禁用,还是 BIOS 不反对 FLC,或是被 CSP 锁定),都会像不反对 FLC 的 SGX1 平台那样遇到雷同的问题。兴许到了咱们能把这个问题像下面提到的那样做到真正的精细化解决,即可能明确辨别出“平台控制权民主化”和“非预期的平台配置锁定”并为前者提供切实的平安解决方案的时候,咱们会再给社区发送一组 patch,以容许 SGX in-tree 驱动反对那些用户明确心愿禁用 FLC 的平台。(完)

原文链接
本文为阿里云原创内容,未经容许不得转载。

退出移动版