跨特权级调用
通常发起调用的函数和被调用的函数都是位于同一个特权级的代码中的,这种调用叫做同特权级调用,另一种情况是位于不同特权级代码段中的代码互相调用,被称为跨特权级调用。跨特权级调用通常是通过一个所谓的调用门(Call Gate)来完成的。调用门的全称是调用门描述符( Call-Gate Descriptor),其结构与中断描述符非常类似,调用门描述符可以出现在GDT和LDT表中,不可以出现在IDT表中。
在调用门描述符结构中包含SegmentSelector (段选择子)用来指定被调用代码所在的段,offset in segment 用来指定被调用代码的偏移地址。DPL代表了这个段描述符的特权级别,下面以低特权级的代码调用高特权级的代码为例介绍CPU执行跨特权级的调用过程。
1. 进行访问权限检查,如果检查失败,则产生保护性异常
2. 将SS,ESP,CS,EIP寄存器的值临时保存到CPU内部
3. 从任务状态段(TSS)中找到目标代码所处特权级的栈信息,并将段选择子和栈指针加载到SS和ESP寄存器中。这一步进行的动作经常被称为栈切换。
4. 将第二步保存的SS和ESP寄存器值依次压入新的栈,这一步的目的是将发起调用的代码的栈信息压入到被调用代码所使用的栈。
5. 将参数从发起调用的栈复制到新的栈。调用门中的Param Count(参数个数)字段描述了要复制的参数个数,这里是以DWROD为单位i,最多可以复制32个DWORD。
6. 将第二步保存的CS和EIP值压入到新的栈中。
7. 将要调用的代码段的段选择子和函数偏移分别加载到CS和EIP寄存器中。
8. 开始执行被调用的代码
CPU在处理中断或异常时,如果CPU当前正在执行用户代码段中的特权级别代码,而中断处理例程位于高特权级别的内核代码段中,那么CPU所做的动作与上面的跨特权级调用非常类似,只不过使用的是中断描述符。Windows操作系统使用INT 2E 或专门的快速系统调用指令来实现从用户态(低特权)到内核态(高特权)的系统调用,没有使用调用门。但是某些rootkit使用调用门来从用户态调用内核空间的代码。
作者 shifters
补充:综合编程 , 安全编程 ,