MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}}); function MyAutoRun() {    var topp=$(window).height()/2; if($(window).height()>450){ jQuery(".outline_switch_td").css({ position : "fixed", top:topp+"px" }); }  }    window.onload=MyAutoRun; $(window).resize(function(){ var bodyw=$win.width(); var _leftPaneInner_width = jQuery(".rich_html_content #leftPaneInner").width(); var _main_article_body = jQuery(".rich_html_content #main_article_body").width(); var rightw=bodyw-_leftPaneInner_width-_main_article_body-25;   var topp=$(window).height()/2; if(rightw<0||$(window).height()<455){ $("#nav-article-page").hide(); $(".outline_switch_td").hide(); }else{ $("#nav-article-page").show(); $(".outline_switch_td").show(); var topp=$(window).height()/2; jQuery(".outline_switch_td").css({ position : "fixed", top:topp+"px" }); } }); 引入内可信基的应用程序保护方法
  软件学报  2016, Vol. 27 Issue (4): 1042-1058   PDF    
引入内可信基的应用程序保护方法
邓良1, 2, 曾庆凯1, 2     
1. 计算机软件新技术国家重点实验室(南京大学), 江苏 南京 210023;
2. 南京大学 计算机科学与技术系, 江苏 南京 210023
摘要: 提出一种在不可信操作系统中保护应用程序的新方法AppISO.针对传统的虚拟化方法的高开销问题,AppISO在不可信操作系统的同一特权层引入内可信基,代替虚拟机监控器实施应用程序保护,避免了昂贵的特权层切换.同时利用硬件虚拟化,以及页表锁定、影子IDT、切换页面等软件技术保证内可信基的安全性.证明了所提内可信基方法与虚拟化方法具有同样的高安全性.实验和分析结果表明,内可信基方法可显著地提高系统性能.
关键词: 内可信基    应用程序保护    不可信操作系统    虚拟化    
Inner TCB Based Application Protection
DENG Liang1, 2, ZENG Qing-Kai1, 2     
1. State Key Laboratory for Novel Software Technology(Nanjing University), Nanjing 210023, China;
2. Department of Computer Science and Technology, Nanjing University, Nanjing 210023, China
Foundation item: National Natural Science Foundation of China (61170070, 61572248, 61431008, 61321491); National Key Technology R&D Program of China (2012BAK26B01); the Program B for Outstanding PhD Candidate of Nanjing University (2015)
Abstract: This paper presents AppISO, a novel approach to provide whole-application protection in an untrusted operating system(OS). Unlike previous virtualization-based approach, AppISO does not directly use any higher privilege hypervisor for application protection, which is known to cause high overhead due to frequent privilege transitions. Instead, AppISO introduces a software component named Inner TCB running in the same privilege layer with the untrusted OS, and uses Inner TCB to realize application protection. Meanwhile AppISO leverages hardware virtualization and software techniques such as page table lockdown, shadow IDT, and transition page to guarantee the security and isolation of Inner TCB. This paper proves that Inner TCB can achieve the same level of security as hypervisor, and experimental results show that the presented approach has significant improvement in performance.
Key words: inner TCB    application protection    untrusted OS    virtualization    

在现代操作系统中,安全敏感的应用程序很容易受到攻击.即使对应用程序本身进行安全设计和验证,底层的操作系统仍然存在广泛的攻击窗口,如大量的系统调用接口,硬件服务商提供的设备驱动等.操作系统结构复杂,通常采用不安全的程序语言编写.越来越多的安全漏洞报告表明,操作系统安全问题依然不容忽视.然而,在传统的系统中,由于操作系统运行在最高特权层,攻击者只要攻陷了操作系统,就能够控制并攻击应用程序,包括窃取和篡改敏感信息、破坏控制流完整性等等.

针对操作系统不可信的问题,目前应用程序保护的主流方法是虚拟化方法.Inktag[1]和Overshadow[2]在操作系统底层引入更高特权层的虚拟机监控器,对应用程序实现了全面保护,包括保护应用程序的内存隔离、控制流完整性和文件数据安全等.Trustvisor[3]基于虚拟机监控器,构建软件TPM,保证应用程序中的代码片段(codeblock)的执行是安全隔离和可验证的.Fides[4]进一步保护了多个代码片段,保证它们之间的安全交互.Trusted Path[5]关注不可信操作系统中应用程序的I/O安全问题,基于虚拟化技术构建一条从应用程序到外设的可信I/O路径.此外,针对操作系统服务的不可信问题,Proxos[6]将安全敏感的系统调用导入到一个可信的VM中加以处理,以保证这些系统服务的可信.

虚拟化方法基于如下可信链:硬件>虚拟机监控器>安全策略.其中,所有的安全策略都基于虚拟机监控器实现;虚拟机监控器运行在更高的特权层,与不可信操作系统完全隔离,也有着更小的代码量和攻击窗口.引入更高特权层的虚拟机监控器保证了高安全性.然而,频繁的特权层切换也导致了较高的运行开销.

针对这一矛盾,本文提出了基于内可信基的应用程序保护方法AppISO.它在不可信操作系统的同一特权层引入软件模块,即内可信基.在应用程序保护中,内可信基接管了虚拟化方法中虚拟机监控器的所有工作,但是这些工作的执行无需特权层的切换.由于内可信基与不可信操作系统运行在同一特权层,本文提出了一系列技术保证内可信基的可靠执行和安全隔离.此外,本文提出了基于内可信基的文件保护和文件访问控制,避免了传统虚拟化方法中低效的加密解密计算.AppISO具有以下特点:(1) 高安全性.应用程序保护基于可信链:硬件>内可信基>安全策略.所有的安全策略都基于内可信基实现.与虚拟机监控器一样,内可信基与不可信操作系统完全隔离.(2) 高性能.与传统虚拟化方法相比,内可信基的引入避免了频繁的特权层切换和低效的加密解密.本文进一步提出了一系列针对内可信基的性能优化技术.(3) 全面保护.与Inktag和Oveshadow一样,AppISO提供全面的应用程序保护,包括内存保护、控制流完整性保护和文件访问控制等.

1 安全假设

本文假设操作系统内核是不可信的.不可信内核运行在最高特权层,能够任意访问底层硬件、执行内存中任意代码、读写内存中的任意数据以及利用外设进行恶意的DMA 操作.在该假设下,不可信内核能够攻击系统中的任意一个应用程序,包括攻击它们的内存数据、控制流和文件I/O等.本文不考虑应用程序本身的漏洞,因为在现实中,需要保护的敏感应用程序通常代码量小且经过了充分的验证和测试,存在漏洞的几率比较小.此外,本文假设硬件(包括CPU、内存控制器、外设)是可信的,不考虑物理攻击.以上安全假设与传统虚拟化方法Inktag和Oveshadow是一致的.

2 基本模型和安全目标 2.1 Inktag的基本模型和安全目标

为了与虚拟化方法对比,我们首先以Inktag[1]为例,阐述虚拟化方法实现全面应用程序保护的基本模型和安全目标.如图 1所示,该模型在操作系统底层引入了更高权限(root模式)的虚拟机监控器.应用程序运行在被虚拟机监控器保护的安全执行环境中,与不可信操作系统(与其他应用程序)隔离.基于该虚拟化模型,Inktag实现了以下安全目标:

Fig. 1 Overview of Inktag 图 1 Inktag的基本模型

(1) 应用程序地址空间安全.Inktag基于虚拟机监控器的内存保护机制,保护地址空间中数据和代码的安全隔离;并进一步在虚拟化模型的基础上提出Paraverification机制,保护应用程序的地址空间完整性.

