李天佑 翟高寿
(北京交通大学 北京 100044)
操作系统安全是计算机及信息系统安全的基础。传统的操作系统安全加固和安全增强主要通过在现有操作系统平台上引入和完善强制访问控制机制来实现,如Linux操作系统内核中嵌入了基于RBAC[1]、TE[2]和MLS安全模型的SELinux[3]。但必须指出,这种安全加固的模式是建立在传统两层特权级的操作系统体系结构上。由于第三方代码仍然可能通过各种途径成为核心代码或运行在核心代码独享的特权级上,故而有可能通过核心违规获得各种客体资源的访问权限和实施破坏操作。
只有保证了操作系统核心运行的安全,才能根本上保证在此基础上进行的访问控制等模式的安全加固起到系统安全增强的作用。现有主流操作系统将运行空间划分为核心层和用户层两个层级,并将所有操作系统内核模块代码安排部署在一个公共的、共享地址空间的核心层运行。这样,在操作系统实现外设兼容和内核模块扩展特性的过程中,任何添加到操作系统内核中的外部第三方代码都可能威胁到整个系统的安全,研究和设计一种超越两层特权级、有效分离操作系统核心内核和包括外部第三方内核级代码在内的系统功能的操作系统安全体系结构很有必要。
根据操作系统的资源管理特性,操作系统逻辑上等同于倒金字塔形的控制管理结构[4]。作为运行平台的操作系统内核具有管理计算机系统资源和为用户提供功能服务两个功能。操作系统内核运行是内核模块部分在核心内核的组织下为用户进程系统核心服务功能的过程。依据角色访问控制原理,操作系统安全通过赋予操作系统不同运行空间不同访问权限并进行与之对应的访问控制实现,因此操作系统安全性能提高的关键是操作系统运行空间访问权限的细化。本文提出的操作系统安全体系结构将操作系统内核拆分成对系统资源进行组织管理的核心内核和为用户进程提供服务的内核模块两个相对独立的部分,使内核模块部分从核心特权级空间剥离[5],由此内核空间划分成核心内核空间和内核模块空间,因而提出基于三层特权级的操作系统安全体系结构。系统结构如图1所示。
图1 基于三层特权级操作系统结构
表1 各个特权级运行空间的数据及代码分布
核心内核是操作系统运行的组织者和管理者,具有最高的系统权限。核心内核由内核进行系统管理控制的部分组成,包含系统管理的内核代码和全局数据。核心内核作为系统运行的控制顶层,具有最高权限。保存在核心内核空间中的段页表等全局数据属于核心内核,通过核心控制空间对其进行隔离保护,保证了存放于核心控制空间的全局数据的安全性。内核服务模块通过篡改核心全局数据取得核心权限进而控制整个操作系统隐患被消除。
系统运行过程中,关于内核模块的使用存在两种情况:(1)用户进程执行过程中,由于发生中断(包括系统调用或外部中断等)切入到核心内核态并获得内核模块服务,如图2所示。(2)内核模块运行过程中,由于产生外部中断而需要执行新的内核模块,如图3所示。
图2 从核心内核态获得内核模块服务的过程
图3 内核模块被外部中断的情况
内核模块是操作系统内核为用户提供功能性服务的模块概括性总称。内核模块通过系统隔离机制与核心内核分隔开来,而内核模块空间内部各个功能模块之间也在核心内核的控制管理下进行有效隔离,杜绝因个别功能模块问题影响系统服务的安全。内核模块与核心内核的交互通过核心内核为内核模块层提供的调用接口实现,将内核功能模块存在的漏洞限制在其自身的运行空间内。为了表述内核模块空间中内核功能模块独立运行的过程,引入内核模块运行体的概念。内核模块运行体是内核模块运行的状态、服务的对象、占有的资源、运行上下文概况性描述。
操作系统核心细化隔离保护有三个方面:不同层次间运行空间的隔离保护、输入/输出隔离保护、内核模块间隔离保护。为有效进行隔离保护,必须依靠芯片级硬件存储保护机制。Intel i386体系计算机保护模式运行过程中空间分为具有不同特权级的4层,通过硬件的存储保护模式为系统软件提供分层保护[6]。
根据计算机系统的程序存储式结构,操作系统进行分层隔离所针对的对象即为存储地址空间以及程序指令(寄存器通过指令寻址,因此隔离对象同时包括寄存器)。I386体系保护模式采用分段寻址的方式,通过段描述符描述段内数据性质、访问权限、线性地址基址和段界限在内的地址空间段的情况。段描述符引入段界限和段优先级的概念,规范、限制和保护对系统运行空间的访问。
利用i386体系保护模式提供的硬件存储保护机制,将系统运行空间分为三层:核心内核层(特权级0)、内核模块层(特权级1)、用户层(特权级3)。不同层次存储空间的隔离通过GDT中段描述符DPL赋值实现。
运行中的内核模块属于用户进程的系统服务部分。进程和因处理进程系统调用而运行的内核模块在系统运行过程中的状态必须保持同步。内核模块因等待外部设备或者核心内核分配资源阻塞的过程中,进程也必须进入阻塞的状态。进程切换的同时也必须进行内核模块空间内核模块运行栈之间的切换。
内核模块针对服务对象进程的数据共享传输有核心内核控制完成。在用户进程通过系统调用进入内核模块服务时,向核心内核传入数据段指针。在核心内核切换到内核模块运行过程中,此数据段暂时向提供服务的内核模块开放读写权限,此权限伴随着内核模块的关闭被核心内核收回。
内核模块之间的隔离表现在两个方面,一个是杜绝各个模块间的同特权级直接调用,防止因个别内核模块的不安全问题影响系统内核服务功能。根据这一原则,内核模块之间不提供调用接口,当正在运行的内核模块需要使用其他模块提供数据或者调用其他模块的方法时,需要返回核心以系统调用的方式请求需要的内核模块提供服务。
另一方面,空间内的功能模块运行体属于不同的进程,而且还有一个单独的内核模块运行体服务核心内核用以处理中断,这些运行体之间不能相互影响因此必须分配不同的运行栈空间,同时也有效分离不同进程对同一内核模块的服务请求。
三层特权级结构设计实现便于理论验证的兼具开放性方便后续功能开发的操作系统。本文提出的原型验证系统核心完全自主开发,功能应用部分参考M inix操作系统[7]。目前系统支持i386结构。原型系统验证环境为VmWare虚拟机和Bochs虚拟机。
目前原型系统开发已经完成:核心内核:内存管理、进程管理(进程调度、进程切换、进程管理、简单进程间消息传递)、中断处理、基本系统调用;文件系统:通过文件系统接口实现FAT12;设备管理:块设备管理(软盘驱动)、字符设备管理(控制台)。并在此基础上实现简单的shell程序,并对txt文件进行修改操作。原型系统的总体结构图如图4。
图4 原型系统总体设计Fig.4 The overall design of the prototype system
这一设计与传统操作系统的区别是将系统功能服务的内核模块与核心内核特权级分离,在传统操作系统的基础上引入具有特权级1级的内核模块空间。因此原型系统设计实现的关键在于内核模块层的组织管理,需要引入对内核模块进行控制和管理。而核心内核层和用户空间与传统操作系统的系统态和用户态两个层级基本一致[8],读者可参考 Linux代码分析,不在赘述。操作系统结构变化带来了系统运行优先级的变化。系统运行优先级从高到低依次为:核心内核、服务中断的内核模块运行体、服务于系统调用的内核模块运行体、用户进程。
3.2.1 内核模块控制体
内核模块结构体唯一描述运行中的内核模块。作为可执行体,表征内核模块的数据中应包含两个部分,一是模块状态属性,二是模块运行上下文。同时,为了对模块运行状况进行管理,定义了与模块运行控制相关的若干属性。内核模块结构体如下所示:
内核模块运行必须的程序入口和运行环境在装载内核模块的过程中存放与regs数据结构中。其他属性用来对加载内核模块的状态进行控制管理。call_proc用来区分内核模块的服务对象,call_state指示内核模块的状态。call_type指示此内核模块服务对象的属性。next指针,用以连接其他装载后的内核模块。
内核模块空间运行栈管理依赖三组数据:内核模块运行栈、内核模块运行栈数组和内核模块运行栈队列。外部中断处理内核模块运行栈处理由核心内核响应外部中断控制内核模块执行的运行体,此运行体的服务对象为核心内核具有最高运行优先级,其被加载到 call_list队列头部。核心通过内核模块运行体数组对内核加载后的内核模块运行栈进行管理,通过队列call_list组织加载的内核模块运行。
3.2.2 内核模块生命周期及状态切换
运行的内核模块生命周期始于装载过程中运行栈的建立和相关资源的分配,结束于核心内核回收资源和删除内核模块运行栈。在内核模块的一个生命周期内有四种状态:就绪;运行;阻塞;结束。这四种状态之间的转换关系如图5。
图5 内核模块状态转换关系Fig.5 The relationship of kernel module status transition
就绪状态,内核模块运行栈加入内核模块运行队列等待执行。运行状态表示此时内核模块占有计算机运算资源运行。阻塞状态表示此时内核模块由于等待某些资源或者环境而处于被阻塞的状态,由于核心内核请求的外部中断处理内核模块运行体属于核心内核,具有最高的系统运行优先级,因此不会等待资源,进而不会处于阻塞状态。结束状态表示内核模块完成服务功能正常退出或者由于核心内核控制下被强制退出。
图5中①表示服务核心内核的功能模块运行栈开始执行或者被加载到内核模块运行体队列中的内核模块运行栈开始执行。②表示在核心内核控制下,内核模块运行体由就绪状态直接被删除。③表示内核模块执行体响应内核服务请求结束或者由核心内核控制下内核模块运行体直接被关闭删除。④表示阻塞的内核模块运行体被核心内核唤醒。⑤内核模块运行体需要等待资源而被阻塞。⑥表示处于阻塞状态的内核模块运行体被核心内核控制直接关闭删除。⑦表示在某些情况下由于中断停止内核模块运行体的执行,在需要保证内核模块的服务与外设交互的时效性的情况下,操作系统允许内核模块通过软中断的方式返回核心内核通过修改内核模块运行栈中的内核模块运行上下文关闭或打开部分中断。
服务核心内核的内核模块运行体由于其服务对象具有最高优先级,因此只存在①、③和⑦三种状态转换情况。
3.2.3 内核模块的管理
系统功能模块运行是核心内核根据中断和系统调用加载。外部设备和系统调用中断发生时,系统进入核心内核的基本中断处理过程,核心内核基本中断处理根据发生中断的中断号和寄存器中传递的参数(系统调用号、中断功能号)取得内核模块号,通过系统功能号查找加载对应的系统功能模块。
新建内核模块运行栈的过程是查找内核模块运行栈数组中未被占用的元素,将内核模块入口、运行上下文、运行状态、服务对象、模块类型等信息写入。服务核心内核的内核模块加载过程与此类似,区别在于不新建运行栈,将内核模块运行体直接加载到中断处理模块运行栈中。
内核模块空间的运行顺序为先中断处理模块运行栈,当中断处理模块运行栈为空时,顺序运行队列 call_list队列中后续的内核模块运行栈。
内核模块空间的管理主要工作围绕着对内核模块运行栈队列的维护以及内核模块运行体的操作上。针对内核模块加载和状态转换等系统功能模块管理工作设计了以下主要函数:
根据系统规定的运行优先级,当核心内核运行栈为空即内核操作完成时将进行运行空间的切换。切换的顺序为先进入内核模块空间,当内核模块空间的运行栈队列没有等待运行的内核模块存在时切换进入用户进程空间执行。
3.3.1 核心内核层到内核模块层的切换
从核心内核空间(特权级0)到内核模块空间(特权级1)的跳转是用IRET实现的,在核心内核基本处理中断结束后存在call_list不为空的情况下进行。空间切换之前将call_list头节点 RING1CALL数据结构中的切换上下文放入相应的寄存器中,IRET指令实现跳转。
3.3.2 核心内核层到用户空间层的切换
用户空间到核心的切换与传统的操作系统结构相同,通过IRET指令实现从核心到用户的跳转。本设计和原型系统的实现参考了 M inix操作系统[7]。用户态通过进程的方式组织运行。具体设计实现过程不再赘述。与之不同在于核心到用户态跳转的条件是功能实现层无等待运行的功能实现模块。
3.3.3 用户空间层到核心内核层的切换
用户层到核心通过系统调用的方式实现,系统调用通过INT指令完成。本设计中提供了两个主要的系统调用模式:核心层系统调用、功能实现层系统调用。分别应用了80号和90号INT中断。
80号中断响应过程参考了Linux中断相应的过程[8]。
90号中断响应过程与80号相同,区别是核心内核中基础中断处理对应的处理过程通过_add_ring1_call函数添加功能处理核心模块。
3.3.4 核心内核层到核心内核层的切换
内核模块层到核心内核的跳转也是通过INT指令中断实现的。本文原型系统中通过91号和92号中断分别实现功能模块的完成返回核心和功能模块系统调用两个系统调用。为防止用户程序对这两个系统调用的误操作,此原型系统中,91号和92号中断核心内核的基本中断处理对调用的客体层级进行检测,隔离用户空间对这两个中断的使用。
安全性分析:Linux等二元结构的操作系统中核心代码复杂的功能实现部分或者被第三方装载恶意代码,操作系统核心之上的访问控制就形同虚设。如利用网卡驱动中传输数据无空检测的漏洞,产生溢出异常进入系统核心获得超级用户权限。此设计过程中,网卡驱动被独立在模块内核空间中,溢出错误将被隔离在内核模块空间内,在核心内核的控制下将此内核模块运行体关闭删除。
性能测试:验证系统中一次中断涉及多次特权级转换,必然带来系统运行效率的下降。为了定量分析设计中特权级转换对于系统运行效率的影响采用如下方法进行了测试:提供一个核心内核直接处理的系统调用(空操作),提供一个内核模块处理的系统调用(空操作),加载进程分别调用 10万次、20万次和30万次两种空操作,分别记录系统调用前和调用后系统滴答数,比较两种系统调用处理方式之间的用时。
通过统计学原理求两种系统调用处理方式耗时之比的平均值为138.006%。由此可以得出结论:同等条件下,特权级转换过程中基于三层特权级的操作系统通过内核模块处理系统调用效率下降将近40%左右。
本文提出的三层隔离安全操作系统结构,根据内核功能控制管理层次权限细化分层隔离,由i386硬件存储保护保证核心内核不被内核模块实现层部分篡改,同时保证用户进程不会影响内核模块实现的正常运行。有效防范系统性的安全风险,提高系统的整体安全稳定性。
从实验结果看,系统运行效率还有很大的提高前景。下一步的研究目标主要是细化系统控制管理与功能实现之间交集部分代码权限,更大限度的丰富核心内核功能,减少核心内核与功能实现层之间特权级之间的切换频度,提高系统运行效率。深入研究通过三层隔离手段构建系统中存在的资源共享与互斥的问题,提高系统的并行效率和稳定性。
[1]WALKER KM.STEME DF.BADGER ML,et a1.Confining root programs w ith domain and type enforcement(DTE)[A].Proceedings of the 6th USEN IX Security Symposium[C].Usenix Association,1996.2l一36.
[2]BELL DE,LAPADULA LJ.Secure computer systems:unified exposition and multics interpretation[R].MTR-2997,M ITRE Corp,1976.
[3]Gaoshou Zhai,Raodong Li.Study and Implementation of SELinux-Like Access Control Mechanism Based on Linux[C].International Conference on Security Technology Hainan,DEC 13-15,2008,pp.50-56.
[4]Gaoshou Zhai,W enlin Ma,M inli Tian,Na Yang,Chengyu Liu,Hengsheng Yang.Design and implementation of a tool for analyzing SELinux secure policy[C].Proceedings of the 2nd International Conference Page:446-451,2009.
[5]谢钧,张韬,张士庚,黄皓.一个分层隔离的操作系统内核[J].计算机应用.2005年6月.第25卷第6期.pp.1286 – 1289.
[6]李忠,王小波,余杰.x86汇编语言:从实模式到保护模式[M].北京:电子工业出版社.2013,375.
[7]Andrew S.Tanenbaum,Albert S.W oodhull.Operating Systems:Design and Implementation[M](Third Edition).New Jersey:Prentice Hall.2006.1054.
[8]赵炯.Linux内核完全注释[M].北京:机械工业出版社.2004.652.