最近笔者回顾CPU硬件的段访问控制机制,重新看到了代码段一致性问题。虽然目前操作系统没有应用分段机制,但了解其运行原理仍然具有吸引力XD。本片文章,我们就来理清CPU段访问控制中,代码段一致性的概念。

Privilege Level 特权级

首先,应当分清三个特权级的基本概念:

  • DPL (Descriptor Privilege Level 段描述符特权级): 定义于**段描述符 (Segment Descriptor)**中,对于不同的段,DPL的意义不尽相同

    • Data Segments 数据段:访问该段的最低特权等级。如果程序特权级过低,则不可访问该段
    • Stack Segment 栈段:访问该段的特权等级(需要相同,否则触发general-protection fault #GP
    • Non-conforming Code Segments 非一致性代码段:Direct Call(直接跳转,不经过 call gate)时,caller需要的特权等级(必须相同
    • Call gate & TSS:访问该Call gate / TSS 的最低特权等级,低权限程序无权使用高权限服务。
    • invoking Code Segments via Call Gates 通过调用门调用的代码段:访问该段的最高等级,这里与一般设置不同。事实上,通过调用门调用代码,通常是低特权级程序请求高特权服务时使用,这个设计也符合以上应用需求。详见下一节。
  • RPL (Requested Privilege Level 请求特权级):定义于段选择子中(最后两位),表示当前发起请求的特权级(以何种身份发起请求)。可以用于防止低权限程序借用高权限代码破坏高权限段

  • CPL (Current Privilege Level 当前特权级): 定义于当前程序的CS中,即CPL = CS.RPL。表示当前运行程序的特权级。

特权级检查

特权级检查,在将Segment Selector放入Segment Register时进行。按照上述规则执行检查

如果检查不通过,通常会产生异常:General-protection fault (#GP)

关于跳转中各种情况的分类解析,详见下节:控制权转移

控制权转移

有多种途径进行控制权的转移:

  • 应用程序执行的指令: JMP CALL RET INT n IRET
  • 来自硬件的事件:中断 interrupt异常 exception

在跨段的跳转中,会执行特权级检查,跳转主要有以下几种情形:

direct jump

当通过CALL 或者 JMP 直接跳转到另一个代码段时,会检查CPL、目标段描述符的DPL、目标段选择子(Segment Selector)的RPL。此时按照Target Segment Descriptor的C标志位(Conforming 一致性),可分为两种情况:

  • 一致性代码段(Conforming Code Segment):CPL 必须大于等于DPL(低权限代码借用高权限代码段)。即使跳转到DPL较高(数字小)的一致性代码段时CPL也不会改变因此不会进行堆栈切换(Stack-Switch)

    可以将一些不需要系统保护的部分API(数学函数、Exception Handlers等)设置在Conforming Segment中,由于CPL不改变,避免其影响高特权级数据

  • 非一致性代码段(non-Conforming Code Segment):CPL一定与Target DPL相同,且RPL小于等于CPL (特权级更高,请求方必须以高权限访问该段)(如果RPL比CPL更低(大于),则表示请求来自低特权级程序,访问失败)
    CPL=DPLRPL≤CPLCPL=DPL\\ RPL\le CPL CPL=DPLRPL≤CPL
    一般情况下,大部分其他Code Segment都应当设定为非一致性的

Call Gate

**Gate(门)**是一种系统段,它的Segment Descriptor 称为 gate descriptor。通常有四种门:Call Gates 调用门Trap Gates 陷门Interrupt Gates 中断门Task Gates 任务门。这里只讨论Call Gates。

typedef struct _CALL_GATE
{USHORT OffsetLow;USHORT Selector;UCHAR NumberOfArguments:5;UCHAR Reserved:3;UCHAR Type:5; // 01100 in i386, 00100 in i286UCHAR Dpl:2;UCHAR Present:1;USHORT OffsetHigh;
}CALL_GATE,*PCALL_GATE;

JMPCALL指令的目标段寄存器存放的选择子是Call Gate时,视为使用调用门(忽略偏移,在Gate Descriptor中已经指定)。

经由Call gate调用API时,CPL和RPL都要小于等于(特权级高于)Call gate的DPL

Call 使用调用门时,CPL和RPL都要大于等于Call gate对应Segment的DPL(非Call Gate的DPL)。如果调用者权限更高,则不能通过调用门进行调用;JMP使用时,若target segment是non-conforming segment,则target DPL必须与CPL相同。

按照目标代码段区分:

  • 一致性代码段:
    CPL≥targetDPLCPL \ge target\ DPL CPL≥target DPL
    CPL不改变,没有特权级转换。

  • 非一致代码段:

    • JMP跳转
      CPL=targetDPLRPL≤CPLCPL = target\ DPL \\ RPL \le CPL CPL=target DPLRPL≤CPL
      事实上,由于RPL被清零,条件二一定被满足。

      跳转后,CPL不变,没有特权级变化

    • CALL跳转
      CPL≥targetDPLRPL≤CPLCPL \ge target DPL \\ RPL \le CPL CPL≥targetDPLRPL≤CPL
      事实上,由于RPL被清零,条件二一定被满足。

      由低等级程序通过调用门请求访问高等级代码。

      跳转后,CPL=Target DPL产生特权级变化。(这是目前唯一产生变化的跳转方式)。

由程序中返回

使用RET指令进行跨段返回时,会检查返回目标的Segment Descriptor中的DPL是否大于等于当前CPL(权限较低),否则说明堆栈中数据错误。

CPU使用栈存储的返回CS中的RPL进行权限判断,检查是否需要改变权限。如果需要改变权限,则同时进行堆栈切换。所以,处理器会先将CS:IP载入,再载入SS:SP,同时,CPU还会恢复其他段寄存器的权限,并将指向更高权限的段的选择子置为空。

Real World

从设计原理上,RPL只是提供了一个CPU和操作系统之间的协议:CPU负责检查特权级、操作系统负责RPL的正确性。内核知道用户态请求操作的段选择子,也就能检查/修改对应的RPL,保证其与需要的权限相同。

通常,我们不会使用分段的保护机制,硬件架构建议将所有段的RPL设为0,这样可以通过所有RPL判断,不会进行这部分检查。

CPU段访问控制:特权级(RPL CPL DPL)和代码段一致性相关推荐

  1. 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-无特权级转换)...

    在上次的代码基础上,添加一个代码段作为通过调用门转移的目标段.了解一下调用的工作方法,代码分析如下: <<红色标识部分为新增代码>> ; =================== ...

  2. 特权级——保护模式的特权级检查 DPL,RPL,CPL, 一致代码段,非一致代码段

    特权级是保护模式下一个重要的概念,CPL,RPL和DPL是其中的核心概念,查阅资料无数,总结如下. 一.CPL.RPL.DPL简单解释     CPL是当前进程的权限级别(Current Privil ...

  3. CPL DPL RPL的区别 一致性代码段和非一致性代码段

    概述:在谈论保护模式编程的时候,一直会有这样的困惑:为什么除了CPL和DPL还有RPL?什么时候高特权级不能访问低特权级?什么时候低特权级不能访问高特权级?一致性代码和非一致性代码有什么区别?等等这些 ...

  4. X86(IA32)段权限标志位CPL DPL RPL详解

    1.DPL,RPL,CPL 之间的联系和区别是什么?RPL和CPL是必须相同吗?如果相同,为什么要釆用两个而不改用一个呢? 答:特权级是保护模式下一个重要的概念,CPL,RPL和DPL是其中的核心概念 ...

  5. 代码段间转移控制时的特权级检查(JMP/CALL)——《x86汇编语言:从实模式到保护模式》读书笔记28

    代码段间转移控制时的特权级检查(JMP或者CALL指令) 在保护模式下,JMP或CALL指令可以用以下四种方法之一来引用另外一个代码段: 1. 目标操作数含有目标代码段的段选择子和偏移 2. 目标操作 ...

  6. DPL,RPL,CPL 之间的联系和区别

    之所以出现这个定义是因为系统要安全:内核要和用户程序分开..内核一定要安全.不能被用户程序干涉. 但是有时候用户程序也需要读取内核的某些数据,怎么办呢? 操作系统就引入了访问特权等级(0-3)的机制. ...

  7. DPL RPL CPL区别与联系

    先说说他们的含义和存储的位置! PL:Privilege Level.特权级 CPL(Current):当前任务的特权级!内核态的时候,CPL = 0,用户态的时候,CPL = 3:linux中只用了 ...

  8. 特权级概述(哥子就想知道CPU是如何验证特权级的)GATE+TSS

    [0]README text description from orange's implemention of a os . [1]特权级概述 当当前代码段试图访问一个段或者门时,目标段的DPL将会 ...

  9. 【OS学习笔记】二十四 保护模式七:调用门与依从的代码段----特权级保护

    学习交流加 个人qq: 1126137994 个人微信: liu1126137994 学习交流资源分享qq群: 962535112 上一篇文章学习了保护模式下的任务与任务隔离,以及简单介绍了保护模式下 ...

最新文章

  1. 你没听说过的Go语言惊人优点
  2. 细菌基因组基本概念(一)
  3. MIPI CSI-2规范一——概述及层级
  4. 中专计算机系专业总结范文,计算机*的中专生自我鉴定范文
  5. Nodejs+socket.io搭建WebRTC信令服务器
  6. 原生javaScript中使用Ajax实现异步通信
  7. for循环中的setTimeout()
  8. IDEA 代码格式化设置
  9. cmd命令跳舞代码_Golang语言元编程之代码生成
  10. MetaPAD: 从大量文本语料库中发现元模式
  11. 用python实现聚类分析
  12. Win11玩游戏延迟高的解决办法
  13. 第二讲:双活灾备方案建设方法论
  14. IDEA中如何给代码添加Copyright
  15. docker-compose 部署prometheus+grafana+alertmanager+chronograf+prometheus-webhook-dingtalk+loki
  16. could not find included file 'pods/target support files/pods-runner/pods-runner.debug.xcconfig 什么问题
  17. C++如何定义一个长度超过一百万的整型数组
  18. 【UE4笔记】蓝图升降电梯
  19. 6天带你玩转mysql课程第一天
  20. 溢信IP guard文档加密系统控制台看着正常客户端无加密图标问题解决

热门文章

  1. 海洋地球物理十年个人总结
  2. 腾讯千万美元购康盛打响站长争夺战
  3. linux查看网络摄像头,用网络查看usb摄像头的图像
  4. 阿里云财务软件好会计-好会计财务管理系统介绍...
  5. [T系统]手帐04:无痕记录系统相关导出的日志
  6. pycharm的英文版使用
  7. L2-009 抢红包 (25 分)
  8. ABT 节点 1.0 发行候选版 1 发布 | ArcBlock 新闻
  9. [技巧] 网页视频倍速播放(以百度云盘为例)
  10. 江南天安环境的编译和使用(tassl)