(2) 应用程序控制流完整性.应用程序在运行过程中可能随时被操作系统中断.Inktag基于虚拟机监控器,截获应用程序中的系统调用和中断异常,安全保存应用程序的执行上下文,并在返回应用程序之前恢复执行上下文,确保操作系统无法恶意修改应用程序的控制流和寄存器.

(3) 应用程序文件I/O安全和访问控制.由于应用程序仍然需要依赖操作系统提供的文件服务实现文件存储,Inktag基于加密和哈希,保证文件数据在操作系统中的私密性和完整性;并进一步提出基于虚拟机监控器的文件访问控制,保证文件访问的安全性.

然而,在该模型中,如下两个因素造成了较高的性能开销.

(1) 频繁的non-root/root切换.虚拟机监控器必须截获应用程序中所有的页表更新操作,实现地址空间完整性保护;虚拟机监控器必须截获应用程序中所有的系统调用和中断异常.例如,一次系统调用需要4次昂贵的non-root/root切换.

(2) 低效的加密解密.虚拟机监控器对文件数据的加密解密、密钥的管理也带来了较大的开销.

2.2 AppISO的基本模型、安全目标和主要挑战

本文中,AppISO的安全目标与Inktag一致,包括保护应用程序的地址空间安全、控制流完整性、文件I/O安全和实现访问控制.然而,针对虚拟化模型的高开销问题,AppISO提出了内可信基模型,以实现这些安全目标.

图 2所示,在该模型中,整个系统始终运行在non-root模式中.该non-root模式的执行环境在系统启动时被设置,此后,在系统运行过程中不再陷入到root模式中.在non-root模式中,操作系统与应用程序运行在两个不同的地址空间,分别称为内核地址空间KAS(kernel address space)和安全地址空间SAS(secure address space).操作系统运行在KAS的ring 0层中;应用程序运行在SAS的ring 3层中.与Inktag一样,本文中的操作系统指的是操作系统内核.KAS中使用的页表称为KPT(kernel page table),SAS中使用的页表称为SPT(secure page table).

Fig. 2 Overview of AppISO 图 2 AppISO的基本模型

该模型在SAS的ring 0层引入内可信基,应用程序运行在内可信基保护的安全上下文中.当SAS ring 3层的应用程序与操作系统交互时,应用程序首先陷入到SAS ring 0层的内可信基,内可信基保存应用程序上下文,然后切换到KAS,进入操作系统执行.当操作系统返回应用程序时,必须首先返回SAS ring 0层的内可信基,内可信基恢复应用程序上下文,再返回SAS ring 3层中的应用程序继续执行.

在该模型中,应用程序的保护由non-root模式中的内可信基实现,无需陷入到root模式中.

(1) 基于内可信基的内存保护机制,保证应用程序地址空间与不可信操作系统的安全隔离和地址空间的完整性.

(2) 基于内可信基的影子IDT机制,截获系统调用和中断异常,保护应用程序的控制流完整性和寄存器安全.

(3) 基于内可信基的I/O验证机制,在不可信操作系统内构建可信文件数据流,保证应用程序文件数据的私密性和完整性,同时避免了低效的加密解密;并进一步提出基于内可信基的文件访问控制.

该模型能够有效地解决虚拟化方法影响性能的两个主要问题.然而,该模型的挑战在于:内可信基和不可信操作系统运行在同一特权层(non-root模式的ring 0层),那么,如何在同一特权层实现内存保护、控制流完整性保护和文件保护呢?更为重要的是,如何保证内可信基本身的安全?

本文第3节介绍技术背景.第4节介绍内可信基的内存保护机制、影子IDT机制.第5节介绍应用程序地址空间保护和控制流保护.第6节介绍内可信基的I/O验证机制和文件访问控制.第7节构建内可信基的安全模型,分析和证明内可信基安全隔离和可信执行必须满足的安全属性.第8节介绍AppISO在Linux上的原型系统实现.第9节给出实验结果并进行性能分析.第10节介绍相关工作.第11节对本文进行总结.

3 技术背景

为了更加方便地理解AppISO的设计和实现原理,我们首先对AppISO用到的硬件虚拟化技术作一些简单的介绍.在x86中,硬件虚拟化(Intel VMX和AMD SVM)提供了两种CPU运行模式:root模式和non-root模式.运行在root模式中的软件可通过使用一个位于内存中的数据结构VMCS(virtual machine control structure)来控制non-root模式中软件的行为,包括限制non-root模式中软件能够执行的特权操作以及能够直接处理的系统事件.当non-root模式软件执行某个不允许的特权操作时,CPU会产生VM exit并陷入到root模式中.从而,root模式中软件能够对这些操作进行截获和处理.

在AppISO中,我们将整个系统(包括内核、内可信基和应用程序)始终运行在non-root模式中.通过系统初始化时VMCS的设置,AppISO允许non-root模式中软件执行大部分的特权操作和直接处理系统事件,保证整个系统在non-root模式中的顺利运行.同时,AppISO基于硬件虚拟化,对non-root模式中几个特殊的特权操作(比如修改cr3寄存器)进行限制,在此基础上,实现了内可信基的隔离和应用程序的保护.

4 内可信基的内存保护机制

在虚拟化方法中,虚拟机监控器实施保护的关键是,截获并验证系统中所有的CR3寄存器修改和页表更新操作,以完全控制页表,实现内存保护.

在AppISO中,内可信基利用硬件虚拟化直接对CR3寄存器的目标值进行限制.同时,内可信基截获并验证系统中所有的页表更新操作,实现内存保护.

4.1 CR3限制

在系统启动、设置non-root执行环境时,AppISO使用硬件虚拟化的CR3-Target Controls[7]机制保证整个non-root模式系统(操作系统、应用程序和内可信基)只能运行在KAS和SAS中.CR3-Target Controls机制允许在VMCS的CR3_TARGET_LIST中预设定最多4个CR3寄存器的目标值.当运行在non-root模式中的软件修改CR3寄存器时,若目标值是CR3_TARGET_LIST中的一个,则该CR3修改可直接在non-root模式中完成. AppISO仅使用两个目标值,将KAS的页表KPT和SAS的页表SPT的基地址写入CR3_TARGET_LIST,因此,整个系统在运行过程中只能将CR3寄存器修改为这两个值.如果试图修改为其他目标值,则均会使CPU陷入到root模式,AppISO中任何导致陷入到root模式的操作都被认为是恶意的,并会导致整个系统重启.因此,基于硬件虚拟化的设置,整个系统只能在KAS和SAS中运行.

4.2 页表验证

在KAS中,AppISO基于“页表锁定”技术,保证运行在KAS中的任何软件(即使运行在ring 0层)都不能修改页表.具体来说,在KAS中,整个页表被映射为只读.任何运行在KAS中的软件若想要修改某个页表项,则必须首先将该页表项映射为可写.然而,整个页表都是只读的,不允许将任何只读映射修改为可写.因此,在KAS中,整个页表都被只读锁定了.KAS中的软件试图解除页表锁定的方式只有两个:(1) 修改CR3寄存器、切换地址空间.但是该方式已被硬件虚拟化限制.(2) 修改CR0寄存器的WP位,使页表的只读保护失效.针对这种方式,AppISO使用硬件虚拟化禁止non-root模式的所有软件修改CR0寄存器的WP位,任何修改WP位的操作都会陷入到root模式,进而导致系统重启.

在SAS中,AppISO基于传统特权层隔离(ring 3/ring 0)的方式,保证只有ring 0层的软件能够修改页表.页表在其他层(ring 3层)被映射为不可见.

因此,整个系统中只有SAS ring 0层的软件能够修改页表.AppISO将内可信基运行在SAS ring 0层,将操作系统运行在KAS ring 0层,应用程序运行在SAS ring 3层.因而所有的页表更新操作只能由内可信基完成.当操作系统需要更新页表时,只能向内可信基发出请求,内可信基能够截获并验证所有的页表更新操作,实现内存保护.这种页表验证方式与半虚拟化方法类似.

