8 个版本 (破坏性更新)
0.8.0 | 2024年4月25日 |
---|---|
0.7.0 | 2022年11月11日 |
0.6.0 | 2022年4月15日 |
0.5.0 | 2021年10月26日 |
0.1.1 | 2020年10月14日 |
#82 在 解析器实现
每月16,632次下载
在 2 crates 中使用
98KB
1K SLoC
vm-superio
vm-superio
提供旧设备的模拟。目前,它仅为此提供了对 Linux 串行控制台、一个最小的 i8042 PS/2 控制器 和一个 ARM PL031 实时时钟 的支持。为了启用快照使用案例,例如实时迁移,它还提供了保存和恢复状态以及持久化的支持。为了实现这一点,并保持关注点的清晰分离,vm-superio
是一个 工作区,包含以下 crate
vm-superio
- 保留组件的状态;vm-superio-ser
- 反映vm-superio
中的状态结构,并添加所需的版本约束,并推导/实现所需的(反)序列化特性(即serde
的Serialize
和Deserialize
;Versionize
)。
串行控制台
设计
控制台模拟通过模拟一个带有 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 Control Register(FCR)未进行仿真;目前尚不支持直接控制FIFOs(在本实现中,FIFOs始终启用)。串行控制台仅实现了RX FIFO(及其相应的RBR寄存器)。RX缓冲区有助于在环回模式下测试UART,并在一次发送更多字节到虚拟机时使用。TX FIFO通过立即将来自驱动程序的字节写入一个io::Write
对象(例如,io::Stdout
或io::Sink
)来实现。当初始化串行控制台时必须提供此对象。当前使用的机制是Trigger
对象,用于通知驱动程序需要处理的事件的输入/输出。
威胁模型
可信参与者
- 宿主内核
不可信参与者
- 虚拟机内核
- 虚拟机驱动程序
不可信参与者可以通过在设备驻留的地址上对总线进行读取和写入来更改设备的状态。
#NR | 威胁 | 缓解措施 |
---|---|---|
1 | 恶意虚拟机通过洪水串行控制台输入来生成大量内存分配。 CVE-2020-27173 | 串行控制台将对应于串行控制台输入的FIFO元素数量限制为FIFO_SIZE (=64),当达到限制时返回FIFO Full错误。此错误必须由crate客户处理。当串行控制台输入连接到事件循环时,客户必须确保在FIFO中没有可用空间时,循环不会被不可信来源的事件淹没。 |
2 | 恶意虚拟机可以通过生成大量要写入串行输出的数据来填满宿主磁盘。 | 在仿真层无法缓解威胁,因为我们不控制输出(Writer )。这需要在VMM层通过添加速率限制机制来缓解。我们建议使用具有固定大小的资源(例如环形缓冲区或命名管道)作为输出。 |
用法
在仿真级别,串行控制台与其驱动程序之间的交互是通过两个read
和write
特定方法完成的,它们处理单字节访问。对于发送更多输入,可以使用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实现,并扩展它们以生成警报(例如,停止恶意客户机的执行)。 |
保存/恢复状态支持
以下抽象为Rtc
和Serial
设备提供了这种支持:
<Device>State
-> 保留<Device>
的硬件状态;<Device>StateSer
-> 可以由需要同时(De)Serialize
和/或Versionize
的顾客使用。如果客户需要与上游不同的状态,则可以在他们的产品中实现From
(或类似机制)以将上游状态转换为所需的产品状态。
有关rust-vmm中保存/恢复状态支持的详细设计文档,可以在此处找到:此处。
vm-superio
和vm-superio-ser
版本的兼容性
每次从vm-superio
更改状态时,都需要在相应的vm-superio-ser
状态中进行传播。为了保持这两个crate发布版本的兼容性,一旦我们有一个新的vm-superio
发布,导致vm-superio-ser
发生变化,我们还需要发布一个新的vm-superio-ser
版本。因此,vm-superio-ser
crate将包含一个与vm-superio
的精确版本相对应的精确版本。
许可证
本项目采用以下许可证之一: