阅读intel x86手册和其他来源,我不明白DPL(描述符权限级别)和RPL(请求权限级别)之间的区别。 为什么两者都有必要? 非常感谢你
答案 0 :(得分:17)
好问题。
为了简化这一点,我们首先考虑CPL和DPL:
RPL是与段选择器关联的权限级别。段选择器只是引用段的16位值。每个内存访问(隐式 2 或其他)使用段选择器作为访问的一部分。
访问段时,实际上必须执行两项检查。只有在以下两者为真时才允许访问该段:
因此,即使CPL有足够的权限访问某个段,如果引用该段的段选择器没有足够的权限,访问仍将被拒绝。
这是什么目的?嗯,推理现在有点陈旧,但英特尔文档提供了类似这样的场景:
应用程序通常无法访问段X中的内存(因为CPL> DPL)。但是,根据系统调用的实现方式,应用程序可能能够使用段X中的地址参数调用系统调用。然后,因为系统调用具有特权,所以它将能够代表段X写入申请。这可能会在操作系统中引入privilege escalation vulnerability。
为了缓解这种情况,官方建议当特权例程接受由非特权代码提供的段选择器时,它应首先设置段选择器的RPL以匹配非特权代码 3 的RPL。 。这样,操作系统将无法对非特权调用者无法进行的该段进行任何访问。这有助于强制操作系统和应用程序之间的界限。
在x86系列处理器中存在分页之前,286引入了段保护。那时,分段是限制从用户模式上下文访问内核内存的唯一方法。在跨不同权限级别传递指针时,RPL提供了一种方便的方法来强制执行此限制。
现代操作系统使用分页来限制对内存的访问,从而无需进行分段。由于我们不需要细分,因此我们可以使用flat memory model,这意味着细分寄存器CS
,DS
,SS
和ES
都具有零基数并延伸到整个地址空间。事实上,在64位"长模式"中,无论这四个段寄存器的内容如何,都会强制执行强制平面存储器模型。有时仍会使用细分(例如,Windows使用FS
和GS
指向Thread Information Block,0x23和0x33指向switch between 32- and 64-bit code,Linux类似,但是你只是不要再绕过段了。所以RPL在很久以前就是一个未使用过的剩余物。
你问为什么同时拥有DPL和RPL是必要的。即使在286的背景下,RPL实际上并不是必需。考虑到上述情况,特权过程总是可以通过LAR指令检索所提供段的DPL,将其与呼叫者的特权进行比较,并且如果呼叫者的特权不足以访问该段,则抢先挽救。但是,在我看来,设置RPL是一种更优雅,更简单的方法来管理不同权限级别的段访问。
要了解有关权限级别的更多信息,请查看Intel's software developer manuals的第3卷,特别是标题为"权限级别&#34的部分;和"检查来电者访问权限"。
1 从技术上讲,DPL可以有不同的含义,具体取决于访问的段或门的类型。为简单起见,我描述的所有内容都特别适用于数据段。有关更多信息,请查看英特尔文档 2 例如,指令指针在获取指令时隐含地使用存储在CS中的段选择器;大多数类型的数据访问隐含地使用存储在DS等中的段选择器 3 请参阅ARPL指令(仅限16位/ 32位保护模式)