需要强调的是,虽然KAS ring 0层和SAS ring 0层都是系统中最高特权层,但AppISO基于CR3限制和页表锁定技术,消除了KAS ring 0层的操作系统修改页表的权限.

4.3 内可信基的隔离与保护

由于只有SAS ring 0层的软件能够修改页表,因此,实现内存保护的关键是:保证SAS ring 0层中只有内可信基运行,外部组件(操作系统和应用程序)不能破坏SAS ring 0层中内可信基的数据代码和执行流的完整性.

我们分析一下虚拟化方法的可信基(虚拟机监控器)的保护原理:虚拟机监控器控制了所有进入root模式的入口,保证CPU一旦切换到root模式,虚拟机监控器将获得系统的控制权.虚拟机监控器在root模式中完成自己的执行流程,在返回外部组件时,将CPU切换回non-root模式,保证root模式中只有虚拟机监控器运行.因此,外部组件始终只能运行在non-root模式,不能破坏root模式中虚拟机监控器的数据代码和执行流完整性.

参照虚拟化方法,内可信基也必须控制所有进入SAS ring 0层的入口点,保证一旦CPU进入SAS ring 0层,内可信基便获得系统控制权.内可信基在SAS ring 0层完成自己的执行流程,在返回外部组件时,将CPU切换回KAS或者SAS ring 3,保证SAS ring 0层中只有内可信基运行.因此,外部组件始终只能运行在KAS或者SAS ring 3层中,不能破坏SAS ring 0层中内可信基的数据代码和执行流的完整性.

4.3.1 入口点控制

硬件虚拟化规定了只允许系统在KAS和SAS中运行.因此,SAS ring 0层的入口点包括两类:(1) 从SAS ring 3层通过中断异常陷入,进入SAS ring 0层(从应用程序进入内可信基);(2) 从KAS切换到SAS,进入SAS ring 0层(从操作系统进入内可信基).

第1类入口点控制.在x86中,中断异常的入口点在IDT(interrupt descriptor table)中设置,IDT的基地址由IDTR(interrupt descriptor table register)寄存器指定.当中断异常发生时,CPU根据IDTR寄存器中的地址找到IDT,并根据中断向量(interrupt vector)索引IDT,跳转到相应IDT表项指定的中断处理程序.

在AppISO,操作系统仍然维护自己的IDT,但是CPU实际使用的是内可信基维护的IDT(称为影子IDT),IDTR寄存器指向影子IDT.同时,AppISO使用以下技术保证影子IDT的安全:(1) 利用硬件虚拟化禁止non-root模式的所有软件执行LIDT指令、修改IDTR寄存器,因此IDTR寄存器只能指向影子IDT的基地址.

(2) 将影子IDT所在的页框、对应的中断处理程序的代码均映射为只读,保证它们无法被操作系统修改.(3) 由于IDTR和IDT表项均使用虚拟地址,因此,它们对应的页表映射也被保护.(4) 内可信基在影子IDT的表项中使用中断门(interrupt gate[7]),保证在执行影子IDT的中断处理程序时,中断被禁止,控制流无法被操作系统劫持.因此,当SAS ring 3层发生中断异常时,内可信基通过影子IDT在SAS ring 0层可靠地获得系统控制权.

此外,x86中可调用sysenter和syscall两条指令(快速系统调用)陷入SAS ring 0层.sysenter和syscall使用MSR寄存器(比如msr_sysenter_eip)来指定入口点.AppISO将这些MSR寄存器指向内可信基的入口点,并使用硬件虚拟化的MSR Controls机制[7]禁止在系统初始化后修改该MSR寄存器.

第2类入口点控制.这类入口点的控制更加困难,KAS中的不可信操作系统可能执行自己代码中任意的MOV-TO-CR3指令(x86中修改CR3寄存器的指令)、修改CR3寄存器值,试图切换到SAS.AppISO必须保证,一旦操作系统试图从KAS切换到SAS,内可信基将可靠地获得系统的控制权.

AppISO在KAS和SAS中引入切换页面,并保证该页面是KAS和SAS中被同时映射为可执行的唯一页面.KAS中的操作系统只能使用切换页面中的MOV-TO-CR3指令切换到SAS,而执行其他页面中的MOV-TO-CR3指令试图切换地址空间均会导致缺页异常,进而被内可信基的影子IDT截获并禁止,因为其他页面被禁止在KAS和SAS中同时执行.因此,切换页面是从KAS(操作系统)切换到SAS(内可信基)的唯一方式.

图 3描述了作为操作系统进入内可信基唯一入口的切换页面中的指令序列.首先,KAS中的操作系统跳转到切换页面中的P1,P1将SPT的页表基地址赋值给RAX寄存器,P2再将之赋予CR3寄存器,切换到SAS.即使不可信操作系统试图绕过P1,直接执行P2中的MOV-TO-CR3指令,它也只能将CR3寄存器的值修改为SPT的页表基地址,因为其他的目标值都已被硬件虚拟化设置禁止.进入SAS后,P3执行CLI指令,立即禁止中断,保证从此以后的指令执行都是原子的,操作系统无法再获得控制流.然而,不可信操作系统仍然可能在P2和P3触发恶意中断.针对这一问题,内可信基通过影子IDT检测并禁止该恶意中断.最后,P4和P5跳转到内可信基的入口点,进入内可信基执行.

Fig. 3 Transition page 图 3 切换页面

切换页面的入口机制保证了,KAS中操作系统只能执行切换页面中的MOV-TO-CR3切换到SAS、进入内可信基;在切换页面中,执行流一旦进入到SAS ring 0层,将原子性地进入内可信基中指令执行,保证内可信基获得控制权.

4.3.2 内可信基完整性保护

从入口点进入SAS ring 0后,内可信基在整个执行过程中,中断被禁止,执行流无法被外部组件劫持:在第1类入口,中断被影子IDT中的中断门禁止;在第2类入口,中断被切换页面中的CLI指令禁止.只有当返回外部组件时,内可信基才恢复中断.同时,内可信基将CPU切换回KAS或者SAS ring 3,保证SAS ring 0中只有内可信基运行.当内可信基中发生不可屏蔽中断(NMI)时,内可信基通过影子IDT暂时阻塞该NMI,防止外部组件使用NMI劫持内可信基执行流.当返回到操作系统时,内可信基再将该NMI转发给操作系统进行处理.因此,内可信基的执行流完整性得到保护.

运行在KAS的操作系统或者SAS ring 3层的应用程序无法破坏内可信基数据代码的完整性(它们在KAS和SAS ring 3层被映射为不可见),也无法修改页表、对内可信基的数据代码进行恶意映射.

4.4 应用程序页表切换

每个应用程序都有自己的页表,进程切换时应用程序页表也需要作相应切换.然而,硬件虚拟化设置不允许修改CR3寄存器切换页表.AppISO提出“软切换”技术,实现SAS中不同应用程序页表之间的切换.在x86-64中,页表由4级结构组成(L1,L2,L3和L4表示),CR3寄存器指向L4页表的物理基地址.在传统操作系统中,页表的切换是通过修改CR3寄存器来实现的,本文称其为“硬切换”.而在软切换中,CR3寄存器保持不变,它指向SPT的L4页表(称为S-L4),页表切换是通过将目标应用程序的L4页表复制到S-L4来实现的.由于x86中L4页表的大小只有一个页面的大小(4KB),而且只需要拷贝应用程序部分,软切换并不会带来太大的性能开销.而且,与其他页表一样,S-L4只能被SAS ring 0层中的内可信基修改.因此,进程切换时,操作系统只能向内可信基发出请求,由内可信基切换应用程序页表.内可信基完成软切换并对目标应用程序页表进行验证,本质上与内可信基对页表更新的验证没有区别.

