4个版本 (重大更新)

0.4.0 2024年4月25日
0.3.0 2022年11月11日
0.2.0 2022年4月15日
0.1.0 2021年10月26日

编码 中排名 726

Download history 153/week @ 2024-04-21 7/week @ 2024-04-28 10/week @ 2024-05-19 25/week @ 2024-05-26 13/week @ 2024-06-02 10/week @ 2024-06-09 3/week @ 2024-06-16 3/week @ 2024-06-23 1/week @ 2024-06-30 1/week @ 2024-07-07

每月下载量 228

Apache-2.0 OR BSD-3-Clause

120KB
1.5K SLoC

vm-superio

vm-superio 提供了旧版设备的模拟。目前,它仅为此提供以下支持:Linux串行控制台,最简的 i8042 PS/2 控制器ARM PL031 实时时钟。为了启用快照使用案例,如实时迁移,它还提供保存和恢复状态以及持久化的支持。为了实现这一点,并保持关注点的清晰分离,vm-superio 是一个 工作区,包含以下crate

  • vm-superio - 保留组件的状态;
  • vm-superio-ser - 从 vm-superio 反映状态结构并添加所需的版本约束,并推导/实现所需的(反)序列化特性(即 serdeSerializeDeserializeVersionize)。

串行控制台

设计

控制台模拟是通过模拟一个简单的 64 字节 FIFO 的 UART 16550A 串行端口 来实现的。这个UART是原始 UART 8250 串行端口 的改进,主要是因为FIFO缓冲区允许同时存储多个字节,这在虚拟化环境中是必不可少的。

为了VMM能够使用此设备,除了此crate中涵盖的模拟部分外,VMM还需要执行以下操作

  • 将串行端口添加到总线(无论是PIO还是MMIO)
  • 定义串行后端
  • 事件处理(可选)

以下UART寄存器通过Serial结构体进行仿真:DLL、IER、DLH、IIR、LCR、LSR、MCR、MSR和SR(有关这些寄存器的简要但不错的介绍,请参阅此处)。Fifo控制寄存器(FCR)未进行仿真;目前尚不支持直接控制FIFO(在本实现中,FIFO始终处于启用状态)。串行控制台仅实现了RX FIFO(及其对应的RBR寄存器)。RX缓冲区有助于在环回模式下测试UART,以及在单次向客户机发送更多字节时。TX FIFO通过立即将来自驱动器的字节写入一个io::Write对象(例如,可以是io::Stdoutio::Sink)来实现,该对象必须在使用初始化串行控制台时提供。一个Trigger对象是目前用于通知驱动器需要处理的事件的输入/输出事件的当前机制。

威胁模型

可信参与者

  • 宿主内核

不可信参与者

  • 客户机内核
  • 客户机驱动程序

不可信参与者可以通过在设备驻留的地址上对总线进行读写操作来改变设备的状态。

#NR 威胁 缓解措施
1 恶意客户机通过淹没串行控制台输入生成大量内存分配。 CVE-2020-27173 串行控制台将串行控制台输入对应的FIFO元素数量限制为FIFO_SIZE(=64),当达到限制时返回FIFO Full错误。此错误必须由软件包客户处理。当串行控制台输入连接到事件循环时,客户必须确保在FIFO中没有空间时,循环不会被不可信来源的事件淹没。
2 恶意客户机可以通过生成大量要写入串行输出的数据来填满宿主磁盘。 在仿真层中无法进行缓解,因为我们没有控制输出(Writer)。这需要在VMM层通过添加速率限制机制来解决。我们建议使用具有固定大小(例如环形缓冲区或命名管道)的资源作为输出。

用法

在仿真级别,串行控制台与其驱动程序之间的交互是通过两个readwrite特定方法完成的,它们处理单字节访问。对于发送更多输入,可以使用enqueue_raw_bytes

i8042 PS/2控制器

到目前为止,i8042 PS/2控制器仅仿真了CPU复位命令,这是通知VMM关于客户机关机所需的。

ARM PL031实时时钟

本模块仿真了ARM PrimeCell实时时钟(RTC)PL031。PL031提供了一个长时间基计数器,具有1Hz计数器信号和一个可配置的偏移量。

此实现仿真了所有控制、外围ID和PrimeCell ID寄存器;然而,基于匹配寄存器(RTCMR)值的中断目前尚未实现(即,设置匹配寄存器没有任何效果)。

为了使VMM能够使用此设备,VMM需要执行以下操作:

  • 将RTC添加到总线( PIO 或 MMIO)
  • 提供一个结构体,实现RTCEvents以跟踪重要事件的发生(可选)

请注意,由于匹配寄存器是事件发生的唯一可能来源,而匹配寄存器目前尚未实现,因此无需事件处理。

威胁模型

可信参与者

  • 宿主内核

不可信参与者

  • 客户机内核
  • 客户机驱动程序

不可信参与者可以通过在设备驻留的地址上对总线进行读写操作来改变设备的状态。

#NR 威胁 缓解措施
1 恶意虚拟机向加载寄存器写入无效值,以在随后的数据寄存器读取操作中造成溢出。 RTC中的算术运算检查溢出。当出现这种情况时,设备的状态会被重置。
2 恶意虚拟机从无效偏移量(不对应于RTC寄存器)进行读取和写入操作,以引起崩溃或获取访问权限。 通过模拟拒绝无效偏移量的读取和写入,并调用一个invalid_read/write事件。VMM可以实现这些事件,并将它们扩展到生成警报(例如,停止恶意虚拟机的执行)。

保存/恢复状态支持

以下抽象提供了对RtcSerial设备的支持:

  • <Device>State -> 保存<Device>的硬件状态;
  • <Device>StateSer -> 可以供需要<Device>同时是(De)Serialize和/或Versionize的客户使用。如果客户想要与上游不同的状态,那么他们可以在他们的产品中实现From(或类似的机制)以将上游状态转换为所需的产品状态。

有关rust-vmm中保存/恢复状态支持的详细设计文档,请参阅此处

vm-superiovm-superio-ser版本之间的兼容性

每次从vm-superio的状态发生变化时,都需要将该变化传播到相应的vm-superio-ser状态。为了保持这两个crate发布版本之间的兼容性,一旦我们有了vm-superio的新版本,该版本意味着vm-superio-ser有所变化,我们还需要有vm-superio-ser的新版本。因此,vm-superio-ser crate将vm-superio的确切版本作为依赖项。

许可证

本项目采用以下任一许可证:

依赖项

~2.5MB
~54K SLoC