首页 > 代码库 > CPU特权级保护

CPU特权级保护

1.特权级

1.1特权级

处理器段保护机制可以识别0-3共4级特权级,数值越大,特权越小。处理器通过识别CPL、DPL、RPL这三种特权级来进行特权级校验

(1)CPL:CPL是当前正在执行程序或任务的特权级。它存放在CS和SS段寄存器的0位和1位。通常CPL等于当前代码段的特权级。当程序把控制转移到另一个具有不同特权级的代码段中时,处理器就会改变CPL。

(2)DPL:DPL是一个段或门的特权级别。它存放在段或门的描述符的DPL字段中。在当前执行代码段试图访问一个段或门时,段或门的DPL会用来与CPL以及段或门选择符中的RPL做比较。根据被访问的段或门的类型不同,DPL的意义也不同

(3)RPL:RPL是一种赋予段选择符的超越特权级,存放在在选择符的位0和位1中。处理器会同时检查RPL和CPL,以确定是否允许访问一个段。即使程序或任务有足够的特权级CPL来访问一个段,但是如果提供的RPL特权级不足则访问也将拒绝。即:如果段选择符的RPL的数值大于CPL,那么RPL将覆盖CPL(而是用RPL作为检查比较的特权级)。RPL可以用来确保高特权级的代码不会代表应用程序去访问一个段,除非应用程序自己具有访问这个段的权限--这句话来itel手册,比较抽象,后面会讲解。

2.为什么增加RPL

Intel手册上的解释为:The RPL can be used to insure that privileged code does not access a segment on behalf of an application program unless the program itself has access privileges for that segment.
(RPL能够用来确保具有特权级的代码不会代表另一个应用程序去访问一个段,除非那个应用程序具有访问那个段的权限.)
比方说:A进程的DPL为0,C进程的DPL为1,现在有一个B进程他的DPL为2,这B进程想委托A进程(外围程序可以访问一致代码段的内核)去访问C的数据(内核可以访问外围数据),
如果没有RPL来限制的话,这样的委托访问是可以成功的,但这样是非常不安全的。
有了RPL以后,A进程在访问C的时候还要受到RPL的约束,此时可以将访问C的选择子的RPL设为B的DPL,这样A的访问权限就相当为EPL=max(RPL,DPL)=2,这样他就无法代表B去越权访问C了。(那还要委托A干嘛?反正B如果不够权限,委托谁都没用;如果B有权限,不用委托别人也可以啊?)
有RPL的情形,CPU同时检查CPL和RPL来判断是否允许对一个段的访问。在低特权级代码调用高特权级代码时,你可以把RPL认为是调用者CPL的影子。即使高特权级代码在运行,但它是应低特权级代码的请求,作为低特权级代码的代理在执行任务,在必要的时候,RPL作为对CPL的覆盖,可以削弱当前执行代码的可访问的区域,从而保证高特权级代码不会代表低特权级代码去访问一个后者没有访问权限的段。
这里有一个问题,就是低特权级代码在向高特权级代码传递段选择子时,可以任意设置RPL。所以x86处理器有一条专门的指令ARPL用来纠正RPL。

3.RPL的理解

CPL和DPL都是见字面就能理解含义的。唯独RPL不容易理解。
今天就说说我的理解,将来回头来看看,今天说的到底对不对。
1、- 当前进程的意愿 -
RPL代表了当前进程的意愿(因为是一种request)。注意,是当前进程的意愿而不是别的进程。其次是一种意愿,是否实现还有待CPU的许可。
2、- 不能超越自己的特权级 -
前面的帖子已经说了,RPL可以由当前进程随便写,但是CPU会检查RPL和CPL的取值,如果RPL填写的特权级比自己实际情况还高,CPU就不会认可,仍旧给他当前的权限。
3、- 只能下降权限 -
鉴于上面的原因,使用RPL的真正情况就是当前进程使用比自己低的或者相同的RPL。这种情况最典型的,就是外围程序A调用内核B,然后通过内核B再访问程序C。由于访问的来源是A,所以内核为了安全起见,将RPL(来自A的访问意愿)设置为A的DPL。这样在逻辑上就完整了。内核就不会越俎代庖了。

参考:

http://www.360doc.com/content/11/0429/12/6580811_113130013.shtml

http://blog.csdn.net/MOOD/article/details/4623763