4.5 页表更新验证和性能优化

图 4(a)阐述了内可信基的页表更新验证过程.当应用程序发生缺页中断、陷入内可信基时,在步骤1,内可信基保存应用程序安全上下文,并将该缺页中断转发给KAS中的操作系统.在步骤2,操作系统完成缺页中断处理,分配相应的物理页框.由于KAS中的操作系统无法直接更新页表映射新页框(页表被锁定),它只能切换到SAS,由切换页面进入内可信基,请求内可信基完成页表更新.在步骤3,内可信基根据请求完成页表更新和验证操作,然后返回操作系统.在步骤4,操作系统完成余下的缺页中断处理工作,最终返回内可信基.在步骤5,内可信基恢复应用程序安全上下文,返回应用程序.

Fig. 4 The process of page table update verification 图 4 页表更新验证过程

然而,整个过程额外增加了两次KAS/SAS的切换,造成了额外的性能开销.针对这一问题,我们提出了称为“延迟更新”的优化.事实上,该缺页中断处理的是SPT的更新(应用程序页表的更新),而应用程序页表的更新一直要到应用程序运行时才会发生作用.也就是说,即使在步骤3中,内可信基马上更新了SPT,该更新也要到步骤6才会用于映射内存.因此,AppISO推迟了该页表的更新操作.优化后的处理过程如图 4(b)所示,在步骤1',内可信基向操作系统发送缺页中断.在步骤2',操作系统完成物理页面分配后,并不马上请求内可信基更新页表,而是将页表更新的具体内容置于一块共享内存中.一直到操作系统完成所有处理,返回内可信基时(步骤3'),内可信基才从共享内存中读取更新请求,完成页表更新,然后直接返回应用程序(步骤4').由此可见,优化后的缺页中断处理无需额外的地址空间切换.如果缺页中断发生在KAS中(即KPT缺页中断),页表更新请求无法延迟.然而,KPT缺页中断很少发生,特别是在64位操作系统中.此外,AppISO进一步利用x86的硬件特性(PCID[7])给KAS和SAS中的页表项做上不同的硬件标记(tag).因此,在KAS和SAS的切换过程中,无需刷新TLB缓存,极大地提高了性能.

图 4(c)描述了基于虚拟化系统(Inktag)的页表验证过程.其中,离开和返回应用程序必须进入虚拟机监控器,更新页表也必须进入虚拟机监控器,导致了6次non-root/root的切换.而在内可信基的页表更新验证过程,无需non-root/root的切换.

5 应用程序地址空间和控制流完整性保护

SAS ring 0层中的内可信基基于页表验证,完全控制了页表,因而可以通过页表映射对系统中任意一块内存进行保护.下面具体讨论内可信基如何保护应用程序地址空间中的内存,实现地址空间隔离和完整性保护.

5.1 地址空间隔离

为了实现应用程序地址空间与操作系统的隔离,内可信基使用一个数组来跟踪系统中每个物理页框的映射情况.如表 1所示,每个页框可被定义为3种映射状态:normal,isolated和owned.Normal状态的页框被KPT和SPT-内(本文将SPT中映射内可信基的部分称为SPT-内;映射应用程序的部分称为SPT-应)两者映射,因而操作系统和内可信基都能访问它们.Isolated状态的页框仅被SPT-内映射,只能被内可信基访问.内可信基和页表所在的页框都被映射为isolated状态.Owned状态的页框已被分配给某个应用程序,仅被SPT-内及其应用程序拥有者的SPT-应映射,因而只有内可信基及其拥有者能访问它们.内可信基使用唯一的安全标识符(SID)来标识owned页框的拥有者.SID在进程创建时由内可信基赋予每个进程,每个进程都有自己单独的SID.

Table 1 Mapping states of memory frames (M means mapping, N means not mapping) 表 1 页表映射状态(M表示映射,N标识不映射)

以应用程序A的页框分配为例,阐述页框映射状态的转化过程和地址空间隔离.当一个页框被操作系统分配给应用程序A时,内可信基要求操作系统只能使用isolated状态的页框.当内可信基将该页框映射到A的SPT-应时,会对该页框的映射状态进行验证,拒绝所有非isolated页框.然后,该页框被安全地分配给A,标记为owned状态、并被A的SID标记.内可信基通过验证SID,禁止owned状态的页框被KPT或者其他应用程序的SPT-应映射,保证A的内存隔离.同时,为了防范Iago攻击[8],内可信基也禁止应用程序页框在应用程序地址空间中被重映射.

5.2 地址空间完整性保护

除开地址空间隔离,内可信基必须保证应用程序地址空间中映射的内存是应用程序想要的(地址空间完整性).例如,对于文件映射,内可信基需要保证:(1) 应用程序访问的文件是它想要的文件;(2) 访问的文件位置是它想要的位置.

AppISO采用了Inktag提出的Paraverification机制解决该问题.内可信基要求应用程序自己维护一个链表,描述自己的地址空间映射状态.该链表与应用程序地址空间的其他数据一样,无法被操作系统修改.当内可信基更新应用程序页表时,将会查看该链表.如果操作系统的页表更新请求与该数组描述的地址空间映射状态不一致,则内可信基将拒绝该请求.下面以应用程序调用mmap系统调用映射文件为例,阐述这一机制.

在磁盘上,不同文件被不同的ID标记,同一文件的不同数据块被文件偏移标记,表示该数据块在文件中的位置.当应用程序调用mmap系统调用时,它同时更新自己维护的地址空间状态链表,在该数组中描述自己的意图,包括想要读取的文件对应的ID和偏移.当内可信基进行页表更新验证时,会查看该链表.如果该更新对应的地址空间映射到文件,则内可信基将该链表中的ID和偏移与文件本身的ID和偏移进行比对.如果不是应用程序想要的文件或者偏移位置,内可信基将会拒绝将文件映射到地址空间、并告知应用程序.

在应用程序地址空间保护中,本文的主要贡献是提出了内可信基的内存保护机制.而在内存保护机制上如何具体实现地址空间完整性保护与Inktag类似(比如Paraverification机制),具体细节本文不再重复.

5.3 控制流完整性保护

如第4.3.1节所述,内可信基通过影子IDT技术和硬件虚拟化截获系统中所有的中断异常和系统调用.当SAS ring 3层中应用程序的控制流被中断异常或者系统调用中断时,SAS ring 0层的内可信基获得系统的控制权,保存应用程序的安全上下文,然后进入操作系统执行.当操作系统返回应用程序时,操作系统只能使用切换页面(唯一方式)进入SAS.同时,SAS ring 0层的内可信基获得系统的控制权,并恢复应用程序的安全上下文,最后进入应用程序执行.因此,即使操作系统能够任意中断应用程序的执行,也无法破坏应用程序的控制流完整性或窃取上下文中的敏感数据.

6 内可信基的I/O验证机制和应用程序文件保护 6.1 内可信基的I/O验证机制

内可信基截获并验证系统中所有发送到磁盘外设的I/O命令,整个I/O验证过程在non-root模式中实现.

在x86中,软件通过两种方式向外设发送I/O命令:端口I/O(port I/O)和内存映射I/O(memory mapped I/O).端口I/O使用特殊的I/O指令(比如in和out),而内存映射I/O将一段系统内存(称为I/O内存)分配给外设,使用一般的访存指令来控制外设.软件可访问PCI/PCIe配置空间,修改分配给设备的I/O端口和I/O内存的基地址.

