汇编学习笔记(17)

特权级的基本概念

CPL 当前代码的特权级 = CS寄存器中的RPL

RPL 选择子中要求的特权级

DLP 目标段中要求的特权级

好比如说我是ROOT 用户拥有root权限, 我是用读权限打开一个文件, 这个文件的权限是 777 

CPL = ROOT 权限

RPL = 读权限

DLP = 777 

 数据段的装载 

ss 寄存器

    1. 可读写数据段
    2. CPL=DL=RPL

 

其他数据段寄存器

    1. 可读可写数据段,可读代码段
    2. CPL<=DPL, RPL<=DPL

 

运行权的变更(CS的装载 )

 指向代码段

JMP

CALL

要求

非一致代码,CPL = DPL, RPL<=DPL

一致代码,CPL >= DLP

结果

CS 的INDEX 和TI 被改变 而CPL不变

RET

要求

RPL = CPL

RET返回使用的是之前CS的选择子,因为在CALL的时候CPL是不变的,所以无意外的话RPL=CPL总是成立的之后就相当于CALL 和 JMP 了

提炼:

    1. 特权级永远不会变
    2. 对于转入非一致代码 要求 CPL = DPL,则强制规定了 非一致代码只能同级转入
    3. 对于转入一致代码要求CPL >= DLP, 则一致代码只能同级或者从外层向内转,但是无论哪种情况特权级不变
    4. RET 用的是压在堆栈中的之前的CS,所以 RPL=前 CPL, 因为CPL保持不变所以 前CPL=CPL总成立,所以RET的首要条件总是满足
    5. 由于 非一致代码要求 CPL = DPL 和 一致代码要求 CPL >= DPL 的要求看,而CPL不变,所以合法的调用链中 CPL >= DLP 是永远成立的
    6. 由4可知RPL就是CPL的压栈,而CPL不变,所以可知RPL = CPL, 所以得出结论,调用栈中  RPL=CPL>=DLP
    7. 一致代码不要求 RPL,所以从一致代码返回一致代码是可能出现的RPL > DLP的情况被忽略,而因为非一致代码都是CPL=DPL的,所以无论从何处返回非一致代码 情况都是 CPL=DPL=RPL(满足6中RPL=CPL>=DLP的情况),也能正常返回

 

小结

1. 使用CALL 和 JMP的时候根据转移目标代码的不同需要满足如下情况

目标是非一致代码:CPL = DPL, RPL<=DPL

目标是一致代码: CPL >= DLP

2. CPL 永远不变

3. 只要CALL满足执行条件 对应的RET永远也满足条件

 

 

指向调用门

首先指向门的调用中只有选择子有效,偏移地址是会被忽略的

其次调用门有自己DPL,所以想要使用调用门需要满足如下场景

CPL <  门DPL, RPL < 门 DPL

满足条件之后会从调用门中取出选择子和偏移地址,来替换掉转移指令中的选择子和偏移地址,在替换之前会将新选择子的RLP设为0,也就是说门中的选择子的RPL是没意义的始终会被替换成0. 

之后和 直接指向段的转跳大致相当,只要当使用CALL指令转移到非一致代码的情况有特殊

当使用CALL指令指向的调用门指向了非一致代码段的时候

如果出现 CPL > DPL的情况 在直接指向的情况下是会出错的,但是在指向门的情况下 会出现 设置CPL = DPL,也就是说出现提权的情况。

对应的RET指令在发现RPL>CPL的时候,也会设置CPL = RPL 也是就说降权。

注意:权限切换的时候还涉及到堆栈的切换,这个将在任务门相关内容的时候解释。

 

小结

      1. 指向门是只有选择子有效,偏移地址无意义

      2. 调用的时候会有 CPL <  门DPL, RPL < 门 DLP 的验证

      3. 实际调用的地址由门给出,同时实际调用的RPL总是0

      4. 其他调用规则同直接指向一致,唯一的区别是当CALL实际指向的地址是非一致代码的时候如果出现 CPL > DPL 的情况不会调用失败,而是设置CPL = DPL,对应的RET会发现RPL>CPL的时候会设置CPL=RPL,这里的RPL实际就是CALL指令压栈的CS寄存器的CPL,也就是或恢复特权级。

指向TSS数据

要求权限,CPL <=DPL RPL<= DPL

调用指令中的偏移地址被忽略,CPU直接用TSS中的数据直接切换任务(线程)了。

指向任务门

和直接指向TSS的数据没啥区别,就是多了些权限检测

首先检测 CPL < 门DPL, RPL <= 门DPL

然后检测 CPL < TSS的DPL, 门RPL <= TSS的DPL

然后就使用TSS的数据切换任务,指令和门中的偏移都没意义。

注意这里用JMP和用CALL 是有一点区别的

CALL 会引起任务的嵌套,所以使用CALL进行任务门的调用的话是可以用RET返回原来的任务的

     

 特权级切换时堆栈的切换

      在特权级发生切换的时候会有堆栈的切换,每个特权级都有自己的堆栈,这些地址是被保存在TSS中的,而且 0 1 2 这三个特权级的堆栈,在每次进去时候都会被重置,也就是说不会保留上次进入时的痕迹,而为了在特权级变更的时候传递参数,都会发生内存的拷贝,至于拷贝的字节数,任务门是有任务门的双字节字段决定,中断门和陷阱门有中断或者异常类型自动决定。

原文地址:https://www.cnblogs.com/alwaysking/p/12345946.html