x86中DPL和RPL之间的区别

dlb*_*lbp 11 x86 privilege memory-segmentation

阅读intel x86手册和其他资源,我不明白DPL(描述符权限级别)和RPL(请求权限级别)之间的区别.为什么两者都有必要?非常感谢

use*_*557 21

好问题.

CPL与DPL vs. RPL

为了简化这一点,我们首先考虑CPL和DPL:

  • CPL是您当前的权限级别.
  • DPL是段的权限级别.它定义了访问该段所需的最低1个权限级别.
  • 特权级别从0到3; 较低的数字更有特权
  • 因此:要访问段,CPL必须小于或等于段的DPL

RPL是与段选择器关联的权限级别.段选择器只是引用段的16位值.每个内存访问(隐式2或其他)使用段选择器作为访问的一部分.

访问段时,实际上必须执行两次检查.只有满足以下两个条件时才允许访问该段:

  • CPL <= DPL
  • RPL <= DPL

因此,即使CPL有足够的权限访问段,如果引用该段的段选择器没有足够的特权,则仍将拒绝访问.

RPL背后的动机

这是为了什么目的? 好吧,推理现在有点过时,但英特尔文档提供了类似这样的场景:

  • 假设操作系统提供一个系统调用,该调用接受来自调用者的逻辑地址(段选择器+偏移量)并写入该地址
  • 正常应用程序以CPL为3运行; 系统调用以CPL为0运行
  • 假设某段(我们称之为X)的DPL为0

应用程序通常无法访问段X中的内存(因为CPL> DPL).但是,根据系统调用的实现方式,应用程序可能能够使用段X中的地址参数调用系统调用.然后,因为系统调用具有特权,所以它将能够代表段X写入申请.这可能会将权限提升漏洞引入操作系统.

为了缓解这种情况,官方建议当特权例程接受由非特权代码提供的段选择器时,它应首先设置段选择器的RPL以匹配非特权代码3的RPL .这样,操作系统将无法对非特权调用者无法进行的该段进行任何访问.这有助于强制操作系统和应用程序之间的边界.

然后现在

在x86系列处理器中存在寻呼之前,286引入了段保护.那时,分段是限制从用户模式上下文访问内核内存的唯一方法.在跨不同权限级别传递指针时,RPL提供了一种方便的方法来强制执行此限制.

现代操作系统使用分页来限制对内存的访问,这消除了对分段的需要.因为我们不需要分割,我们可以使用一个平面内存模型,这意味着段寄存器CS,DS,SS,和ES所有具有零的基部和通过整个地址空间延伸.实际上,在64位"长模式"中,无论这四个段寄存器的内容如何,​​都会执行平坦存储器模型.有时仍然使用段(例如,Windows使用FSGS指向线程信息块,0x23和0x33 在32位和64位代码之间切换,Linux类似),但是你只是不去传递段了.所以RPL在很久以前就是一个未使用过的剩余物.

RPL:有必要吗?

你问为什么同时拥有DPL和RPL是必要的.即使是在286的情况下,这本来就不是一个需要有RPL.考虑到上述情况,特权过程总是可以通过LAR指令检索所提供段的DPL,将其与调用者的特权进行比较,并且如果调用者的特权不足以访问该段,则抢先挽救.但是,在我看来,设置RPL是一种更优雅,更简单的方法来管理跨不同权限级别的段访问.

要了解有关权限级别的更多信息,请查看英特尔软件开发人员手册的第3卷,特别是标题为"权限级别"和"检查来电者访问权限"的部分.

1从技术上讲,DPL可以有不同的含义,具体取决于访问的段或门的类型.为简单起见,我描述的所有内容都特别适用于数据段.有关详细信息,请查看Intel文档
2例如,指令指针在获取指令时隐式使用存储在CS中的段选择器; 大多数类型的数据访问隐式使用存储在DS等中的段选择器
.3请参阅ARPL指令(仅限16位/ 32位保护模式)

  • 请注意,`arpl`在64位模式下无法编码.操作码`63`重新用于`movsxd r64,r/m32`.这与通常在64位模式中的段功能相结合被大大简化. (2认同)