现代磁盘管理器(比如SATA[9])均使用内存映射I/O,因而AppISO仅需要截获内存映射I/O,就可以截获发送到磁盘外设的I/O命令.具体来说,基于内可信基的内存保护机制,内可信基将分配给磁盘管理器的I/O内存映射为只读.当操作系统需要向磁盘发送I/O命令时,它只能将该命令转发给内可信基,由内可信基访问I/O内存,完成I/O操作.因此,内可信基能够截获这些I/O命令,并进行必要的I/O验证.然而,不可信操作系统仍然能够通过访问PCI/PCIe配置空间,恶意修改磁盘管理器的I/O内存基地址,从而绕过内可信基的只读保护.针对该问题,AppISO在系统启动时,对BIOS设置的PCI/PCIe配置空间进行验证,在系统运行过程中禁止操作系统访问整个PCI/PCIe配置空间.在x86中,PCI/PCIe配置空间可以通过两种方式访问:(1) 通过特殊的I/O端口访问;

(2) 通过保留的系统内存访问.对于第1种方式,AppISO在系统启动时,利用硬件虚拟化的I/O bitmap机制[7],禁止non-root模式中的软件(包括操作系统)访问该段I/O端口;对于第2种方式,内可信基将这段保留的系统内存在地址空间中映射为不可见,禁止操作系统访问.

6.2 文件数据保护和访问控制

传统虚拟化方法(Inktag和overshadow)均使用加密和哈希技术保护应用程序文件数据的安全.在文件数据进入到操作系统之前,虚拟机监控器对文件数据进行加密,防止数据被窃取;当应用程序从操作系统获取文件数据时,虚拟机监控器比对文件数据的哈希值,以防止数据被篡改.

在AppISO中,应用程序的文件数据以明文的形式进入操作系统,内可信基通过在不可信操作系统中构建一条可信文件数据流来传输文件数据,防止文件数据被窃取或篡改.同时,类似于Inktag中基于虚拟机监控器的访问控制模型,AppISO实现了基于内可信基的访问控制模型.在该模型中,文件数据被SUID(secure user identifier)标识(类似于Inktag的OID).每个用户都拥有自己的SUID,用户在启动自己的应用程序时,将SUID赋予应用程序.内可信基通过验证SUID保证文件数据只能被其所有者访问.AppISO也向用户提供了灵活的文件访问控制,比如SUID可以标记一个用户组(group),用于用户之间的文件共享;SUID可以指定不同的读写和执行权限等.

6.2.1 可信文件数据流和文件访问控制

图 5(a)描述了应用程序调用write系统调用存储文件时,文件数据在操作系统中的流动情况.其中,文件数据从应用程序地址空间的页框被拷贝到操作系统的缓存页框,然后从缓存页框传输到磁盘块(disk block).可信文件数据流能够保证:文件数据在操作系统中传输时,文件数据与操作系统隔离,无法被操作系统访问.

Fig. 5 Trusted file data flow 图 5 可信文件数据流

(1) 从应用程序页框到操作系统缓存页框的数据流隔离.首先,应用程序页框被映射为owned状态,其中的文件数据无法被操作系统访问.当操作系统需要将文件数据从应用程序页框复制到缓存页框时,只能向内可信基发出请求,由内可信基完成数据拷贝.内可信基要求操作系统只能提供isolated状态的缓存页框,对于非isolated状态的缓存页框,内可信基将拒绝拷贝文件数据.因此,在拷贝后,操作系统仍然无法访问缓存页框上的文件数据.同时,该缓存页框被打上应用程序的SUID,标识缓存页框上文件数据的所有者.

(2) 从缓存页框到磁盘块的数据流隔离.内可信基定义了两种磁盘块的状态:free和occupied,并使用一个数组(称为磁盘块数组)进行状态跟踪.在磁盘块数组中,内存的一个位对应一个磁盘块的状态.内可信基基于I/O 验证机制,对所有发送到磁盘的I/O命令进行验证.如果该命令是将文件数据写入磁盘块,内可信基确保被写入的磁盘块只能是free状态.在数据传输完成后,该磁盘块变为occupied状态,SUID和文件数据一起存储在磁盘块上,用于标识该磁盘块的所有者.此后,基于I/O验证机制,内可信基只允许具有相同SUID的内存页框与该occupied磁盘块进行数据传输,因而磁盘块上文件数据隔离和访问控制得到保证.

当应用程序调用read系统调用读取文件时,可信文件数据流的实现方法类似.如图 5(b)所示,基于I/O验证机制,内可信基只允许occupied磁盘块上的文件数据传输到isolated状态的缓存页框,同时,该缓存页面被赋予occupied磁盘块的SUID.此后,内可信基只允许该缓存页框的数据拷贝到具有相同SUID的应用程序页框,被其应用程序所有者访问.此外,第5.2节中验证地址空间完整性相关的元数据(文件ID和偏移)也随文件数据一起,在可信文件数据流中传输,与不可信操作系统隔离.

6.2.2 性能优化

在构建可信文件数据流中,操作系统需要向内可信基发出请求,由内可信基完成应用程序页框和操作系统缓存页框之间的数据拷贝,造成了额外的KAS/SAS的切换.针对这一问题,AppISO基于现代操作系统的磁盘缓存特性提出了以下性能优化.事实上,在read系统调用的文件数据流中(如图 5(b)所示),即使内可信基立即将文件数据从操作系统缓存页框复制到应用程序页框,该文件数据也要等到返回应用程序之后才会被使用.因此,AppISO将该数据复制延迟到操作系统最终返回内可信基时,以避免额外的地址空间切换.该思想与第4.5节中针对页表验证的优化类似.同样,该延迟思想对于write系统调用中的文件数据流也适用,因为在现代操作系统中磁盘I/O的传输总是被延迟的.在图 5(a)中,即使内可信基将文件数据立即从应用程序页框拷贝到操作系统缓存页框,该缓存页框中的文件数据也不会马上被传输到磁盘块中.因此,AppISO将该数据拷贝延迟.操作系统只需将缓存页框的地址记录下来,发送到一块共享内存中;当操作系统最终返回内可信基时,内可信基读取该记录,完成数据复制,并代替操作系统将该缓存页框标记为脏页(dirty page).

需要强调的是,虽然不可信操作系统参与到性能优化过程中,但可信文件数据流中文件数据的安全隔离仅依赖于内可信基.

6.2.3 SUID身份验证问题

内可信基的用户验证与Linux中用户验证过程类似,是基于验证用户密码来实现的.内可信基进一步使用公钥/私钥对保证不可信操作系统无法窃取用户密码.

AppISO假设CPU的TPM[10, 11]硬件模块可用,并使用TPM中的存储密钥(storage key)来加密和解密内可信基的私钥.当用户启动自己的应用程序时,将自己的用户密码放置在应用程序的可执行文件里,并使用内可信基的公钥进行加密.内可信基从应用程序可执行文件中获得用户密码,并使用自己的私钥进行解密.然后,内可信基通过验证用户密码赋予该应用程序相应的SUID,标识应用程序的身份.在整个身份验证过程中,AppISO保证了可信链:TPM储存密钥>内可信基私钥>用户密码>SUID.

AppISO虽然在SUID身份验证时使用了加密解密,但是此过程只在应用程序启动时发生,并不会影响应用程序的文件性能.

7 内可信基的安全性

为了实施应用程序保护,内可信基必须具有与虚拟机监控器一样的安全性.本节进一步归纳内可信基必须满足的安全属性,并从攻击的角度对这些安全属性进行证明.

定理1. 在内核不可信的安全假设下,内可信基满足如下安全属性:

(1) 数据代码完整性.内可信基的数据代码不能被外部不可信组件(操作系统和应用程序)读写、执行.

(2) 入口点完整性.外部组件(操作系统和应用程序)只能从指定入口点进入内可信基.

