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

概述

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

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

DEXCR

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

HDEXCR

一个超级visor 特权 SPR,可以控制超级visor 的方面,并强制内核和用户空间的方面。

UDEXCR

一个可选的 ultravisor 特权 SPR,可以控制 ultravisor 的方面。

用户空间可以使用专用 SPR 来检查当前的 DEXCR 状态,该 SPR 提供用户空间 DEXCR 方面的非特权只读视图。 还有一个 SPR 提供超级visor 强制方面的只读视图,该视图与用户空间 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

执行后将设置此方面/执行后设置此方面

PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC

执行后将清除此方面/执行后清除此方面

请注意

  • 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 更改此设置。

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

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

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

  • PR_PPC_GET_DEXCR 返回的状态表示进程希望应用的值。 它不包括任何替代覆盖,例如,如果超级visor 强制设置该方面。 要查看真实的 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 值以进行读取和写入。 这是提高安全性和检查点/恢复支持之间的一种权衡:进程通常不需要知道其密钥,但恢复进程需要设置其原始密钥。 因此,密钥出现在核心转储中,攻击者可能能够从核心转储中检索到该密钥,并有效地绕过共享此密钥的任何线程上的 ROP 保护(可能来自同一父进程的所有尚未运行 exec() 的线程)。