10个版本 (5个重大更新)

0.6.3 2022年8月8日
0.6.2 2022年7月28日
0.5.1 2022年5月24日
0.4.0 2022年4月11日
0.1.0 2021年10月20日

#132 in 无标准库


4 crates 中使用

Apache-2.0

285KB
7K SLoC

sallyport

虚拟机微内核边界的API

sallyport 是一个用于代理从 Enarx Keep 到宿主机的服务请求(如系统调用)的协议库。一个 sally port 是一个安全的网关,通过这个网关,防御军队可以从他们的防御工事中“出击”。

作用机制

sallyport 通过向主机提供执行系统调用所需的最低限度的寄存器上下文来工作。通过这种方式,主机可以立即调用所需的系统调用,而不需要任何额外的逻辑。

客户机和主机通过一个相互不信任的共享内存块进行通信。

此库为客户端提供通过代理请求到主机的不受信任块的功能,以及为主机执行不受信任块中包含的请求的功能。

块格式

Sallyport 是包含零个或多个 的内存区域。所有项都包含以下

  • 大小: usize
  • 类型: usize

大小参数包括项的完整长度(不包括头值)。项的内容由 类型 参数的值定义。具有未知 类型 的项可以被跳过,因为项的长度可以从 大小 字段中得知。收到未知 类型 项的接收者不得以任何方式解释或修改项的内容。

类型

  • END0
  • SYSCALL1
  • GDBCALL2
  • ENARXCALL: 3

结束

END项必须具有size0的大小。它没有内容,仅简单标记了该块中项的结束。这向主机传达了项列表的结束。然而,在返回到虚拟机时,虚拟机不得依赖于存在终止符。

系统调用

SYSCALL项包含以下内容

  • nmbr: usize - 系统调用号
  • arg0: usize - 第一个参数
  • arg1: usize - 第二个参数
  • arg2: usize - 第三个参数
  • arg3: usize - 第四个参数
  • arg4: usize - 第五个参数
  • arg5: usize - 第六个参数
  • ret0: usize - 第一个返回值
  • ret1: usize - 第二个返回值
  • data: ... - 可以引用的数据(可选)

GDB调用

GDBCALL项包含以下内容

  • nmbr: usize - GDB调用号
  • arg0: usize - 第一个参数
  • arg1: usize - 第二个参数
  • arg2: usize - 第三个参数
  • arg3: usize - 第四个参数
  • ret: usize - 返回值
  • data: ... - 可以引用的数据(可选)

Enarx调用

ENARXCALL项包含以下内容

  • nmbr: usize - Enarx调用号
  • arg0: usize - 第一个参数
  • arg1: usize - 第二个参数
  • arg2: usize - 第三个参数
  • arg3: usize - 第四个参数
  • ret: usize - 返回值
  • data: ... - 可以引用的数据(可选)

参数值可能包含数值。然而,所有指针都必须转换为从数据区开始处的偏移量。

示例

以下是如何使用sallyport协议在主机和受保护的虚拟机之间代理系统调用的示例

  1. Keep内部的工作负载执行了一个write系统调用。
  2. shim捕获了所有系统调用,并注意到这是一个write系统调用。
  3. shim为项头、系统调用号、六个参数、两个返回值、工作负载想要写入的尽可能多的字节数以及一个END项头分配空间。
  4. shim写入项头、参数值并将工作负载想要写入的字节复制到块的日期区域。现在它对主机是可访问的。
  5. shim写入分配的区段。在write系统调用的例子中,shim
    1. 写入项头,将项kind设置为Syscall,大小等于9 + 要写入的字节数(系统调用号 + 参数 + 返回值 + 数据长度)。
    2. 写入请求nmbr,等于Linux整数值SYS_write
    3. 写入系统调用参数和返回值
      1. arg0 = 要写入的文件描述符。
      2. arg1 = 从最后一个返回值之后开始的偏移量,字节已复制到此处。
      3. arg2 = write 系统调用应该从第二个参数指向的字节中发出的字节数。
      4. arg3 = NULL
      5. arg4 = NULL
      6. arg5 = NULL
      7. ret0 = -ENOSYS
      8. ret1 = 0
    4. 将要写入的字节复制到已分配的区域。
  6. Shim 将控制权交给不可信的主机,在主机端 Enarx 代码意识到它必须代理一个系统调用。
  7. 主机端 Enarx 代码可以使用块中的值立即调用系统调用。
  8. 一旦系统调用完成,主机端 Enarx 代码可以更新系统调用返回值区域,将系统调用的返回代码写入其中。
  9. 主机端 Enarx 代码将控制权返回给 shim。
  10. shim 检查块并将任何修改后的数据传播回受保护地址空间。然后它可以将其控制权返回给其工作负载。

许可:Apache-2.0

依赖关系

~1MB
~19K SLoC