(3) 执行流完整性.进入内可信基后,按照内可信基预先设定的方式运行,执行流不会被外部组件修改.

证明:在系统启动后,系统将处于操作系统初始化、执行应用程序、应用程序请求操作系统服务、操作系统服务以及进程切换等几种工作情况.以下逐一证明各种情况下,内可信基这些安全属性都能得到满足.

(1) 系统启动:系统启动时,首先进入内可信基执行.内可信基初始化整个系统的安全环境,以保证系统在此后运行过程中内可信基的所有安全属性得到满足.具体来说,内可信基一开始运行在root模式,它利用硬件虚拟化设置non-root模式执行环境,并初始化non-root模式中KAS和SAS,然而将整个系统陷入到non-root模式中执行.在non-root模式中,内可信基运行在SAS ring 0层,并通过切换页面和影子IDT技术控制了所有进入SAS ring 0层的入口点.由于此时不可信组件(操作系统和应用程序)还没有运行,并且AppISO通过可信启动硬件保证内可信基映像的完整性,因此内可信基设置安全环境的整个过程是可信的.最后,内可信基启动操作系统在KAS ring 0层中执行.

(2) 操作系统初始化:操作系统在KAS ring 0层完成自己的初始化工作.操作系统无法读写、执行内可信基的数据代码(它们在KAS中映射为不可见);操作系统也无法修改页表映射,因为KAS中页表被只读锁定.硬件虚拟化只允许操作系统从KAS切换到SAS.然而,一旦操作系统试图切换到SAS,内可信基将通过切换页面(唯一方式)获得系统的控制权.对于正常的切换(比如,操作系统请求内可信基更新页表),内可信基完成自己的服务(页表更新和验证),并在返回操作系统时,将CPU切换回KAS,保证操作系统始终只能在KAS中运行;对于异常切换,内可信基将直接重启系统.由于操作系统始终只能运行在KAS中,它无法修改页表映射、破坏内可信基对SAS ring 0层入口点的控制,也无法修改只读的切换页面,破坏内可信基的入口点完整性(入口点由切换页面中的JMP指令指定).此外,由于操作系统进入内可信基时,中断立即被切换页面中的CLI指令禁止,操作系统也无法利用中断破坏内可信基的执行流完整性.因此,进入内可信基后,内可信基在自己的数据代码上(数据代码完整性已保证),按照其预先设定的方式运行.

(3) 执行应用程序:当操作系统离开KAS、执行自己的应用程序时,只能从切换页面进入内可信基.内可信基将应用程序运行在SAS的ring 3层,通过传统特权层隔离的方法(ring 3/ring 0)保证应用程序无法读写、执行内可信基的数据代码,或者破坏内可信基的入口点完整性和执行流的完整性.

(4) 应用程序请求操作系统服务:内可信基通过影子IDT技术控制了所有从SAS ring 3层到SAS ring 0层的入口点,保证CPU一旦从SAS ring 3层陷入到SAS ring 0层(应用程序发出系统调用或者发生中断异常),内可信基将获得系统的控制权.内可信基将相关系统事件转发给操作系统之前,将地址空间切换到KAS,保证操作系统只能在KAS中执行.

(5) 操作系统服务:由于内可信基在进入操作系统时,将CPU切换到KAS,如上面(2)所述,因此,在操作系统服务过程中,也无法破坏内可信基的安全.

(6) 进程切换:当操作系统进行进程切换时,由于它无法切换SAS中的应用程序页表(硬切换和软切换均不能使用),只能向内可信基发出请求.内可信基在SAS ring 0层对应用程序页表实现软切换,并对目标应用程序页表进行验证.此后,内可信基将在SAS ring 3层执行新切换的应用程序.如上面的3)所述,新切换的应用程序也无法破坏内可信基的安全. □

8 原型系统实现

我们在Linux操作系统上实现了AppISO的系统原型.

8.1 系统启动

系统启动时,BIOS首先进入内可信基执行.AppISO依赖于x86的可信启动硬件(TPM)保证内可信基的可信启动.内可信基如表 2所示设置VMCS(具体过程在前文中已论述),配置non-root模式的执行环境,然后将整个系统陷入到non-root模式,并启动操作系统在KAS ring 0层执行,该启动过程使用了Linux的半虚拟化接口.此后,内可信基和操作系统始终运行在non-root模式中,不再陷入root模式.

Table 2 VMCS configurations in system startup 表 2 系统启动过程中VMCS设置

由于x86硬件的限制,non-root模式中的软件执行CPUID指令会无条件地陷入root模式.AppISO的处理方式是:内可信基在启动时(仍运行在root模式时)执行CPUID指令,并将结果保存.此后,应用程序和操作系统以调用的形式直接从内可信基中获得CPUID信息.由于CPUID只在极少的库函数(libc)中执行,我们只需将libc中的CPUID指令替换掉,而无需修改应用程序.更简单的方法是,在root模式中仅保留一小段代码,专门处理CPUID指令.

8.2 进程创建和进程切换

在Linux中,应用程序调用fork()系统调用创建新的子进程,然后子进程调用exec()系统调用加载自己的可执行文件.对于fork(),内可信基通过页表验证,保证子进程映射的内存只能是父进程的克隆.对于exec(),内可信基通过在地址空间中验证文件的ID和偏移(第5.2节),保证被加载的可执行文件的完整性.

进程切换时,内可信基在软切换过程中对目标应用程序页表进行验证.具体的验证过程与半虚拟化类似,内可信基对系统中所有合法的、已验证的应用程序页表进行跟踪和标记,在切换时只需拒绝所有未标记的页表.操作系统在创建进程时,需要将新应用程序页表向内可信基注册,完成验证.

8.3 系统调用参数传输

与传统的虚拟化方法一样,AppISO使用复制的方式在操作系统与应用程序之间传递系统调用参数.当发生系统调用时,内可信基将系统调用参数复制到一块共享内存中,将该内存的地址作为参数发送给操作系统.操作系统在处理系统调用过程中对该共享内存进行操作.当操作系统返回时,内可信基再将共享内存中的数据复制回应用程序.

由于操作系统的请求分页机制,当内可信基试图将共享内存中的数据拷贝回应用程序时,应用程序的页框可能还未分配,因而发生缺页中断现象.针对该问题,最简单的方法就是重新进入操作系统分配应用程序页框,但这会增加额外的地址空间切换.AppISO实现了一种更高效的方式.当应用程序触发系统调用进入内可信基时,内可信基会探测所有的系统调用参数的页框分配情况.如果有页框没有分配,内可信基暂时记录下这次缺页,并在进入操作系统时,在操作系统中模拟该次缺页中断,完成页框分配.这样便有效地避免了额外的KAS/ SAS切换.

8.4 应用程序的透明性

AppISO的整个保护机制对上层应用程序是透明的,AppISO中可以运行任意未修改的应用程序.

在实现应用程序地址空间保护的过程中,AppISO要求应用程序在调用mmap()系统调用时,额外维护地址空间状态链表(见第5.2节).为了保证应用程序的透明性,我们采取的方案是在标准c库中对应用程序的mmap()系统调用进行截获,通过修改标准c库实现应用程序地址空间状态链表的维护.因而,不需要对应用程序本身进行任何修改.

在实现应用程序控制流和I/O保护的过程中,AppISO通过内可信基对中断异常和应用程序的相关系统调用(read()和write())进行截获,透明地实现应用程序上下文保护和可信文件数据流的构建.

在应用程序启动、退出的过程中,AppISO通过内可信基对相关系统调用(fork(),exec()和exit()等)进行截获,透明地实现与安全保护相关的初始化以及程序退出后的清扫工作.此外,考虑到用户需要在应用程序可执行文件中加入自己的密码信息用于SUID验证(见第6.2.3节),AppISO提供了一个简单的工具,可直接在未修改的应用程序可执行文件上完成该操作.

