CPL、RPL和DPL
一、 Current Privilege Level
1.物理位置
CS寄存器低二位,实际为CS寄存器的RPL字段。
2.作用
表明当前所处的特权等级,一般情况下与DPL相等,不如说CPL实际的来源就是DPL,除向一致性段的跳转以外。
二、 Request Privilege Level
1.物理位置
段选择子寄存器低二位。
2.作用
作为请求跨段跳转的请求特权级,一般情况下与CPL相等,RPL是由用户提供的段选择子寄存器指定,所以用户能够定义不符合规定的RPL,不相等只存在与以下两种情况:
- 用户恶意指定RPL。
- 执行一致性代码段。
三、 Descriptor Privilege Level
1.物理位置
段描述符DPL字段
2. 作用
如果是代码段,指明改代码段运行时的CPL,如果是数据段,指定能够访问该数据段最低特权级。
四、跳转规则
例如
call gs:0x1500
在进行跳转前要把GS寄存器的RPL作为跳转是否能成功的判断依据的一部分,具体判断规则如下:
-
跳转到非一致性代码段,只允许相同特权级的访问:
- RPL特权级 = 目的段DPL特权级
- CPL特权级 = 目的段DPL特权级
-
跳转到一致性代码段,访问段特权级不高于被访问段:
- RPL特权级 <= 目的段DPL
- CPL特权级 <= 目的段DPL
-
门,如中断门,调用门等,***门是低特权级到高特权级的唯一手段(除被访问段是一致性代码段外)***:
- RPL特权级 <= 门DPL
- CPL特权级 <= 目标端DPL
-
系统调用的返回
唯一一种由高特权级向低特权级跳转的方式。
有三点需要注意:
-
上面说的是特权级的高低,并不是CPL、RPL、DPL的实际数值大小,实际数值大小越小,所处的特权级就越高,一共有00、01、10、11四种特权级。
-
RPL是可以由用户自己来指定的,即使CPL为低特权,RPL也能指定为高特权级,即便这样做是恶意的。之所以这么说,是因为***向高特权级跳转后,跳转前的RPL会作为跳转后的RPL,跳转后RPL会作为是否能访问高特权级数据段的依据***。
-
在除一致性代码段跳转之后,CPL=跳转后的DPL,很明显,是为了能够以正确的特权级执行,但是在一致性代码段跳转后,CPL的值会保持原有不变,这也是一致性代码段的由来。
之所以会有RPL,单纯是因为在调用一些重要程序时,操做系统需要知道是谁发出的请求,如果用户发出请求,使CPU进入0级特权,通过一些指定的参数去破坏内核,这是不容许的,所以对于数据段的访问中,必须有以下要求:
-
RPL特权级 >= 数据段DPL
-
CPL特权级 >= 数据段DPL
对于上述第二点,一致性代码段不用操心,因为它本身CPL不变,即使RPL变高也无法访问DPL高特权级的数据段。
对于门调用,操作系统提供了这种问题的解决方案,首先明确,虽然RPL可以由用户指定,但是CPL是不能更改的,RPL的值应该与CPL保持一致,在跳转前,当前的ES:IP寄存器都会被压入跳转后特权级对于的新栈,跳转后的程序从这个栈中获取跳转前CPL的信息,查看当前RPL是否与CPL相同,如不是则用CPL代替RPL,这样就保证了操作系统能够得知访问来自哪一个特权级,从而确定当代码对数据段的访问权限。
需要注意,对于RPL的重置选择权在操作系统手中,CPU完全相信操作系统的选择,如果操作系统没有对RPL进行调整,那么用户进程还是有能力访问内核数据段。
到底什么时候操作系统才不会对RPL进行调整,见进程的实现。
五、三者间的关系
在除一致性代码段以外的段内,CPL=DPL,RPL负责数据访问的控制=跳转前的CPL,如果为同级跳转CPL=DPL=RPL。
在一致性代码段中,CPL取决于跳转前的CPL,DPL由段本身决定,RPL由跳转前的RPL决定。
疑问一:一致性代码段的作用和RPL作用的区别
一致性代码段的出现使得特权级能够跳转到高特权级,而且CPL在保持原本用户级CPL的情况下执行内核程序,这样不就保证了内核数据的安全性吗?毕竟现在CPL是短板,即使RPL再高也无法访问内核数据段,那问题来了,既然如此为什么不让RPL消失算了,对于高特权级的跳转全部采用一致性代码段不好吗?
RPL存在的必要性有两个:
- 对于某些指令,如lgdt,内核是不希望CPL为3的程序来执行它的,如果有这样的情况发生,CPU需要报告异常。
- 在某些情况下,如用户进程申请内存时,必然要涉及到页表的修改,这部分功能不可能不访问内核数据段,这时操作系统当然要选择不根据跳转前的CPL来修改访问数据段时的RPL,从而使得用户进程在执行在内核态时有权利修改页表。当然,这种情况下用户进程是无法指定内核程序操作的目的地址的。
疑问二: 在进行段寄存器的load时,RPL、CPL和DPL的物理实体
之前就有说过,特权级检查仅仅发生在段寄存器的重新加载时,但RPL又是在段寄存器的低两位,感觉逻辑关系很混乱,实际上是这么回事:
CPL:就是在进行跳转时CS寄存器中的低两位。
RPL:想要跳转到的段的选择子的低两位,这个东西不一定要在段寄存中,远眺转时就是显式指定了选择子,或者直接用mov指令修改段寄存器中的内容时,想要移动到段寄存器的内容的低两位。
DPL:准确来说是目标段的DPL,存在于目标段的段描述符中。
1143

被折叠的 条评论
为什么被折叠?



