调用门实战(2)----调用门特权级转移理论篇
2010-11-20 19:26
239 查看
假设我们想由代码段A转移到代码段B,运用一个调用门G,调用门G中的目标选择子指向代码B的段。这里有几个要素:CPL、RPL、代码B得DPL(DPL_B)、调用门G的DPL(DPL_G)。A访问调用门G是,要求CPL和RPL都小于等于DPL_G。即CPL和RPL需要在更高的特权级上。
除了上面一步符合要求之外,系统还将比较CPL和DPL_B。如果一致代码段的话,要求DPL_B<=CPL;如果非一致代码段的话,call指令和jmp指令有所不同。call指令要求DPL_B<=CPL;在用jmp指令时,只能是DPL_B=CPL.
综上所述,调用门特权规则如下图:
通过调用门call指令,可以实现从低特权级到高特权级的转移,无论目标代码段是一致的还是非一致的。
在有特权级转移时,堆栈也会随之变化,见下图
每个任务最多可能在4个特权级间转移,所以每个任务实际需要4个堆栈。可是我们只有一个ss和esp,在发生堆栈切换时,从哪里获得其余堆栈ss和esp呢?从TSS(Task-State Stack)。32位TSS如下图所示:
TSS包含多个字段,这里只需要关注偏移4到偏移27的3个ss和3个esp。当发生堆栈切换时,内存的ss和esp就是从这里取得的。比如我们当前所在的ring3,当转移至ring1时,堆栈将被自动切换到由ss1和esp1指定的位置。由于只是外层到内层(低特权级到高特权级),切换时新堆栈会从TSS中取得,所以TSS中没有位于最外层的ring3的堆栈信息。
了解了堆栈问题,就可以屡清特权级转移了。
调用门从外层到内层的转移过程:
1、根据目标代码段的DPL(新的CPL)从TSS中选择应该切换到哪个ss和esp
2、从TSS中读取新的ss和esp。在这过程中如果发现ss、esp或者TSS界限错误都会导致TSS异常(#TS)
3、对ss描述符进行检查,如果发生错误,同样产生#TS异常
4、暂时性保存当前ss和esp值
5、加载新的ss和esp
6、将刚刚保存起来的ss和esp的值压入新栈
7、从调用者堆栈中奖参数复制到被调用者堆栈(新堆栈)中,复制参数的数目由调用门中Param Count一项来决定。如果Param Count是零的话,将不会复制参数。
8、将当前的cs和eip压栈
9、加载调用门中指定的新的cs和eip,开始执行被调用过程。
第7步中,ParamCount只有5位,最多只能复制31个参数。如果参数多于31,可以让其中某个参数变成指向一个数据结构的指针。
ret指令返回的步骤:
1、检查保存的cs中的RPL以判断返回时是否要变换特权级。
2、加载被调用者堆栈上的cs和eip(此时会进行代码段描述符和选择子类型和特权级检验)
3、如果ret指令含有参数,则增加esp的值以跳过参数,然后esp将指向被保存过的调用者ss和esp。注意,ret的参数必须对应调用门中的Param Count的值。
4、加载ss和esp,切换到调用者堆栈,被调用者的ss和esp被丢弃,这里将会进行ss描述符、esp以及ss段描述符的检验。
5、如果ret指令含有参数,增加esp的值以跳过参数(此时已经在调用者堆栈中)
6、检查ds、es、fs、gs的值,如果其中哪一个寄存器指向的段的DPL小于CPL(此规则不适用于一致代码段),那么一个空描述符会被加载到该寄存器。
下图是返回的步骤:
综上所述,使用调用门的过程实际分为两个部分,一部分是从低特权级到高特权级,通过调用门call指令来实现;另一部分是从高特权级到低特权级,通过ret指令来实现。
除了上面一步符合要求之外,系统还将比较CPL和DPL_B。如果一致代码段的话,要求DPL_B<=CPL;如果非一致代码段的话,call指令和jmp指令有所不同。call指令要求DPL_B<=CPL;在用jmp指令时,只能是DPL_B=CPL.
综上所述,调用门特权规则如下图:
通过调用门call指令,可以实现从低特权级到高特权级的转移,无论目标代码段是一致的还是非一致的。
在有特权级转移时,堆栈也会随之变化,见下图
每个任务最多可能在4个特权级间转移,所以每个任务实际需要4个堆栈。可是我们只有一个ss和esp,在发生堆栈切换时,从哪里获得其余堆栈ss和esp呢?从TSS(Task-State Stack)。32位TSS如下图所示:
TSS包含多个字段,这里只需要关注偏移4到偏移27的3个ss和3个esp。当发生堆栈切换时,内存的ss和esp就是从这里取得的。比如我们当前所在的ring3,当转移至ring1时,堆栈将被自动切换到由ss1和esp1指定的位置。由于只是外层到内层(低特权级到高特权级),切换时新堆栈会从TSS中取得,所以TSS中没有位于最外层的ring3的堆栈信息。
了解了堆栈问题,就可以屡清特权级转移了。
调用门从外层到内层的转移过程:
1、根据目标代码段的DPL(新的CPL)从TSS中选择应该切换到哪个ss和esp
2、从TSS中读取新的ss和esp。在这过程中如果发现ss、esp或者TSS界限错误都会导致TSS异常(#TS)
3、对ss描述符进行检查,如果发生错误,同样产生#TS异常
4、暂时性保存当前ss和esp值
5、加载新的ss和esp
6、将刚刚保存起来的ss和esp的值压入新栈
7、从调用者堆栈中奖参数复制到被调用者堆栈(新堆栈)中,复制参数的数目由调用门中Param Count一项来决定。如果Param Count是零的话,将不会复制参数。
8、将当前的cs和eip压栈
9、加载调用门中指定的新的cs和eip,开始执行被调用过程。
第7步中,ParamCount只有5位,最多只能复制31个参数。如果参数多于31,可以让其中某个参数变成指向一个数据结构的指针。
ret指令返回的步骤:
1、检查保存的cs中的RPL以判断返回时是否要变换特权级。
2、加载被调用者堆栈上的cs和eip(此时会进行代码段描述符和选择子类型和特权级检验)
3、如果ret指令含有参数,则增加esp的值以跳过参数,然后esp将指向被保存过的调用者ss和esp。注意,ret的参数必须对应调用门中的Param Count的值。
4、加载ss和esp,切换到调用者堆栈,被调用者的ss和esp被丢弃,这里将会进行ss描述符、esp以及ss段描述符的检验。
5、如果ret指令含有参数,增加esp的值以跳过参数(此时已经在调用者堆栈中)
6、检查ds、es、fs、gs的值,如果其中哪一个寄存器指向的段的DPL小于CPL(此规则不适用于一致代码段),那么一个空描述符会被加载到该寄存器。
下图是返回的步骤:
综上所述,使用调用门的过程实际分为两个部分,一部分是从低特权级到高特权级,通过调用门call指令来实现;另一部分是从高特权级到低特权级,通过ret指令来实现。
相关文章推荐
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-理论)
- 3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-理论)
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-理论)
- 调用门实战(4)----特权级转移实践
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-无特权级转换)
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-实践篇)
- 通过调用门进行有特权级变换的转移,详细注解 对pmtest5.asm解释很详细.
- 第三章 pmtest4源码解析——利用门调用实现特权级转移
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-实践篇)
- 80386保护模式--GDT,LDT,TSS,调用门,特权级转移,附pmtest5代码详解
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-无特权级转换)
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-进入ring3-b)
- 3.保护模式7-特权级转移(通过调用门转移目标段-无特权级转换)
- 调用门实战(3)----理论补遗之TSS
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-进入ring3)
- 3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-进入ring3)
- 通过调用门进行有特权级变换的转移,详细注解 对pmtest5.asm解释很详细.
- 3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-进入ring3-b)
- 保护模式编程——保护的详尽意义:通过调用门转移特权级
- 保护的详尽意义:通过调用门转移特权级