保护模式中的特权级

简介: 保护模式中的特权级

引言

  • 在上一章节中提过,调用门可以实现不同特权级的代码之间跳转执行
  • 不能直接跳转吗?我们先来做个小实验
  • 将 Task A 中代码段选择符中的特权级由 0 改 为 3 ,然后编译运行一下看看效果
; TASK_A_CODE32_SELECTOR equ (0x0000 << 3) + SA_RPL0 + SA_TIL
TASK_A_CODE32_SELECTOR equ (0x0000 << 3) + SA_RPL3 + SA_TIL
  • 实验结果:原本应该打印的字符串 “Task A”,并没有打印出来,程序崩溃了
  • 结论:不同特权级的代码之间并不能随意跳转
  • 想要搞清楚原因,就需要先对特权级进行一定的了解

特权级

  • 我们知道,保护模式下, CPU 提供各种各样的保护机制,比如段界限,指定范围;段属性,指定读写等权限等等。这些都比较好理解,在这里就不总结了
  • 保护模式下, CPU 还提供了有关特权级的保护机制
  • 处理器的段保护机制可以识别 4 个特权级(或特权层),0 级到 3 级。数值越大,特权越小

  • 处理器利用特权级来防止运行在较低特权级的程序或任务访问具有较高特权级的一个段
  • 我们熟知的 linux 系统只使用了特权级 0(内核)和特权级 3(应用)

与特权级相关的三个概念

  • 当前特权级 CPL(Current Privilege Level)
  • CPL 是当前正在执行程序或任务的特权级。它存放在 CS 和 SS 段寄存器的位 0 和位 1 中
  • 当程序把控制转移到另一个具有不同特权级的代码段中时,处理器就会改变 CPL
  • 处理器进入保护模式后,CPL = 0(最高特权级)
  • 描述符特权级 DPL(Descriptor Privilege Level)
  • DPL 是一个段或门的特权级。它存放在段或门描述符的 DPL 字段中
  • 在当前执行代码段试图访问一个段或门时,段或门的 DPL 会用来与 CPL 以及段或门选择符中的 RPL 作比较
  • 根据被访问的段或门的类型不同,DPL 也有不同的含义,这里先不深究,后面再做介绍
  • 请求特权级 RPL(Request Privilege Level)
  • RPL 是一种赋予段选择符的超越特权级,它存放在选择符的位 0 和位 1 中
  • 处理器会同时检查 RPL 和 CPL,以确定是否允许访问一个段

CPL、DPL 和 RPL 的关系

  • 当处理器从 A 代码段成功跳转到 B 代码段执行
  • 跳转前: CPL = DPL(A)
  • 跳转后: CPL = DPL(B)
  • 当处理器运行过程中需要访问数据段时
  • CPL <= DPL(Data)
  • 在请求某特权级为 DPL 级别的资源时,参与特权检查的不只是 CPL,还要加上 RPL. CPL 和 RPL 的特权必须同时大于等于受访者的特权 DPL,即:数值上 CPL <= DPL 并且 RPL <= DPL

再做小实验

  • 先对段描述符中 DPL 属性进行宏定义
; 段描述符中 DPL 属性定义(段描述符高 32 位的 bit13-bit14 )
DA_DPL0     equ    0x00  ; DPL = 0
DA_DPL1     equ    0x20  ; DPL = 1
DA_DPL2     equ    0x40  ; DPL = 2
DA_DPL3     equ    0x60  ; DPL = 3
  • 给全局描述符表中 32 位代码段增加属性 DPL = 3
; CODE32_DESC : Descriptor 0, CODE32_SEG_LEN - 1, DA_C + DA_32
CODE32_DESC : Descriptor 0, CODE32_SEG_LEN - 1, DA_C + DA_32 + DA_DPL3
  • 运行一下,不出意外,果然不能运行,CODE32_START 代码段并没有运行,这说明高特权级代码段不能够跳转到低特权级的代码段
  • 将本章节 RPL、DPL 有关的改动都恢复一下,恢复后代码(可以运行):loader.asm
  • 同样的实验我们也在数据段上做一次,改动如下:
; DATA_DESC : Descriptor 0, DATA_SEG_LEN - 1, DA_DR + DA_32
DATA_DESC : Descriptor 0, DATA_SEG_LEN - 1, DA_DR + DA_32 + DA_DPL3
  • 运行一下,居然未发生任何错误
  • 再改一下:
