Occlum是基于Intel SGX的内存安全、多进程库操作系统(LibOS)。 作为LibOS,它允许应用程序在SGX上运行,而不需要修改源代码或者只需要少量修改源代码,从而保护了用户工作负载的机密性和完整性。
Occlum有以下显著特征:
如果您要使用SGX SDK编写SGX Hello World项目,该项目将包含数百行代码。 要做到这一点,您必须花费大量的时间来学习api、编程模型和SGX SDK的构建系统。
多亏了Occlum,你可以从编写任何额外的SGX-aware的代码中解放出来,只需要键入一些简单的命令来明确保护SGX应用程序——四个简单的步骤即可。
步骤1。 用Occlum toolchain(例如,occlum-gcc) 编译用户程序
$ occlum-gcc -o hello_world hello_world.c
$ ./hello_world
Hello World
注意,Occlum toolchain不是传统意义上的交叉编译:Occlum toolchain构建的二进制文件也可以在Linux上运行。 这个属性可以方便地编译、调试和测试面向Occlum的用户程序。
步骤2。 通过occlum init或occlum new初始化一个文件夹为Occlum实例
$ mkdir occlum_instance && cd occlum_instance
$ occlum init
或者
$ occlum new occlum_instance
occlum init命令在当前工作目录中创建occlum的编译时和运行时状态。 occlum new命令做了基本相同的事情,但在一个新的实例目录。 每个Occlum实例目录应该用于应用程序的单个实例; 多个应用程序或一个应用程序的不同实例应该使用不同的Occlum实例。
步骤3。 通过Occlum build构建生成一个安全的Occlum文件镜像和Occlum SGX enclave
$ cp ../hello_world image/bin/
$ occlum build
image directory的内容由occlum init命令初始化。image directory的结构类似于普通UNIX FS,包含/bin、/lib、/root、/tmp等目录。 在将用户程序hello_world复制到image/bin/后,image directory被occlum build命令打包,生成一个安全的occlum FS image以及occlum SGX enclave。 默认情况下,FS image是完整性保护的,如果您想用自己的密钥保护机密性和完整性,请在这里查看。
对于不支持SGX的平台,也可以在SGX模拟模式下运行Occlum。 要切换到模拟模式,occlum构建命令必须提供一个额外的参数或环境变量,如下所示:
$ occlum build --sgx-mode SIM
或
$ SGX_MODE=SIM occlum build
步骤4。 通过occlum run在SGX enclave内部运行程序
$ occlum run /bin/hello_world
Hello World!
occlum run命令启动一个occlum SGX enclave,它在后台验证并加载相关的occlum FS image,生成一个新的LibOS进程来执行/bin/hello_world,并最终打印消息。
Occlum可以通过一个名为Occlum.json的配置文件轻松配置。 它是由occlum init命令在Occlum实例目录中生成的。 用户可以修改Occlum.json来配置Occlum。 Occlum.json示例如下所示。 添加了一些注释以提供简短的解释。 如果您不确定如何为您的应用程序设置resource_limits或进程,请查看资源配置指南。
{
// Resource limits
"resource_limits": {
// The total size of enclave memory available to LibOS processes
"user_space_size": "256MB",
// The heap size of LibOS kernel
"kernel_space_heap_size": "32MB",
// The stack size of LibOS kernel
"kernel_space_stack_size": "1MB",
// The max number of LibOS threads/processes
"max_num_of_threads": 32
},
// Process
"process": {
// The stack size of the "main" thread
"default_stack_size": "4MB",
// The max size of memory allocated by brk syscall
"default_heap_size": "16MB",
// The max size of memory by mmap syscall
"default_mmap_size": "32MB"
},
// Entry points
//
// Entry points specify all valid path prefixes for <path> in `occlum run
// <path> <args>`. This prevents outside attackers from executing arbitrary
// commands inside an Occlum-powered enclave.
"entry_points": [
"/bin"
],
// Environment variables
//
// This gives a list of environment variables for the "root"
// process started by `occlum exec` command.
"env": {
// The default env vars given to each "root" LibOS process. As these env vars
// are specified in this config file, they are considered trusted.
"default": [
"OCCLUM=yes"
],
// The untrusted env vars that are captured by Occlum from the host environment
// and passed to the "root" LibOS processes. These untrusted env vars can
// override the trusted, default envs specified above.
"untrusted": [
"EXAMPLE"
]
},
// Enclave metadata
"metadata": {
// Enclave signature structure's ISVPRODID field
"product_id": 0,
// Enclave signature structure's ISVSVN field
"version_number": 0,
// Whether the enclave is debuggable through special SGX instructions.
// For production enclave, it is IMPORTANT to set this value to false.
"debuggable": true
},
// Mount points and their file systems
//
// The default configuration is shown below.
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
"source": "./build/mount/__ROOT",
"options": {
"MAC": ""
}
},
{
"target": "/",
"type": "sefs",
"source": "./run/mount/__ROOT"
}
]
}
},
{
"target": "/host",
"type": "hostfs",
"source": "."
},
{
"target": "/proc",
"type": "procfs"
},
{
"target": "/dev",
"type": "devfs"
}
]
}
Occlum添加了几个新的实验命令,为用户提供了更像容器的体验,如下所示:
occlum init
occlum build
occlum start
occlum exec <cmd1> <args1>
occlum exec <cmd2> <args2>
occlum exec <cmd3> <args3>
occlum stop
Occlum通过prlimit syscall (https://man7.org/linux/man-pages//man2/prlimit.2.html和shell内置命令ulimit (https://fishshell.com/docs/current/cmds/ulimit.html)启用了每个进程的资源配置。 欲了解更多信息,请阅读demos/fish/README.md。
我们已经在Ubuntu 18.04上构建并测试了Occlum,无论是否支持SGX硬件(如果CPU不支持SGX, Occlum可以在SGX模拟模式下运行)。 为了给Occlum一个快速的尝试,可以使用Occlum Docker图像通过以下步骤执行:
步骤1-3在主机操作系统(Linux)上执行:
对于旧的IAS驱动(非DCAP):
docker run -it --device /dev/isgx occlum/occlum:[version]-ubuntu18.04
版本在1.41之前的DCAP驱动:
docker run -it --device /dev/sgx/enclave --device /dev/sgx/provision occlum/occlum:[version]-ubuntu18.04
对于v1.41以来的DCAP驱动或in-tree内核驱动:
# Two methods:
# (1) Create softlinks on host
mkdir -p /dev/sgx
cd /dev/sgx && ln -sf ../sgx_enclave enclave && ln -sf ../sgx_provision provision
docker run -it --device /dev/sgx/enclave --device /dev/sgx/provision occlum/occlum:[version]-ubuntu18.04
# (2) Create the docker with privileged mode
docker run -it --privileged -v /dev/sgx_enclave:/dev/sgx/enclave -v /dev/sgx_provision:/dev/sgx/provision occlum/occlum:[version]-ubuntu18.04
步骤4-5是在Docker容器内运行的客户操作系统上完成的:
cd /opt/intel/sgxsdk/SampleCode/SampleEnclave && make && ./app
另外,如果要在不使用Docker的情况下使用Occlum,可以在Ubuntu和CentOS等流行的Linux发行版上分别使用Occlum DEB和RPM包安装Occlum。 这些包为0.16.0以来的每一个发行版提供。 有关包的更多信息,请参见这里。
要从最新的源代码构建Occlum,在Occlum Docker容器中执行以下步骤(可以按照上一节所示准备):
下载Occlum源码
mkdir occlum && cd occlum
git clone https://github.com/occlum/occlum .
准备Occlum的子模块和工具
make submodule
编译和测试Occlum
make
make test
对于不支持Occlum的平台
SGX_MODE=SIM make
SGX_MODE=SIM make test
安装Occlum
make install
这将在/opt/occlum目录下安装occlum命令行工具其他文件。
Occlum Dockerfile可以在这里找到。 使用它直接构建容器或读取它来查看Occlum的依赖关系。
Occlum支持运行1)基于musl libc和2)位置无关的任何可执行二进制文件。 我们选择musl libc而不是Glibc,因为musl libc的代码库比Glibc小10倍,这意味着更小的可信计算基础(TCB)和攻击面。 我们认为这对Occlum来说是一个重要的考虑因素,Occlum的目标是运行在SGX enclaves内的安全关键应用程序。
上述两个需求不仅可以通过Occlum toochain来满足,还可以通过一些Linux发行版(如Alpine Linux)的本地工具链来满足。 我们认为Alpine Linux,一个强调简单和安全的流行Linux发行版,是适合Occlum的自然选择。 我们已经提供了演示(参见Python)来运行来自Alpine Linux包的未经修改的应用程序。
要调试运行在Occlum上的应用程序,可以通过Occlum GDB命令利用Occlum内置的对GDB的支持。 更多信息可以在这里找到。
同时,可以使用occlum mount 命令来访问和操作安全文件系统,以进行调试。 更多信息可以在这里找到。
如果问题的原因似乎不是应用程序,而是Occlum本身,那么我们可以通过查看其日志来了解Occlum的内部工作。 Occlum的日志级别可以通过occlu_log_level环境变量进行调整。 它有六个级别:off, error, warn, debug, info, 以及 trace。 默认值是off,也就是说,根本不显示日志消息。 最详细的级别是跟踪。
默认情况下,occlum build命令在调试模式下构建并标记enclaves。 这些SGX调试模式enclaves仅用于开发和测试目的。 对于生产使用,enclaves必须使用从Intel获得的密钥进行签名(当Flexible Launch Control准备好后,这个限制将被取消),并且禁用SGX调试模式。
Occlum内置支持在release模式下构建和运行Enclaves。 要做到这一点,需要修改Occlum.json中的 metadata-debuggable字段为false。 然后运行下面的命令:
$ occlum build --sign-key <path_to/your_key.pem>
$ occlum run <prog_path> <prog_args>
最终,Enclave是否在release模式下运行应该由可信的客户端通过远程验证Enclave来检查和判断。 在这里查看远程认证演示。
为了减少自托管基础设施的复杂性,可以将基于Occlum的SGX应用部署到支持SGX的公共云上。 例如,我们已经在Azure Kubernetes Service (AKS)上测试并成功部署了Occlum Docker容器。 请查看这个文档了解更多细节。
Occlum正在积极发展。 现在我们将重点放在实现生产环境中所需的更多系统调用和其他特性上。
虽然这个项目仍然不成熟或不稳定(我们已经到达版本1.0.0的一半),我们已经在很少或没有修改源代码情况下,使用Occlum移植许多现实世界的应用程序(如Tensorflow Lite, XGBoost, GCC, Lighttpd等)到SGX。 我们相信当前的Occlum应用已经对许多用户有用,并准备在一些用例中部署。
Occlum高层次架构如下图所示:
这个项目的名字Occlum源于j·k·罗琳(J. K. Rowling)在《哈利·波特》(Harry Potter)系列中创造的大脑封闭术(occlumency)一词。 在《哈利·波特与凤凰社》中,大脑封闭术被描述为:
保护心灵不受外界侵入的魔法。 一个晦涩的魔法分支,但非常有用…… 如果使用得当,大脑封闭术的力量将有助于保护你不被接触或影响。
同样的道理也适用于Occlum,不是针对大脑,而是针对程序:
程序抵御外部侵入的神奇防御。 一个晦涩的技术分支,但非常有用…… 如果使用得当,Occlum的力量将有助于保护您的程序免受访问或影响。
当然,Occlum必须运行在Intel x86并且支持SGX的 cpu上。
本文为从大数据到人工智能博主「xiaozhch5」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。