QEMU 安全模型深度解读:威胁边界、隔离机制与安全状态报告机制
【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址: https://gitcode.com/gh_mirrors/qe/qemu
本篇指南基于 docs/system/security.rst 展开,系统梳理 QEMU 官方定义的安全需求(Security Requirements)、安全边界判定范围(Security boundary scope)、以secure注解为核心的安全状态报告机制,以及“客户机隔离 + 最小权限”的安全架构设计原则,并辅以仓库源码(如 qapi/compat.json、qapi/qapi-util.c、include/hw/core/boards.h)验证实现细节。读完本文,你将掌握:哪些使用场景被 QEMU 官方视为“受安全支持”、如何用-compat insecure-types与qom-list-types识别不具备安全边界(security boundary)的机器/设备类型,以及安全部署 QEMU 时应遵循的最小权限与隔离加固手段。
一、安全需求:QEMU 设计要满足的承诺
QEMU 支持众多差异极大的使用场景,其中部分场景的安全要求远高于其他场景。社区对“用户可依赖的整体安全需求”达成了一致,这些需求界定了从安全角度看“什么是被支持的”。需求被划分为两大类:虚拟化用例(Virtualization Use Case)与非虚拟化用例(Non-virtualization Use Case)。
1.1 虚拟化用例:唯一提供安全保证的支撑范围
虚拟化用例涵盖云主机、虚拟私有服务器(VPS)托管,以及传统数据中心与桌面虚拟化。这类用例依赖硬件虚拟化扩展(如 Intel VT-x / AMD-V、ARM 虚拟化扩展)在物理 CPU 上以接近原生的速度安全执行客户机代码。
在该用例下,以下实体被认定为不可信(可能自身存在缺陷或被恶意利用):
- 客户机(Guest)
- 面向用户的接口(如 VNC、SPICE、WebSocket)
- 网络协议(如 NBD、在线迁移 live migration)
- 用户提供的文件(如磁盘镜像、内核、设备树)
- 透传设备(Passthrough devices,如 PCI、USB)
凡是影响这些实体的缺陷,都会被评估“在真实使用场景中是否可能造成损害”;若确实可能造成损害,则按**安全缺陷(security bug)**处理。
要纳入这套安全支持策略(即获得官方安全承诺),必须同时满足两个条件:
- 使用虚拟化加速器,如 KVM 或 HVF;
- 使用下方列出的受支持 machine 类型之一。
文档同时提醒:即使搭配虚拟化加速器,其他 machine 类型也可能在“客户机可信”的工作负载下带来更好性能,但任何未列入清单的 machine 类型都不应被认为提供客户机隔离或安全保证,它们被归入“非虚拟化用例”。
受支持的安全 machine 类型清单(按目标架构整理):
| 目标架构 | 受安全支持的 machine 类型 |
|---|---|
| aarch64 | virt |
| i386, x86_64 | microvm、xenfv、xenpv、xenpvh、pc、q35 |
| s390x | s390-ccw-virtio |
| loongarch64 | virt |
| ppc64 | pseries |
| riscv32, riscv64 | virt |
以 aarch64 的virt机器为例,其最新版本宏定义位于 hw/arm/virt.c(DEFINE_VIRT_MACHINE_AS_LATEST/DEFINE_VIRT_MACHINE),从源码结构看,virt是 aarch64 上持续演进、承担虚拟化安全职责的主力机型。
1.2 非虚拟化用例:TCG 纯软件模拟不提供安全保证
非虚拟化用例指使用 Tiny Code Generator(TCG)进行的纯软件模拟。原则上,TCG 与配套的设备模拟代码应当满足与虚拟化用例相同的安全需求,但由于历史原因,大量非虚拟化用例代码在编写时并未以这些安全需求为前提。
因此,影响非虚拟化用例的缺陷目前不被视为安全缺陷。使用非虚拟化用例的用户绝不能依赖 QEMU 提供客户机隔离或任何安全保证——例如在纯 TCG 模拟中运行恶意代码、研究不受信二进制等场景,都应默认“无隔离、无防护”前提。
二、安全边界范围:什么缺陷才算安全漏洞
即使缺陷影响的是上述“虚拟化用例”,也并非所有场景都纳入安全处理范围。QEMU 官方使用以下指引判定:是走完整安全流程(含 CVE 分配),还是仅作为普通缺陷修复。
2.1 assert / abort(断言与中止)
若触发某条代码路径需要客户机内核权限(或 root 账户访问),那么 QEMU 内的 assert/abort 属于“自损式拒绝服务”,不会按安全缺陷处理(至多算加固缺陷 hardening bug)。反之,若可由客户机内的非特权账户触发,则可能有理由按安全缺陷处理。
2.2 vhost-user / vfio-user 后端
后端进程与 QEMU 进程共享同一块内存区域(co-mapped)。进程分离的初衷是运维弹性与灵活性,以及允许独立软件供应商提供后端实现;QEMU 与 vhost-user、vfio-user 后端之间不认为存在安全边界。因此,后端中能导致 QEMU 崩溃/异常行为的缺陷不会被当作安全缺陷,而应作为加固缺陷修复。
2.3 内存分配边界(Memory allocation bounds)
QEMU 进程合法消耗的内存有诸多途径可能远超分配的客户机 RAM,QEMU 的最坏情况内存用量应视为实际上无上界。因此宿主上的 QEMU 部署必须为内存峰值预留余地,并采取反制措施保证宿主操作连续性。典型做法是依赖 Linux OOM killer 在内存过量提交(overcommit)时回收过度消耗内存的进程,提供一定程度的保护。据此,会导致过度/无界内存分配的缺陷通常不归类为安全缺陷,而按加固缺陷修复。
2.4 降级的客户机行为(Degraded guest behaviour)
存在一类缺陷会让客户机的硬件设备行为异常,例如虚拟 IOMMU 操作缺陷可能无法提供应有的设备隔离。若利用此类缺陷需要客户机内核权限(或 root 账户),且结果只是虚拟设备行为次优,则视为自损式服务降级,不按安全缺陷处理(至多加固缺陷);若客户机内非特权账户即可触发,则可能构成安全缺陷。
2.5 嵌套虚拟化(Nested virtualization)
嵌套虚拟化的安全范围是“防止 level 2 客户机逃逸进入 level 1 客户机”。如前所述,大量仅可由客户机内核/root 账户利用、且只影响客户机自身服务/可用性的缺陷场景被排除在安全处理之外。在带 PCI 设备直通的嵌套虚拟化场景中,level 2 客户机内核可能触发影响 level 0 QEMU 进程的缺陷;这类缺陷应当修复,但当前不会按安全缺陷分诊。
2.6 迁移 / 快照(Migration/snapshots)
只要源虚拟机与 savevm 文件分别仍然可用,迁移失败与快照加载失败被视为正常运行的一部分。在迁移/快照目标端中止 QEMU 进程同样不视为安全问题。只要下述“架构”章节所述设计原则成立,迁移数据流即被假定为安全,仅对数据流的普通篡改不被视作攻击向量。
2.7 未初始化栈变量
若缺陷场景依赖“未显式初始化栈变量”导致的未定义行为,通常不视为安全缺陷。构建系统会加入-ftrivial-auto-var-init=zero编译选项(受支持的 GCC 与 Clang 均支持),确保所有栈变量隐式零初始化,消除未定义行为,从而消除绝大多数此类缺陷场景。
2.8 低严重性影响(兜底规则)
作为兜底规则:对系统影响严重度被判定为“低”的问题,通常不构成安全缺陷,也不分配 CVE,将在时间允许时作为常规缺陷修复。
三、安全状态报告机制:secure 注解与 insecure-types 策略
3.1 TypeInfo.secure:显式声明安全边界
QEMU 项目通过注解类型来显式声明某类型是否提供安全边界。对于 machine、accelerator 与 device 类型,只有被标注secure标志的类型才有资格分配 CVE。未来该注解会逐步扩展到其他后端(backend)与对象(object)类型,使安全状态完全显式化。
实现层面,TypeInfo结构体在 include/qom/object.h 中新增了bool secure;字段。类型注册时,该标志随.secure字段写入类型信息(见 qom/object.c 中ti->secure = info->secure;),并提供查询函数object_class_is_secure()(qom/object.c)判断某类是否声明安全边界。
机器类型的宏体系在 include/hw/core/boards.h 中做了统一封装:
DEFINE_MACHINE_EXTENDED(namestr, ..., ABSTRACT, SECURE, ...):通过参数传入.secure = SECURE;DEFINE_MACHINE(...):默认.secure = false,注释明确写有 “Implicitly insecure”(隐式不安全);DEFINE_SECURE_MACHINE(...)/DEFINE_SECURE_MACHINE_WITH_INTERFACES(...):硬编码.secure = true,供受支持的安全机器类型使用。
从源码结构可以推断:官方文档列出的受支持 machine 类型(virt、pc、q35、microvm、s390-ccw-virtio、pseries等)正是通过这类带安全标志的宏注册,从而获得“eligible for CVE assignment”的资格。
3.2 -compat insecure-types:控制不安全类型的使用
用户或管理工具可以使用-compat参数的insecure-types选项来控制或识别未显式提供安全边界类型的使用。该参数接受三个值:
| 取值 | 行为 |
|---|---|
accept | 允许使用任何类型。这是当前与历史上的默认行为 |
warn | 使用未显式声明 secure 的类型时输出警告消息,但仍允许使用 |
reject | 使用未显式声明 secure 的类型时输出错误消息,且不允许使用 |
兼容性策略在 QEMU启动初期以及运行期通过 monitor 命令所做的任何变更中都会被强制执行。
该策略的 QAPI 定义位于 qapi/compat.json:枚举CompatPolicySecurity(accept/reject/warn),并作为CompatPolicy结构体的可选字段*insecure-types(默认accept)。从该文件注释看,此字段自 QEMU 11.2 起引入。
运行时判定逻辑在 qapi/qapi-util.c 的compat_policy_check_security()中实现:若类型is_secure为真则直接放行;否则根据policy->insecure_types分别执行:
COMPAT_POLICY_SECURITY_ACCEPT:静默放行;COMPAT_POLICY_SECURITY_REJECT:报错Type '%s' does not provide a security boundary to protect against untrusted data or actions,拒绝使用;COMPAT_POLICY_SECURITY_WARN:通过warn_report()输出同名警告,但继续放行。
3.3 运行时查询:qom-list-types、query-machines 与命令行 help
任何类型类的安全状态都可以在运行时查询:
qom-list-types命令:返回信息中会标记任何被声明为 secure 的类型(secure属性),实现见 qom/qom-qmp-cmds.c,其中对非 secure 类型会省略secure属性、对 secure 类型显式置true;query-machines命令:对 machine 类型反映同样的安全信息;- 命令行
-machine help、-accel help、-device help:分别用于查询 machine 类型、加速器与设备的安全状态。
对安全要求严格的部署,建议将insecure-types=reject(或至少warn)纳入启动参数,并定期用qom-list-types审计所用类型的secure标注,避免无意中使用到不具备隔离保证的模拟设备。
四、安全架构:两大设计原则与隔离机制
本章描述确保上述安全需求得到满足的设计原则。
4.1 客户机隔离(Guest Isolation)
客户机隔离指把客户机代码限制在虚拟机内部。当客户机代码在宿主上获得执行控制权时,即称为“逃逸出虚拟机”(escaping the virtual machine)。隔离同时包含资源限制:对 CPU、内存、磁盘或网络的节流(throttling),客户机必须无法突破自身资源限额。
QEMU 以“模拟设备”的形式向客户机呈现攻击面。客户机必须无法获得对 QEMU 的控制权——模拟设备中的缺陷可能让恶意客户机在 QEMU 内获得代码执行,一旦如此,客户机便已逃逸出虚拟机,能够在宿主上以 QEMU 进程的上下文行动。
此外,客户机之间经常互相交互并共享资源。恶意客户机不得获得对其他客户机的控制权,也不得访问其他客户机的数据。磁盘镜像文件与网络流量必须受到保护,除非用户明确与其他人/进程共享。
4.2 最小权限原则(Principle of Least Privilege)
最小权限原则要求:每个组件只拥有其功能所必需的权限。就 QEMU 而言,即每个进程只拥有属于其客户机的资源。
QEMU 进程不应拥有任何“客户机不可访问”的资源——这样客户机即便逃逸进 QEMU 进程也一无所获,因为它在客户机内部本就拥有这些资源。遵循最小权限原则可以立即满足客户机隔离需求:例如客户机 A 只能访问自己的磁盘镜像a.img,而无法访问客户机 B 的b.img。
现实中,确实存在“客户机不可访问、但 QEMU 必须拥有”的资源,例如宿主系统调用(QEMU 需要,但不会暴露给客户机)。一旦客户机逃逸进 QEMU 进程,便可开始调用宿主系统调用——这正是隔离机制要压缩的攻击面。
新功能必须按最小权限原则设计;若因技术原因无法做到,必须将安全风险明确写入文档,让用户知晓启用该功能的代价。
4.3 可用隔离机制总览
除 Linux seccomp 由 QEMU 自身提供外,以下机制均由启动 QEMU 的管理工具(如 libvirt)部署,且具有平台相关性,文档仅针对 Linux 简要描述。
基础机制:QEMU 进程必须以非特权用户运行。有时为让 QEMU 访问宿主设备(如/dev/net/tun)而以 root 启动 QEMU 看似方便,但这带来巨大安全风险。替代方案有两种:
- 文件描述符传递(File descriptor passing):让本无特权的 QEMU 进程获得宿主设备访问权,而无需以 root 运行;
- UNIX 组授权:以非 root 用户启动 QEMU,并通过配置 UNIX 组授权访问
/dev/kvm、/dev/net/tun等设备节点。部分 Linux 发行版已默认内置这些设备的 UNIX 组。
其余机制逐一说明:
- SELinux 与 AppArmor:超越传统 UNIX 进程与文件权限模型来约束进程,限制 QEMU 进程访问宿主上与 QEMU 无关的进程和文件;
- 资源限制与 cgroup 控制器:对 CPU 时间、内存、I/O 带宽等关键资源提供吞吐与利用率上限;
- Linux namespaces:让进程、文件系统及其他系统资源对 QEMU 不可见。处于命名空间中的 QEMU 进程只能访问被授予的资源;
- Linux seccomp:通过 QEMU 的
--sandbox选项启用,禁用 QEMU 不需要的系统调用,从而缩减宿主内核攻击面; - 传输层安全(TLS):在网络不可信时,为在线迁移连接提供真实性与加密。
-sandbox的完整参数在 qemu-options.hx 中有详细定义(Seccomp mode 2 系统调用过滤器,默认off):
-sandbox on[,obsolete=allow|deny][,elevateprivileges=allow|deny|children] [,spawn=allow|deny][,resourcecontrol=allow|deny]各子参数含义:
obsolete:是否允许内核提供、但现代 C 库通常已不再使用的过时系统调用;elevateprivileges:是否允许 QEMU 进程通过set*uid|gid系统调用提权;值children表示对主 QEMU 进程禁用set*uid|gid,但允许其 fork/exec 出的子进程以非特权方式运行;spawn:通过阻断*fork与execve,避免 QEMU 派生出新线程或新进程;resourcecontrol:禁用进程亲和性(affinity)与调度优先级设置。
五、敏感配置:监控控制台(QMP 与 HMP)的安全处置
QEMU 存在若干具有安全影响的方面,用户与管理应用必须知晓。
5.1 控制台即特权接口
监控控制台(无论使用 QMP 还是 HMP)提供对 QEMU 大量运行时行为的动态控制接口。其中许多命令会指示 QEMU 访问宿主文件系统内容或触发外部进程的派生。文档给出两个典型示例:
migrate命令:允许为隧道化迁移数据流而派生任意进程;blockdev-add命令:指示 QEMU 打开任意文件,将其内容作为虚拟磁盘暴露给客户机。
因此,除非 QEMU 已通过 SELinux、AppArmor 或 Linux namespaces 等技术加以约束,否则监控控制台应被视为拥有与 QEMU 运行账户同等的权限。
5.2 字符设备后端的选择
监控控制台所依托的字符设备后端的自身安全性同样关键:它必须能够抵御恶意第三方发起未授权连接或中间人攻击。许多字符设备后端并不满足这一要求,因此不得用于监控控制台。
官方建议明确:监控控制台应仅通过 UNIX domain socket 后端暴露给本地宿主。除非同时配置 TLS 加密与客户端连接授权控制策略,否则使用基于 TCP 的字符设备后端是不恰当的。
5.3 总结
监控控制台是 QEMU 的特权控制接口,只应开放给可信的管理应用或用户访问。任何将其暴露到不可信网络、或通过不加密通道开放的做法,都会显著放大宿主被攻破的风险。
六、安全部署检查清单
综合以上文档与源码要点,面向生产环境的安全部署可遵循以下清单:
- 用例确认:确认自身属于“虚拟化用例”(KVM/HVF 加速器 + 受支持 machine 类型),否则不应期待任何安全保证;
- machine 类型:只选用文档列出的受支持类型(aarch64
virt、x86_64pc/q35/microvm等),可通过-machine help与query-machines核对secure标注; - 安全策略落地:评估后启用
-compat insecure-types=reject或warn,并用qom-list-types审计;留意该策略在启动期与 monitor 变更期均生效; - 最小权限:以非特权用户运行 QEMU,用 FD 传递或 UNIX 组(
/dev/kvm、/dev/net/tun)授权设备访问,避免 root 运行; - 多层加固:按需叠加 SELinux/AppArmor 策略、cgroup 与资源限制、Linux namespaces、
-sandbox onseccomp 过滤(合理配置obsolete、elevateprivileges、spawn、resourcecontrol子项); - 控制台收敛:监控控制台仅通过本地 UNIX socket 暴露给可信管理端;确需远程时启用 TLS 加密并配置授权策略;
- 迁移安全:在不信任的网络中为 live migration 配置 TLS,确保迁移流真实性、机密性与完整性;
- 预期管理:对 vhost-user/vfio-user 后端、内存峰值、客户机内核可触发的 assert 等“边界外”缺陷有合理预期,将其视为加固缺陷而非依赖其获得安全承诺。
上述安全需求的权威定义与边界判定规则,均以 docs/system/security.rst 为准;实现细节可进一步查阅 qapi/compat.json、qapi/qapi-util.c、include/qom/object.h、include/hw/core/boards.h 与 qemu-options.hx 对应章节。
【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址: https://gitcode.com/gh_mirrors/qe/qemu
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考