DEXCR (动态执行控制寄存器)

概述

DEXCR 是 PowerPC ISA 3.1B (Power10) 中引入的特权专用寄存器 (SPR),允许对每个 CPU 控制多个动态执行行为。这些行为包括推测(例如,间接分支目标预测)和启用面向返回的编程 (ROP) 保护指令。

执行控制在硬件中以 DEXCR 中最多 32 位(“方面”)的形式公开。每个方面控制某个行为,并且可以设置或清除以启用/禁用该方面。DEXCR 有几种变体,用于不同的目的

DEXCR

一个特权 SPR,可以控制用户空间和内核空间的各个方面

HDEXCR

一个虚拟机管理程序特权 SPR,可以控制虚拟机管理程序的各个方面,并强制执行内核和用户空间的各个方面。

UDEXCR

一个可选的超虚拟机管理程序特权 SPR,可以控制超虚拟机管理程序的各个方面。

用户空间可以使用一个专用 SPR 来检查当前的 DEXCR 状态,该 SPR 提供用户空间 DEXCR 方面的非特权只读视图。还有一个 SPR 提供虚拟机管理程序强制执行的方面的只读视图,该视图与用户空间 DEXCR 视图进行 OR 运算,可以得出进程的有效 DEXCR 状态。

配置

prctl

进程可以使用 PR_PPC_GET_DEXCRPR_PPC_SET_DEXCR 这对 prctl(2) 命令来控制其自己的用户空间 DEXCR 值。这些调用的形式如下

prctl(PR_PPC_GET_DEXCR, unsigned long which, 0, 0, 0);
prctl(PR_PPC_SET_DEXCR, unsigned long which, unsigned long ctrl, 0, 0);

可能的“which”和“ctrl”值如下。请注意,“which”值与 DEXCR 方面的索引之间没有关系。

prctl() which

方面名称

方面索引

PR_PPC_DEXCR_SBHE

推测分支提示启用 (SBHE)

0

PR_PPC_DEXCR_IBRTPD

间接分支递归目标预测禁用 (IBRTPD)

3

PR_PPC_DEXCR_SRAPD

子程序返回地址预测禁用 (SRAPD)

4

PR_PPC_DEXCR_NPHIE

非特权哈希指令启用 (NPHIE)

5

prctl() ctrl

含义

PR_PPC_DEXCR_CTRL_EDITABLE

可以使用 PR_PPC_SET_DEXCR 配置此方面(仅获取)

PR_PPC_DEXCR_CTRL_SET

设置此方面/设置此方面

PR_PPC_DEXCR_CTRL_CLEAR

清除此方面/清除此方面

PR_PPC_DEXCR_CTRL_SET_ONEXEC

exec 后将设置此方面/在 exec 后设置此方面

PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC

exec 后将清除此方面/在 exec 后清除此方面

请注意

  • which 是一个普通值,而不是位掩码。必须单独处理各个方面。

  • ctrl 是一个位掩码。PR_PPC_GET_DEXCR 返回当前配置和 onexec 配置。例如,PR_PPC_GET_DEXCR 可能会返回 PR_PPC_DEXCR_CTRL_EDITABLE | PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC。这表示该方面当前已设置,在您运行 exec 时将被清除,您可以使用 PR_PPC_SET_DEXCR prctl 更改此设置。

  • 设置/清除术语是指设置/清除 DEXCR 中的位。例如

    prctl(PR_PPC_SET_DEXCR, PR_PPC_DEXCR_IBRTPD, PR_PPC_DEXCR_CTRL_SET, 0, 0);
    

    将在 DEXCR 中设置 IBRTPD 方面位,从而导致禁用间接分支预测。

  • PR_PPC_GET_DEXCR 返回的状态表示进程希望应用的值。它不包括任何替代覆盖,例如,如果虚拟机管理程序强制设置该方面。要查看真正的 DEXCR 状态,软件应直接读取相应的 SPR。

  • fork(2) 上启动进程时,方面状态从父进程的状态复制。在 execve(2) 上,该状态将重置为固定值。PR_PPC_SET_DEXCR prctl() 可以控制这两个值。

  • *_ONEXEC 控制不会更改当前进程的 DEXCR。

使用 PR_PPC_SET_DEXCR 以及 PR_PPC_DEXCR_CTRL_SETPR_PPC_DEXCR_CTRL_CLEAR 之一来编辑给定的方面。

获取和设置 DEXCR 的常见错误代码如下

错误

含义

EINVAL

内核不支持 DEXCR。

ENODEV

内核无法识别该方面,或者硬件不支持该方面。

PR_PPC_SET_DEXCR 也可能会报告以下错误代码

错误

含义

EINVAL

ctrl 值包含无法识别的标志。

EINVAL

ctrl 值包含相互冲突的标志(例如,PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR

EPERM

无法使用 prctl() 修改此方面(使用 PR_PPC_GET_DEXCR 检查 PR_PPC_DEXCR_CTRL_EDITABLE 标志)。

EPERM

进程没有足够的权限执行该操作。例如,在 exec 上清除 NPHIE 是一项特权操作(进程仍然可以清除其自身的 NPHIE 方面而无需权限)。

此接口允许进程控制其自身的 DEXCR 方面,并且还可以为其进程树中的任何子进程设置初始 DEXCR 值(直到下一个子进程使用 *_ONEXEC 控制)。这允许对 DEXCR 的默认值进行细粒度控制,例如允许容器以不同的默认值运行。

coredump 和 ptrace

DEXCR 和 HDEXCR 的用户空间值(按此顺序)在 NT_PPC_DEXCR 下公开。这些值均为 64 位且只读,旨在帮助进行核心转储。DEXCR 将来可能会变为可写。这两个寄存器的前 32 位(对应于非用户空间位)被屏蔽掉。

如果启用了内核配置 CONFIG_CHECKPOINT_RESTORE,则可以使用 NT_PPC_HASHKEYR,并公开进程的 HASHKEYR 值以进行读取和写入。这是提高安全性和检查点/恢复支持之间的一种权衡:进程通常不需要知道其密钥,但是恢复进程需要设置其原始密钥。因此,该密钥会出现在核心转储中,攻击者可能会从核心转储中检索该密钥,并有效地绕过共享此密钥的任何线程(可能是来自同一父进程的所有尚未运行 exec() 的线程)上的 ROP 保护。