论文部分内容阅读
大多数的商业操作系统都是由不安全的编程语言开发而来的,面临着各种基于内存安全的攻击。而操作系统内核通常是整个系统的安全基础,必须对其进行保护。保护的对象涵盖整个操作系统的内核代码和所有的内核数据。其中,动态的内核数据由于其无法确定的存放位置和易变性,保护起来难度较大。现有的解决方案大都只提供了对一般控制数据(例如,函数指针和返回地址)的粗粒度保护,没有涵盖特殊的控制数据(例如,中断上下文中的返回地址)和非控制数据(例如,分支数据)。然而,相关研究者已经论证了这些粗粒度的控制数据保护系统能够被最新的攻击绕过。为此,论文设计并实现了一种基于数据流完整性的内核保护系统。与先前系统相比,该系统能够保护操作系统内核中的控制数据和非控制数据,并且能够通过强制实施细粒度的控制流完整性(Control Flow Integrity,简称为CFI)和数据流完整性(Data Flow Integrity,简称为DFI)来阻止那些基于内存安全的内核攻击。CFI既是DFI的重要组成部分也是DFI的基础和前提,只有实施了细粒度的CFI才能确保DFI的有效性。首先,为了获取实施CFI所必须的细粒度控制流图,论文提出了一种改进的针对内核中间代码(Intermediate Representation,简称为IR)的上下文和字段敏感的指向分析方法,提高了所获取控制流图的准确性。该方法的主要创新点在于引入了一个新的向量,即结构体位置向量(struct location vector),用于推测每个间接函数调用的目标。引入该向量的主要依据是在内核空间中分布着大量对函数指针的初始化和赋值操作,而在整个生命周期中某个函数指针通常总是位于相同结构体的相同字段。其次,为了解决CFI保护中的目标等价问题,论文采用了索引钩子的方法,通过修改编译器的后端对内核中的间接转移指令进行插桩,并借助二进制改写将其代码段和数据段中的代码指针替换为各自的表索引。最后,为了全面地保护中断控制数据,论文提出了一种基于hypervisor的防御机制,在中断发生时将控制信息备份到hypervisor中并在中断返回时验证该信息。因此,论文对内核强制实施了细粒度的CFI保护。为了保护内核中的非控制数据从而实现DFI,论文采用了写完整性测试(Write Integrity Testing,简称为WIT)技术。之所以选择WIT,是因为观测到内核中对分支数据的写操作远远少于读操作,因而可以大大减少需要执行的检查次数。为此,论文实现了一个编译时组件和一个运行时组件。首先,在编译阶段,论文通过对IR的指向分析计算出内核中每条指令可以写的数据对象的集合。同时,为了减少空间和时间开销,论文通过对IR的写安全性分析排除掉那些安全的写指令。最后,在运行阶段,论文通过修改编译器后端对内核中每条不安全的写指令进行插桩,以阻止该指令修改那些不被静态分析允许的数据对象。因此,论文对内核强制实施了DFI保护。论文基于开源的LLVM编译器,实现了一个针对Linux 3.14内核的原型保护系统,并对其进行了全面的功能和性能评估。评估结果表明,在引入可接受性能损耗的情况下,该系统能够阻止所有基于控制数据和非控制数据的攻击。