; DATA_SELECTOR equ (0x0003 << 3) + SA_RPL0 + SA_TIG
DATA_SELECTOR equ (0x0003 << 3) + SA_RPL3 + SA_TIG
  • 还是未发生任何错误
  • 再改一下:
; DATA_DESC : Descriptor 0, DATA_SEG_LEN - 1, DA_DR + DA_32
DATA_DESC : Descriptor 0, DATA_SEG_LEN - 1, DA_DR + DA_32 + DA_DPL2
; DATA_SELECTOR equ (0x0003 << 3) + SA_RPL0 + SA_TIG
DATA_SELECTOR equ (0x0003 << 3) + SA_RPL3 + SA_TIG
  • 这回出错了,这说明请求特权级 RPL 不能够请求比它更高级的特权级数据段,但是可以请求到比它低级的特权级的数据段。
  • 再对栈段做下实验
  • 程序再次恢复到 loader.asm
  • 改动如下:
; STACK32_DESC : Descriptor 0, TOP_OF_STACK32, DA_DRW + DA_32
STACK32_DESC : Descriptor 0, TOP_OF_STACK32, DA_DRW + DA_32 + DA_DPL3
; STACK32_SELECTOR equ (0x0004 << 3) + SA_RPL0 + SA_TIG
STACK32_SELECTOR equ (0x0004 << 3) + SA_RPL3 + SA_TIG
  • 凭感觉栈段应该跟数据段一样,结果程序崩了。这说明栈段的特权级检测规则跟数据段不一样,好吧,代码段、数据段、栈段各自有各自的检测规则
  • 是不是有点乱糟糟的,暂时先不要一下子理清楚所有的规则,以后再在各种场景下具体体会,目前先有个感性的认识就好


目录
相关文章
|
负载均衡 数据中心
云:NAT介绍
NAT详细介绍
534 0
|
Windows
Windows系统下快速删除node_modules
Windows系统下快速删除node_modules
993 0
|
数据采集 监控 安全
数字孪生与金融:风险管理的新工具
数字孪生技术通过构建物理实体或系统的虚拟模型,实现对金融市场的实时监控、客户行为分析、市场风险预测及业务流程优化,为金融机构提供了全新的风险管理工具,提升了风险管理的精准度和效率。
|
边缘计算 开发框架 人工智能
C#/.NET/.NET Core优秀项目和框架2024年8月简报
C#/.NET/.NET Core优秀项目和框架2024年8月简报
230 0
|
存储 机器学习/深度学习 测试技术
[大语言模型-论文精读] 以《黑神话:悟空》为研究案例探讨VLMs能否玩动作角色扮演游戏?
[大语言模型-论文精读] 以《黑神话:悟空》为研究案例探讨VLMs能否玩动作角色扮演游戏?
|
边缘计算 人工智能 安全
5G 核心网络 (5GC) 与 4G 核心网:架构变革,赋能未来
5G 核心网络 (5GC) 与 4G 核心网:架构变革,赋能未来
874 6
|
机器学习/深度学习 人工智能 安全
北大领衔,多智能体强化学习研究登上Nature子刊
【10月更文挑战第1天】近日,北京大学领导的研究团队在《Nature》子刊上发表了一篇关于多智能体强化学习的论文,提出了一种高效且可扩展的框架,解决了大规模网络控制系统中的决策问题。该框架通过局部通信避免了集中式和独立学习的缺点,在交通、电力等领域的实验中展现了卓越性能。然而,其在更复杂系统中的效果及计算复杂度仍需进一步验证。论文链接:https://www.nature.com/articles/s42256-024-00879-7。
278 3
|
Ubuntu Linux 芯片
史上最全的LED点灯程序—使用STM32、FPGA、Linux点亮你的LED灯
不知道小伙伴们点亮过多少板子的LED灯,有很多小伙伴留言说讲一下stm32、fpga、liunx他们之间有什么不同,不同点很多,口说无凭,今天就来点亮一下stm32、fpga和liunx板子的led灯,大家大致看一下点灯流程和点灯环境以及点灯流程,就能大概的了解一下三者的区别,可以有选择的去学习!
608 0
史上最全的LED点灯程序—使用STM32、FPGA、Linux点亮你的LED灯
|
编译器 C++
Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案
Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案
842 0
Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案
|
C语言
深入理解C语言中的printf函数及数据输出
深入理解C语言中的printf函数及数据输出
1022 0