云计算国产化之路 vnc登录 文件系统直通(virtio-9p) 扩展qemu接口 gpg WARNING 珍藏博客 虚拟内存情况dommemstat分析 免密码自动登录脚本 Linux网桥 测试网段IP占用情况 Linux 进程状态 systemc强制依赖 调试openstack ut uefi p2v 重做ubuntu内核 virsh创建虚拟机简介 virtio IO路径 虚拟化层升级后磁盘无法卸载卷 vmtouch使用 Taint flags 主机和虚拟机文件共享处理的几种方法 kvm分析工具 kvm中对磁盘的io cache 虚拟化不同导致的guestos中软件安装差异(未解决) 设备直通(PCI Assignment)到底是咋整的 virtio到底是咋整的 内核启动参数 虚拟化实时性提升(零)之配置步骤 中断虚拟化(pic)到底是咋整的 中断虚拟化(apic)到底是咋整的 Raid卡配置丢失导致服务器无法启动 tainted kernels cpu stuck for 23s问题分析 虚拟化实时性提升(一)之hostOS切换为强实时系统 内存虚拟化到底是咋整的 qemu-kvm中vcpu虚拟化到底是咋整的 风河虚拟化技术点分析 使用qga的好处 qemu迁移代码分析 虚拟机串口配置及其导出到主机pts和console.log System-based I/O vs. Raw I/O 虚拟机使用Hugepage(大页) 硬件辅助分页(hardware assisted paging) 修改centos7默认启动项目 virtio的工作流程——kernel中virtio-pci初始化(2) virtio的工作流程——qemu中virtio-backend初始化(1) qmp ceilometer取不到memory.usage指标 Virtio-Balloon超详细分析 slabtop输出 虚拟机磁盘cache导致的host os kernel崩溃 虚拟机cpu和memory性能优化测评 PCI配置空间(PCI Configuration Space) centos下网卡设备直通(VT-dpci passthrough)遇到的问题及其解决思路 libguestfs详解 yum卸载软件包及其依赖 通过原始Centos ISO来定制自己的ISO centos下网卡设备直通(VT-d,pci passthrough) (占位符)window虚拟机中拔盘如何通知到libvirt和qemu后端的 cirrus漏洞分析CVE-2017-2615 XSA-208 qcow2随笔 控制寄存器概览 ceilometer对接postgresql 解压initrd和vmlinuz qemu guest agent验证 QEMU升级指南(待续) ubuntu中kdump的配置 qemu(2.3)接口梳理 热迁移导致的FC存储场景下的multipath卷残留问题分析 virsh命令(4)secret,snapshot,pool,volume部分 virsh命令(3)之interface,filter,network virsh命令(2)monitor,host,nodedev部分 virsh命令(1)之domain部分 QEMU内存管理之FlatView模型(QEMU2.0.0) ovirt基于sanock的高可用(主机粒度HA) Sanlock防脑裂场景功能测试用例 gnocchi配置及与ceilometer对接指南 make patch for libvirt in centos centos使用sanlock指导 高可用nfs资料 ubuntu14中使用sanlock指导 LVM操作指南 sanlock相关功能验证流程汇总 make patch for libvirt in ubuntu libvirt.so.0-version `LIBVIRT_PRIVATE_1.2.7' not found gdb debug libvirt 基于ubuntu社区源码包编译libvirt compile libvirt(centos) No PCI buses available nfs lead to Linux halt nfs install and config anti-virus for cloud platform nova fetch image from glance(something about _base) token auth process ovs入门指南 virt software anti-virus something about ceilometer disk sample context interview questions openstack vm injection openstack Restful and RPC murano 概览 创建虚拟机流程(compute节点)之网络创建 创建虚拟机流程之compute_api之虚拟机实例填充之配额检测 创建虚拟机流程之compute_api之基本参数生成 创建虚拟机流程之compute_api 创建虚拟机流程(主) 创建虚拟机之image 创建虚拟机流程之准备网桥 创建虚拟机流程之virt 创建虚拟机流程之compute节点 CI/CD研发流程之工程创建 CI/CD研发流程之代码合入 CI/CD研发流程之UT(单元测试) 向openstack社区合入代码记 openstack/ceilometer/gnocchi杂谈 影子页表原理 mem_add(exec.c) qemu编译安装调试 openstack/ceilometer/gnocchi之Grafana简介 openstack wiki etcd openstack计量ceilometer openstack计费cloudKitty enventlet backdoor USB 安装VMWARE ESX pycharm设置指南 无法执行modprobe -a kvm-intel解决办法 QEMU配置项 网络不通小记 libvirt之XML(虚拟机定义文件) openstack-horizon 证书认证 ceilometer与ceph对接 openstack定时任务剖析(TODO) 服务器重启后mongodb进程无法启动 ubuntu14下新增openstack服务到service的导引 ERROR 1045(28000)-数据库连不上 Python两个内置函数—locals和globals unknown exit, hardware reason 31

cirrus漏洞分析CVE-2017-2615 XSA-208

2017年02月13日

背景介绍

最近360爆出一个qemu的安全漏洞,具体可见这里

本文基于openstack kilo和qemu2.3分析
源码分析openstack mitaka和qemu1.5.3同样存在此问题

问题确认

可以通过如下两种方式任何一个确认:
1.带外从libvirt层面 virsh dumpxml
如果类型为cirrus会存在此问题

2.带内从虚拟机内部 lspci
如果vga型号为cirrus会存在问题

问题根因

可以详细见漏洞描述

其实就是边界没有处理好

解决方法

1.升级到问题解决的qemu版本,或者在原版本qemu上打补丁修复问题。
2.虚拟机启动的时候不使用cirrus,使用其他的显示格式代替,如qxl格式代替
(如果是openstack还可以通过镜像meatadata绕开,待拉通验证可用性,详细见下面nova分析)

源码层面问题溯源

下面我们从上向下分析,即从nova到qemu

nova

我们知道,在nova中组装虚拟机的xml(就是给libvirt提供的虚拟机配置)是在_get_guest_config方法中实现的
找到显示对应的部分,如下图
默认情况下CONF.vnc_enabled是True,并且virt_type是kvm
也就是说会走进上面的那个分支,进而add_video_driver会被设置为True

下面重点关注_add_video_driver方法

默认情况下guest的架构是x86,virt_type是kvm
如果不启用spice,且镜像没有设置hw_video_model的话
是vconfig.LibvirtConfigGuestVideo()里的默认值cirrus

综上所述,默认情况下,nova传给libvirt的显卡是cirrus

因此,在nova层面修改,有如下两种方式:
1.修改nova代码,LibvirtConfigGuestVideo默认类型换为其他方式,如qxl
2.运维层面规避,镜像使用hw_video_model这个值

这里使用qxl简单验证

qemu层

众所周知,qemu/kvm这种架构下,vt-d及其SRIOV外的基本设备模拟是在qemu里实现的
在qemu的入口vl.c中的main()方法中,如果有vga相关的参数,会如下处理

接下来根据传入的vga参数调用select_vgahw设置vga相关硬件
(当然,如果没有传入,qemu有自己的规则去生成默认的vga设备,不详述)

我们以cirrus为例,继续跟踪,其他类似

根据qemu的硬件设备加载逻辑(具体不详述,这块内容太绕,如果详细了解需要补齐下qemu启动逻辑,有机会后续专门输出文档)
根据刚才的设置,会调用到/hw/display/cirrus_vga.c

简单可以这么理解
进程启动前,会调用到type_init,调用到cirrus_vga_info
设置好类的初始化方法cirrus_vga_class_init
cirrus的默认设备号是CIRRUS_ID_CLGD5446
设置好设备实例化的方法pci_cirrus_vga_realize

设备示例话的时候,会初始化设备,然后设置一系列的钩子函数
也就是说后续有数据传输的时候,会调用钩子函数
钩子函数实现了数据的传输,传输前会调用blit_is_unsafe判断当前传输是否合法
问题就出现在这里,判断的时候边界没有处理清楚,导致会存在越界可能

另外,具体数据如何处理的,具体涉及到qemu的io处理机制,详细描述又是一大块内容了(后续有机会补齐文档)