x86中分为0,1,2,3四个特权环,数值最小的特权级最高,随着数值增加特权级降低,intel这么安排是十分合理的,如果知道低特权级的实体不能访问高特权级的实体,那么就可以写出不出错的程序,但是这样的程序不是安全的,如果想写出安全的程序,那就必须知道高特权级的实体并不是总能访问低特权级的实体,还要看它此时代理的是哪个特权级的实体,这就是intel的特权环的第二层含义,intel的特权环的设计简直可以称为绝妙,不但保证低特权级不能访问高特权级,而且保证了高特权级不能滥用职权,这个意义十分符合现实世界的模型,可是现实世界却没有intel设计的理想世界那么天衣无缝。
intel的特权环中有几个概念,一个是CPL,一个是RPL,一个是DPL,CPL就是当前执行绪CS寄存器的低两位,代表当前执行绪的特权级,而RPL某些时候代表当前执行绪是在代理哪个特权级的工作,也就是它在代替哪个特权级的执行绪办事,DPL就是被访问对象的描述符的特权级,intel根据这三个XPL和它的特权环机制实现了数据的访问控制,就是说,如果要访问一个数据,那么在分段的保护模式中必然从段描述符中访问,该描述符中有一个DPL,当前的CPL的数值大于DPL是绝对不能访问的,但是当前的CPL小于或者等于DPL就可以获得访问权了吗?如果按照intel特权环的第一层意思,那么就可以了,但是因为有第二层的意义存在,导致cpl即使小于等于dpl也不能保证访问可以获得允许,还要看看rpl,如果rpl起了作用,而且rpl大于dpl的话,访问还是不允许的,只有在dpl同时大于cpl和rpl的情况下,访问才是允许的。这么复杂的机制的现实意义是什么?其实大可不必埋怨这种机制复杂,其实它再显然不过了,试想一个低特权级的代码通过中断或者异常陷入了一个高特权级的代码,然而这个高特权级的代码有漏洞,这样的话,陷入后的特权级的代码拥有了高特权级,这样就可以在漏洞下操作高特权级的数据,甚至将之复制到低特权的缓冲区了,这样系统将不再安全,但是如果有了intel特权环的第二层意义的保护,那么即使低特权级的代码陷入了高特权级,高特权级的代码还是代表低特权级执行的,也就是此时它的rpl是低特权级的,于是访问被拒绝。访问控制必须提供一个机制,即使在规则被破坏的情况下,系统也是安全的,就好像人们可以选举出来一个总理,官够大了吧,但是人们不能保证这个拥有特权的总理总是为人民服务,这样就必然需要一种机制,这就是弹劾。这个道理就和以法治国和以德治国的区别一样,后者表示不提供任何机制,仅仅靠约定的规则来维持稳定,而这样的国家弄不好将是很不稳定的。
intel特权环的第二层意义的精髓就是cpu不能保证任何代码都遵守约定,如果不能保证这些,那么就有必要提供一些内部约束。比如中断,在linux中,如果要防止用户用int指令访问硬件中断处理程序,那么很简单的将硬件中断处理程序的描述符的dpl设置为0就可以了,而专门用来int软中断调用的门的描述符的dpl设置为3,这样就简单的实现了访问控制。intel就是依据现实世界设计出了特权环机制,但是现实世界工作得确实没有intel的处理器工作得好。intel特权环的规则远远要比我上面说的要复杂,规则之所以如此复杂就是在于它并不承诺提供一个统一的机制,而是完全模仿这个复杂又善变的世界,基于对象来实现访问控制而不是基于理想中的统一规则,intel特权环就是通过限制发出访问的对象的访问而不是通过保护被访问对象来实现访问控制的。
现在考虑一下linux的系统安全机制,其实就是继承的unix的uid/gid以及资源的可读,可写,可执行的模型,这种模型非常统一,将所有的要被访问的对象都统一的称作资源,然后所有的资源在系统内部形成文件系统,这也就是unix/linux中“一切皆文件”的意义,linux通过保护资源来实现访问控制,再次重申一遍,这个机制十分统一,在一本书中看到,这样的机制偏重人-机接口中机器的一方,之所以统一就是因为偏重机器,而机器要比我们复杂的人统一的多,如果要偏重人这一边,那么访问控制机制将变得非常复杂,毕竟人就是不统一的。unix的安全模型具备统一性,这是很不错的,因为它可以随时增加新的安全机制,只要将新的安全机制映射到老的“unix的uid/gid以及资源的可读,可写,可执行的模型”就可以了,比如,现在linux就实现了lsm,这个lsm十分简单,就是在设计者认为会出现潜在安全问题的地方挂载钩子,具体怎么发现哪些地方会有潜在的安全问题就要靠经验和专业的安全模型了,linux的安全模型不需要将发现“哪些地方会有安全问题”纳入自己的安全模型,自己的安全模型中只需要实现一旦发现了这样的潜在地方应该怎么做,而这十分简单,就是往统一的模型上映射就可以了。往相反的一端看,就可以看到windows的安全模型,它注重的是和linux相反的一面,它拟在提供一个全面的安全框架,负责安全的方方面面,于是它的安全模型就是基于对象的访问控制,windows的安全框架十分复杂,几乎也是一个和人类社会一样的东西,可想而知,它偏向人-机接口的人的方面,它实现的很累,几乎想囊括一切安全的因素,将一切安全因素纳入自己的框架,于是每个对象的结构光安全相关的东西就占据了很大一部分,而且不同对象的安全结构不统一,因此每一类对象都有一个对象管理器,其实之所以每类对象都有一个管理器是因为不光安全结构,windows中的对象的所有结构几乎都是按类区分,不同类的对象的相同机制的数据结构却不相同,因此每一类才需要一个管理器来管理这一类对象(因为不统一从而没有任何一个管理器可以管理所有的对象)。以上这一点可以用面向对象的思想理解一下。windows的设计本身就没有按照统一的思想,因为它偏向人-机的人而不是机器,人总在变化,因此windows总在变化。unix几十年不大变就是因为它偏向于人-机的机器一方,它虽然不像windows那样操作方便,但是却非常稳定。
通过intel的特权环说了上面那么一大堆,最后我想了一下,unix/linux不是很适合intel的处理器,倒是windows和intel的处理器情投意合。
本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1274148