现在的位置: 首页 > 综合 > 正文

X86体系虚拟化缺陷

2013年04月19日 ⁄ 综合 ⁄ 共 1636字 ⁄ 字号 评论关闭
http://www.mcplive.cn/?controller=Article&id=5788&page=5
特权级别

        大部分的现代计算机体系结构都有两个或两个以上的特权级别,用来分隔内核和应用软件。以x86为例,为了得到更高的保护控制,在x86的保护模式下定义了当前特权级别(Current Previleged Level,简称CPL),一共有四个特级层次(0 to 3)被定义,我们一般称之为Ring。Ring后面的数字越大特权越小,我们的操作系统一般都运行在Ring0上,而Ring1和2一般用来支持设备驱动,Ring3上面跑的就是应用软件了。而在现在的x86处理器中,64位架构已经非常普遍,64位CPU因为必须支持页表模式,所以只有两个特权级别,我们可以简单理解为Ring0和Ring3(实际上另有明确定义),这种模型我们常称为0/3模型。

        系统中有一些关键操作指令只能在最高特权级别上执行,它们一般被称为特权指令,特权指令仅仅在当前的特权级别为零时(CPL=0)才会执行。如果在非特权级别上试图执行特权指令,将生成一个一般保护异常(这通常会生成一个应用程序错误),而非特权指令则可以在任何一个权限级别执行。

敏感指令中的漏网之鱼

        在虚拟化世界的VMM模型中,我们可以看到所有的客户机操作系统都运行在非特权模式下,即非Ring0级。因为Guest OS已经不处在特权级别,所以存在一部分原本应该在特权级别执行但现在因为层级权限不够必须转交VMM进行处理的指令,这部分指令就叫敏感指令。


x86的敏感指令中明显有一部分漏网之鱼

        而根据Popek和Goldberg的定义,指令集支持虚拟化的前提是:所有敏感指令都是特权指令。很可惜x86指令集不能满足这个要求,这是它和RISC架构相比的一个不足。

        在IBM之类的RISC指令集方面,因为敏感指令全部是特权指令,所以敏感指令的执行都可以被VMM捕获,而在x86方面,因为有一部分敏感指令不属于特权指令,变成了非特权指令,而非特权指令在较低的特权级别上是可以直接执行的,也就是说VMM不会处理这些指令。这样就势必会带来问题,试想一个不受虚拟化软件层控制的指令却工作在虚拟化层之上,这是怎样一个情景?x86至少有十几条敏感指令是不会引发异常的非特权指令,在IA-32指令集中,我们称这些非特权级别的敏感指令为临界指令,它们可以分成两类:

        敏感寄存器指令:它们读取或者修改敏感寄存器和(或者)敏感内存数据区所存放的内容,比如时钟寄存器、中断寄存器。

        1.SGDT、SIDT、SLDT
        2.SMSW
        3.PUSHF、POPF

        保护系统指令:涉及存储保护系统、内存或者地址定位系统。

        1.LAR、LSL、VERR、VERW
        2.POP
        3.PUSH
        4.CALL、JMP、INT n、RET
        5.STR
        6.MOV

临界指令实例讲解

        我们用一个实际的例子来解释x86指令集的虚拟化漏洞。SMSW指令(取机器状态字的指令)是为了向下兼容老式处理器,这个指令应该由操作系统完成,也就是说需要Ring0才可以,但很可惜它没有被放在特权指令中。在虚拟化环境中,客户机操作系统都工作在非特权层次上(一般为Ring1或者Ring3),前面我们讲到非特权指令在较低特权级别时可以不被VMM捕获而直接执行。


不同的特权级别满足不同程序运行的需求

        客户机操作系统在执行这个指令时,直接取到的是真实机器的值(假设取值1为保护模式,0为实模式),现在的VMM一般都工作在保护模式下,如果客户机操作系统正好运行在实模式下,那么问题就出来了,SMSW取到的值是1,表示系统运行在保护模式下,而不是真正的客户机操作系统的实模式的返回值0,这显然是不正确的。

抱歉!评论已关闭.