x86-6-特权级

特权级(Privilege Level),是描述符和段选择子中的一个字段,当使用描述符或者选择子时,该字段用来控制将要进行的操作。比如说:切换一个段的时候就会对该段的特权级进行判断。

Intel CPU有4 个特权级别,分别是0 到3,较大的数值意味着较低的特权级别,在Windows中只采用了0和3,也就是常说的0环和3环,其中操作系统的代码处于0环特权级,而应用程序的代码赋予3环的特权级。

特权级(privilege)检查:

前面我们知道保护模式一共有三种类型特权级,分别是:

特权类型内容
CPL(Current Privilege Level) 当前特权级,表明当前代码的特权级,CPL的值存放在CS段选择子寄存器的Selector字段的RPL字段中,SS段选择子寄存器的RPL和CS.Selector.RPL始终是一样的所以SS.Selector.RPL也是CPL。
DPL (Descriptor Privilege Level) DPL存放在描述符里的DPL字段中,表明访问这些段所需要的权限。
RPL(Requested Privilege Level) 存放在段选择子中的特权级字段,表明请求获得该段描述符时所提供的特权级。

对于特权级的检查,一般是在修改段寄存器时出现的检查。

比如说这样一段程序:

jmp  0x0010:0x00000000

mov ax,0x0008 ;0000 0000 0000 1000
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax

其中0x0010和0x0008是段选择子,这里的段选择子就是进行请求更换段描述符的段选择子,所以里面存放的就是RPL(Requested Privilege Level)。

这段代码肯定要运行对吧,那么运行肯定就有运行的环境,而保护模式的环境下肯定是有CS,SS段寄存器的,此时CS,SS的段寄存器中的段选择子中的特权级就是CPL(Current Privilege Level)。而此时我们请求的段选择子肯定会对应一个段描述符,而这个对应的段描述符里也有一个特权级就是这里的DPL段特权级。

基本特权级检查

 

1: 高特权级别的程序可以访问低特权级别的数据段,但低特权 级别的程序不能访问高特权级别的数据段。访问数据段之前,肯定要对 段寄存器DS、ES、FS 和GS 进行修改,比如:

mov fs,ax

在这个时候,要求当前特权级CPL 和请求特权级RPL 都必须高于, 或者和目标数据段描述符的DPL 相同。即,在数值上,

CPL<=目标数据段描述符的DPL
RPL<=目标数据段描述符的DPL

2: 对于依从的段,要求当前特权级CPL和请求特权级必须小于或等于目标段描述符的DPL(用的比较少)

CPL>=目标代码段描述符的DPL
RPL>=目标代码段描述符的DPL

3: 对于栈段,要求当前特权级CPL和请求特权级必须等于目标段描述符的DPL

CPL == DPL
RPL== DPL

 

提高权限:

由于特权级的检测导致用户层只能在自己的特权级下进行工作,但是如果用户层也想调用内核层的代码实现某个功能怎么办?

这个时候就有了门的用处了,前面我们提到段描述符时讲到过系统段里面有Gate(门),这么一个特殊存在,它就是专门来让我们实现通过3环来到0环的空间的关键。

通过采用调用门,中断门,陷阱门和任务门可以来提高权限来帮助我们从3环到达0环:

x86-6-特权级-1-调用门(32-Bit Call Gate) - Sna1lGo - 博客园 (cnblogs.com)

x86-6-特权级-2-中断门(32-Bit Interrupt Gate) - Sna1lGo - 博客园 (cnblogs.com)

x86-6-特权级-3-陷阱门(32-Bit Trap Gate) - Sna1lGo - 博客园 (cnblogs.com)

x86-6-特权级-4-任务门(Task Gate) - Sna1lGo - 博客园 (cnblogs.com)