【问题标题】:Difference between DPL and RPL in x86x86 中 DPL 和 RPL 的区别
【发布时间】:2016-08-05 16:32:50
【问题描述】:

阅读英特尔 x86 手册和其他来源,我不明白 DPL(描述符特权级别)和 RPL(请求特权级别)之间的区别。 为什么有必要两者兼得? 非常感谢

【问题讨论】:

    标签: x86 memory-segmentation privilege


    【解决方案1】:

    好问题。

    CPL 与 DPL 与 RPL

    为了简单起见,让我们首先考虑 CPL 和 DPL:

    • CPL 是您当前的权限级别。
    • DPL 是段的特权级别。它定义了访问段所需的最低1权限级别。
    • 权限级别范围为 0-3;较低的数字更多特权
    • 所以:要访问分段,CPL 必须小于或等于分段的 DPL

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

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

    • CPL
    • RPL

    因此,即使 CPL 有足够的权限访问一个段,如果引用该段的段选择器没有足够的权限,访问仍然会被拒绝。

    RPL 背后的动机

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

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

    应用程序通常无法访问段 X 中的内存(因为 CPL > DPL)。但是根据系统调用的实现方式,应用程序可能能够使用段 X 内的地址参数调用系统调用。然后,由于系统调用是特权的,它将能够代表 X 段写入的应用程序。这可能会在操作系统中引入privilege escalation vulnerability

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

    过去和现在

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

    现代操作系统使用分页来限制对内存的访问,从而无需分段。由于我们不需要分段,我们可以使用flat memory model,这意味着段寄存器CSDSSSES 的基数都为零,并延伸到整个地址空间。事实上,在 64 位“长模式”中,强制执行平面内存模型,而不管这四个段寄存器的内容。有时仍会使用段(例如,Windows 使用FSGS 指向Thread Information Block 和0x23 和0x33 指向switch between 32- and 64-bit code,Linux 类似),但你只是不要到处传递段了。所以 RPL 主要是旧时代未使用的遗留物。

    RPL:它曾经有必要吗?

    您问为什么必须同时拥有 DPL 和 RPL。即使在 286 的上下文中,RPL 实际上也不是必需。考虑到上述情况,特权过程总是可以通过 LAR 指令检索提供的段的 DPL,将其与调用者的权限进行比较,如果调用者的权限不足以访问该段,则抢先退出。但是,在我看来,设置 RPL 是一种更优雅、更简单的方式来管理跨不同权限级别的段访问。

    要了解有关权限级别的更多信息,请查看Intel's software developer manuals 第 3 卷,尤其是标题为“权限级别”和“检查呼叫者访问权限”的部分。

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

    【讨论】:

    • 请注意,arpl 在 64 位模式下不可编码。操作码 63 重新用于 movsxd r64, r/m32。这与通常在 64 位模式下的分段功能一起被大大简化。
    • @Peter Cordes 确实,我更新了我的答案以提及这一点。而且,更一般地说,段保护的适用性在现代操作系统中是有限的。 +1
    • 不错的更新,但让 64 位模式像 32 位模式一样向后工作并不是主要目标。问题在于实现的相似性。就像他们可以用指令编码解决很多错误的决定一样(setcc r/m8 而不是r/m32 是我最讨厌的地方之一),他们尽可能地保持相似,这样他们就可以共享尽可能多的晶体管。解码器和执行单元。
    • @PeterCordes 啊,关于向后兼容性的评论是为了解释为什么它仍然是保护模式的一部分,而不是长模式。我将删除该子句以便更清楚
    • 那么如果段不再存在,x64 如何避免write to segment X?还是他们检查地址形式?
    猜你喜欢
    • 2013-01-05
    • 2019-08-25
    • 2015-01-20
    • 2017-03-11
    • 2020-03-03
    • 2015-06-01
    • 2014-05-07
    • 2015-06-26
    • 1970-01-01
    相关资源
    最近更新 更多