CPL:CPU当前的特权级别[cs,ss 第一、二位]
DPL:描述符标特权级别,如果你想访问我,你应该具备什么样的权限
RPL:用什么权限去访问一个段
(1)CPL
CPL是当前执行的程序或任务的特权级。它被存储在CS和SS的第0位和第1位上。通常情况下,CPL代表代码所在的段的特权级。当程序转移到不同特权级的代码段时,处理器将改变CPL。只有0和3两个值,分别表示用户态和内核态。
(2)DPL
DPL表示段或门的特权级。它被存储在段描述符或者门描述符的DPL字段中,当当前代码段试图访问一个段或者门(这里大家先把门看成跟段一样),DPL将会和CPL以及段或者门选择子的RPL相比较,根据段或者门类型的不同,DPL将会区别对待。
GDT全局描述符表中DPL:
中断门中DPL:
陷阱门中DPL:
调用门中DPL:
(3)RPL
RPL是通过段选择子的第0和第1位表现出来的。RPL是代码中根据不同段跳转而确定,以动态刷新CS里的CPL,在代码段选择符中。而且RPL对每个段来说不是固定的,两次访问同一段时的RPL可以不同。操作系统往往用RPL来避免低特权级应用程序访问高特权级段内的数据,即便提出访问请求的段有足够的特权级,如果RPL不够也是不行的,当RPL的值比CPL大的时候,RPL将起决定性作用。也就是说,RPL相当于附加的一个权限控制,只有当RPL>DPL的时候,才起到实际的限制作用。
当当前代码段试图访问一个段或者门时,DPL将会和CPL以及段或门选择子的RPL相比较,根据段或者门类型的不同,DPL将会被区别对待,下面介绍一下各种类型的段或者门的情况。
(1)数据段: CPL(RPL)<= DPL才可以访问
(2)非一致代码段(不使用调用门的情况下): CPL(RPL)=DPL才可以访问
(3)调用门:DPL规定了当前执行的程序或任务可以访问此调用门的最低特权级(这与数据段的规则是一致的)。
(4)一致代码段和通过调用门访问的非一致代码段:CPL(RPL)=> DPL
具体进入https://jadeshu.blog.csdn.net/article/details/103910323
例如一段call 0x666666 代码执行过程
调用门的访问一般通过call、jmp指令的操作数提供的一个远指针,该指针中的段选择子用于指定调用门,CPU会使用调用门中的偏移值实现跳转。如下图:
通过调用门进行程序的转移控制时,CPU会检查以下这几个字段:1.当前代码段的CPL;2.调用门描述符中的DPL;3.调用门描述符中的RPL;4.目的代码描述符的DPL;5.目标代码段描述符中的一致性标志C(一致与非一致下面会提到)。如下图:
对于call和jmp指令,有着不同的优先级检查规则的:
对call来说:当前CPL<=调用门描述符DPL,RPL<=调用门描述符DPL,当前CPL>=目的代码段描述符DPL;
对jmp来说:除了跟call的“当前CPL<=调用门描述符DPL,RPL<=调用门描述符DPL”一样外,如果目的代码段的一致的话,CPL>=目的代码段的DPL,而如果目的代码段是非一致的话,CPL=目的代码段的DPL。
另外,只有call指令可以将代码通过调用门转移到特权级更高的非一致性代码之中。对于非一致性代码的成功转移,CPL被目的代码的DPL刷新,会引起堆栈切换;对于一致性代码,不会刷新,也不会切换。
调用门的作用是,让一个代码段中的过程被不同特权级的程序访问。通常用于低特权级代码来访问高特权级的代码段。
CPL在Code segment register的[1:0]上,代表了当前程序的权限级别。
DPL保存在segment descriptor(段描述符)中,也就是说在GDT或IDT中。
RPL保存在segment selector中。而segment register保存的就是segment selector中,所以问题就是RPL和CPL到底有什么区别?RPL是数据段或堆栈段的bit[1:0],RPL是可以由程序员自己来设置的,但和CPL不同,CPL由CPU控制,无法被代码修改。