DEXCR (Dynamic Execution Control Register)

概述

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

执行控制在硬件中表现为 DEXCR 中的最多 32 位(称为“方面”(aspects))。每个方面控制特定的行为,并且可以通过设置或清除来启用/禁用该方面。出于不同的目的,DEXCR 有几种变体:

DEXCR

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

HDEXCR

一个虚拟机监控程序(hypervisor)特权的 SPR,可以控制 hypervisor 的方面并强制内核和用户空间实施某些方面。

UDEXCR

一个可选的超级监控程序(ultravisor)特权的 SPR,可以控制 ultravisor 的方面。

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

  • 设置/清除(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 返回的状态表示进程希望应用的值。它不包含任何替代覆盖,例如 hypervisor 是否强制设置了该方面。要查看真实的 DEXCR 状态,软件应直接读取相应的 SPR。

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

  • *_ONEXEC 控件不会改变当前进程的 DEXCR。

使用带有 PR_PPC_DEXCR_CTRL_SETPR_PPC_DEXCR_CTRL_CLEAR 之一的 PR_PPC_SET_DEXCR 来编辑给定的方面。

获取和设置 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 位且只读,旨在辅助核心转储(core dumps)。DEXCR 在将来可能会变为可写。这两个寄存器的高 32 位(对应于非用户空间位)被屏蔽掉。

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