9 实验设计和性能分析

本文选择一系列的开源测试用例,测试AppISO的性能开销.同时将测试结果与虚拟化方法Inktag进行对比.AppISO和Inktag均实现了全面的应用程序保护,包括地址空间保护、控制流完整性保护、文件保护和访问控制等,因此该对比能够比较公平地反映出内可信基方法的优势.实验环境为:CPU Intel i7-3770(4 cores),内存 8GB,操作系统Linux-kernel-3.4.1,编译环境gcc-4.3.1.

9.1 内存保护的性能对比

AppISO和Inktag均实现了应用程序地址空间的隔离和完整性保护.然而,Inktag依赖于虚拟机监控器验证页表,在页表验证过程中需要6次昂贵的non-root/root切换(如图 4(c)所示);而AppISO基于内可信基实现页表验证,仅需要轻量的2次ring 3/ring 0切换和2次KAS/SAS切换(如图 4(b)所示).表 3给出了这3类模式切换在本文实验系统中消耗的具体时间.理论上,Inktag在整个页表验证过程中消耗的切换时间(0.24×6=1.44)大约是AppISO(0.015×2+0.06×2=0.15)的9.6倍.

Table 3 Execution time of different mode switches 表 3 不同模式切换消耗的时间

本文进一步使用lmbench测试用例集[12],测量操作系统中实际内存操作的执行时间,并与Inktag的实验结果进行对比(见表 4).Page fault测量缺页中断处理和页表更新验证的执行时间.Mmap lat测量应用程序调用mmap系统调用映射一块内存所消耗的时间.Fork和fork+exec测量进程创建的时间.由于进程创建时需要频繁的内存映射操作,这两个测试用例也能从侧面反映出内存保护的性能.从实验结果可见,在内存保护上,AppISO相对于Inktag有了明显的性能提升,已接近未修改的Linux的性能.

Table 4 Results of memory performance benchmarks in lmbench 表 4 lmbench中内存性能测试用例的实验结果

此外,2p/0k测量进程切换消耗的时间.在AppISO中,内可信基使用软切换完成进程切换时不同应用程序页表的切换.从测试结果来看,软切换的开销与虚拟化方法的切换开销差不多.需要指出的是,进程切换开销并不是影响应用程序性能的主要因素.

9.2 控制流完整性保护的性能对比

在Inktag中,为保护应用程序的控制流完整性,虚拟机监控器截获系统调用和中断异常,在进入和返回操作系统时均需要陷入root模式,导致了4次non-root/root切换.而在AppISO中只需要2次ring 3/ring 0切换和2次KAS/SAS切换.3类模式切换的性能已在表 3中给出.

本文进一步使用lmbench,测量实际系统调用的执行时间,并与Inktag的测试结果进行对比(见表 5).null call测量应用程序调用一次简单的系统调用(getppid)消耗的时间.Open/Close,file create和file delete对应文件系统相关的系统调用.

Table 5 Results of system call benchmarks in lmbench 表 5 lmbench中系统调用测试用例的实验结果
9.3 文件I/O的性能对比

AppISO和Inktag均实现了灵活的文件访问控制,但两者在具体方法上有着本质的不同.Inktag的文件访问控制基于虚拟机监控器来实现;通过加密和哈希技术,保证文件数据的私密性和完整性.而AppISO的文件访问控制基于内可信基来实现;通过构建可信文件数据流以保证文件数据的安全,并提出基于内可信基的性能优化.

本文参照Inktag的实验环境,在AppISO中测量应用程序以不同窗口大小(window size)调用msync的执行时间,该msync顺序地将一个256M的文件从内存刷新到磁盘.图 6给出了Inktag的msync实验结果(直接从Inktag的图 7复制而来).图中的inktag线给出了Inktag完全实现文件保护和访问控制时,msync的执行时间;inktag-nohash线给出了不使用加密和哈希、仅实现访问控制时,msync的执行时间;linux线作为基准,给出了Linux中msync执行的时间.Inktag的开销主要源于:(1) 文件数据的加密和解密(即图中inktag线相对于inktag-nohash线的增长).(2) 访问控制过程中,为保护元数据(OID、文件偏移、hash值等)的安全,它们被单独存放在由虚拟机监控器控制的磁盘块中.然而,在元数据和文件数据同步时,这导致了频繁的磁盘调度,造成了较高的开销.(3) 虚拟化本身(比如non-root/root切换)也会对文件性能产生影响.图 6中,inktag-nohash线相对于linux线的增长体现了后两类开销.

Fig. 6 Results of msync in Inktag 图 6 Inktag中msync的实验结果

Fig. 7 Results of msync in AppISO 图 7 AppISO中msync的实验结果

图 7给出了AppISO的实验结果,msync的性能接近Linux.原因是:(1) AppISO避免了低效的加密解密; (2) 由于可信文件数据流的构建,访问控制相关的元数据(SUID,文件偏移)不必再单独存放、单独保护,它们与文件数据存放在一起,在可信文件数据流中安全传输,因而避免了频繁的磁盘调度;(3) AppISO避免了虚拟化造成的non-root/root切换.

9.4 应用程序性能对比

与Inktag一样,本文使用DokuWiki测试应用程序的性能.DokuWiki在运行过程中映射大量的文件和匿名内存(anonymous memory),因而可以反映出内存保护和文件保护性能的最坏情况.本文参照Inktag实验中DokuWiki的配置情况和实验方法(具体细节不再重复),将DokuWiki运行在AppISO中,并将AppISO的所有保护机制(内存保护、控制流完整性保护和文件访问控制等)应用到DokuWiki上,最后测量DokuWiki的吞吐量(throughput).表 6给出了实验结果,AppISO的开销仅1.08x,比Inktag(1.54x)有了明显的性能优势.

Table 6 Results of DokuWiki 表 6 DokuWiki的实验结果

此外,本文选择Phoronix Test Suite测试集中一系列应用程序测试用例,来测试其他应用程序在AppISO中的开销.实验结果如图 8所示,测试用例包括computed-bound和I/O-bound两类.I/O-bound类应用程序kernel build和postmark中大量的内存和文件操作带来了一定的开销.

Fig. 8 Results of application benchmarks 图 8 应用程序测试结果
10 相关工作

Overshadow[2]和Inktag[1]基于传统虚拟化技术,依赖于更高特权层的hypervisor实现应用程序保护.Inktag进一步提出Paraverification机制,使得应用程序和不可信内核参与到安全验证过程中,降低了hypervisor安全验证的复杂度,从而有效地减小了可信基规模和系统开销.与Inktag相比,AppISO提出了一种完全不同的保护机制,在不可信内核同一层构建内可信基,实现应用程序保护.该方案有效地避免了传统虚拟化方法由于特权层切换造成的高开销问题.其次,AppISO提出在不可信内核中构建可信文件数据流,保证应用程序I/O的安全,有效地避免了Inktag中低效的加密和哈希计算,明显地提高了I/O性能.另一方面,AppISO也借鉴了Inktag的Paraverification机制,将该机制应用到内可信基的设计实现中,从而有效地减小了内可信基的复杂度和系统开销.此外,需要指出的是,虽然Inktag提供了更加精细的文件访问控制和一致性保护,AppISO基于内可信基同样也能够实现这些保护技术,只不过额外的代价是会增加可信基的规模.

Intel提供了SMEP和SMAP机制[13],保证运行在ring 0层的操作系统无法执行或访问在页表中映射为 ring 3权限的代码或数据,但是不可信操作系统仍然可以通过修改页表来绕过该机制.Flicker[14]基于TPM硬件保护应用程序中的安全敏感代码片段.然而,由于TPM本身的限制,它们无法提供全面的应用程序保护.SICE[15]利用x86硬件的系统管理模式(SMM)在不可信的虚拟机监控器中创建隔离的虚拟机.同样的方法也能应用到保护不可信操作系统中的应用程序,但使用SMM模式进行隔离会导致很大的性能开销,且无法提供全面的应用程序保护和页粒度级的内存保护.其他工作通过改变硬件体系结构[16, 17, 18, 19, 20],实现应用程序隔离.Virtual Ghost[21]提出基于编译器插装和传统的SVM(secure virtual machine)技术,构建可信硬件层,实现应用程序保护.然而,其实现依赖于编译器的可信,但现有安全报告表明,编译器(如gcc)仍然存在许多安全漏洞[22].而且对操作系统代码进行插装,也带来了较大的开销.

此外,针对操作系统的不可信问题,其他工作使用虚拟机自省技术对不可信操作系统进行监控和验证[23, 24, 25],或者直接保护操作系统本身安全,比如Hooksafe[26]保护操作系统中函数钩子,OSck[27]保护操作系统中的动态数据,Secvisor[28]保护操作系统中的代码完整性等等.

11 总 结

本文提出了在不可信操作系统的同一层构建安全隔离的内可信基,并详细介绍了内可信基的内存保护机制、影子IDT机制和I/O验证机制,以及在此之上实现的全面应用程序保护.本文的安全分析表明,内可信基方法具有与传统虚拟化方法一样的高安全性,实验结果和分析也表明,它在性能方面具有明显的提高.

参考文献
[1] Hofmann OS, Kim S, Dunn AM. Inktag: Secure applications on an untrusted operating system. In: Proc. of the Int’l Conf. on Architectural Support for Programming Languages and Operating Systems (ASPLOS). 2013. 265-278 .
[2] Chen X, Garfinkel T, Lewis EC, Subrahmanyam P, Waldspurger CA, Boneh D, Dwoskin J, Ports DR. Overshadow: A virtualization-based approach to retrofitting protection in commodity operating systems. In: Proc. of the Int’l Conf. on Architectural Support for Programming Languages and Operating Systems (ASPLOS). 2008. 2-13 .
[3] McCune JM, Li Y, Qu N, Zhou Z, Datta A, Gligor V, Perrig A. Trustvisor: Efficient TCB reduction and attestation. In: Proc. of the IEEE Symp. on Security and Privacy (Oakland). 2010. 143-158 .
[4] Raoul A, Frank P. Fides: Selectively hardening software application components against kernel-level or process-level malware. In: Proc. of the ACM Conf. on Computer and Communications Security (CCS). 2012. 2-13 .
[5] Zongwei Z, Virgil DG, James N, Jonathan M. Building verifiable trusted path on commodity x86 computers. In: Proc. of the IEEE Symp. on Security and Privacy (Oakland). 2012. 616-630 .
[6] Richard TM, Lionel L, David L. Splitting interfaces: Making trust between applications and operating systems configurable. In: Proc. of the USENIX Symp. on Operating System Design and Implementation (OSDI). 2006. 279-292. https://www.usenix.org/ legacy/event/osdi06/
[7] Intel Corporation. Intel 64 and IA-32 Architectures Software Developer’s Manual. 2013.
[8] Stephen C, Hovav S. Iago attacks: Why the system call API is a bad untrusted RPC interface. In: Proc. of the Int’l Conf. on Architectural Support for Programming Languages and Operating Systems (ASPLOS). 2013. 253-264 .
[9] Intel Corporation. Serial ATA Advanced Host Controller Interface (AHCI) 1.3. 2008.
[10] AMD. AMD 64 Architecture Programmer’s Manual: Volume 2: System Programming. 2011.
[11] Intel. Intel Trusted Execution Technology Preliminary Architecture Specification. 2006.
[12] McVoy L, Staelin C. Lmbench: Portable tools for performance analysis. In: Proc. of the USENIX Annual Technical Conf. 1996. 23. https://www.usenix.org/legacy/publications/library/proceedings/sd96/
[13] Intel Corporation. Intel Architecture Instruction Set Extensions Programming Reference. 2012.
[14] McCune JM, Parno B, Perrig A, Reiter MK, Isozaki H. Flicker: An execution infrastructure for tcb minimization. In: Proc. of the ACM European Conf. in Computer Systems (EuroSys). 2008. 315-328 .
[15] Azab A, Ning P, Zhang X. Sice: A hardware-level strongly isolated computing environment for x86 multi-core platforms. In: Proc. of the ACM Conf. on Computer and Communications Security (CCS). 2011. 375-388 .
[16] Dwoskin JS, Lee RB. Hardware-Rooted trust for secure key management and transient trust. In: Proc. of the ACM Conf. on Computer and Communications Security (CCS). 2007. 389-400 .
[17] Lee RB, Kwan PCS, McGregor JP, Dwoskin J, Wang Z. Architecture for protecting critical secrets in microprocessors. In: Proc. of the Int’l Symp. on Computer Architecture (ISCA). 2005. 2-13 .
[18] Lie D, Thekkath CA, Horowitz M. Implementing an untrusted operating system on trusted hardware. In: Proc. of the ACM Symp. on Operating Systems Principles (SOSP). 2003. 178-192 .
[19] Lie D, Thekkath CA, Mitchell M, Lincoln P. Architectural support for copy and tamper resistant software. In: Proc. of the Int’l Conf. on Architectural Support for Programming Languages and Operating Systems (ASPLOS). 2000. 168-177 .
[20] Shi W, Fryman JB, Gu G, Lee HHS, Zhang Y, Yang J. Infoshield: A security architecture for protecting information usage in memory. In: Proc. of the Int’l Symp. on High Performance Computer Architecture (HPCA). 2006. 222-231 .
[21] Criswell J, Dautenhahn N, Adve V. Virtual ghost: Protecting applications from hostile operating systems. In: Proc. of the Int’l Conf. on Architectural Support for Programming Languages and Operating Systems (ASPLOS). 2014. 81-96 .
[22] Yang X, Chen Y, Eide E, Regehr J. Finding and understanding bugs in C compilers. In: Proc. of the 32nd ACM SIGPLAN Conf. on Programming Language Design and Implementation. 2011. 283-294 .
[23] Dolan B, Leek T, Zhivich M, Giffin J, Lee W. Virtuoso: Narrowing the semantic gap in virtual machine introspection. In: Proc. of the IEEE Symp. on Security and Privacy (Oakland). 2011. 297-312 .
[24] Fu Y, Lin Z. Space traveling across VM: Automatically bridging the semantic gap in virtual machine introspection via online kernel data redirection. In: Proc. of the IEEE Symp. on Security and Privacy (Oakland). 2012. 586-600 .
[25] Srinivasan D, Wang Z, Jiang X, Xu D. Process out-grafting: An efficient out-of-VM approach for fine-grained process execution monitoring. In: Proc. of the ACM Conf. on Computer and Communications Security (CCS). 2011. 363-374 .
[26] Wang Z, Jiang X, Cui W, Ning P. Countering kernel rootkits with lightweight hook protection. In: Proc. of the ACM Conf. on Computer and Communications Security (CCS). 2009. 545-554 .
[27] Hofmann OS, Dunn AM, Kim S, Roy I, Witchel E. Ensuring operating system kernel integrity with OSCK. In: Proc. of the Int’l Conf. on Architectural Support for Programming Languages and Operating Systems (ASPLOS). 2011. 279-290 .
[28] Seshadri A, Luk M, Qu N, Perrig A. Secvisor: A tiny hypervisor to provide lifetime kernel code integrity for commodity oses. In: Proc. of the ACM Symp. on Operating Systems Principles (SOSP). 2007. 335-350 .