요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0-or-later
==========================================
DEXCR (Dynamic Execution Control Register)
==========================================
Overview
========
The DEXCR is a privileged special purpose register (SPR) introduced in
PowerPC ISA 3.1B (Power10) that allows per-cpu control over several dynamic
execution behaviours. These behaviours include speculation (e.g., indirect
branch target prediction) and enabling return-oriented programming (ROP)
protection instructions.
The execution control is exposed in hardware as up to 32 bits ('aspects') in
the DEXCR. Each aspect controls a certain behaviour, and can be set or cleared
to enable/disable the aspect. There are several variants of the DEXCR for
different purposes:
DEXCR
A privileged SPR that can control aspects for userspace and kernel space
HDEXCR
A hypervisor-privileged SPR that can control aspects for the hypervisor and
enforce aspects for the kernel and userspace.
UDEXCR
An optional ultravisor-privileged SPR that can control aspects for the ultravisor.
Userspace can examine the current DEXCR state using a dedicated SPR that
provides a non-privileged read-only view of the userspace DEXCR aspects.
There is also an SPR that provides a read-only view of the hypervisor enforced
aspects, which ORed with the userspace DEXCR view gives the effective DEXCR
state for a process.
Configuration
=============
prctl
-----
A process can control its own userspace DEXCR value using the
``PR_PPC_GET_DEXCR`` and ``PR_PPC_SET_DEXCR`` pair of
:manpage:`prctl(2)` commands. These calls have the form::
prctl(PR_PPC_GET_DEXCR, unsigned long which, 0, 0, 0);
prctl(PR_PPC_SET_DEXCR, unsigned long which, unsigned long ctrl, 0, 0);
The possible 'which' and 'ctrl' values are as follows. Note there is no relation
between the 'which' value and the DEXCR aspect's index.
.. flat-table::
:header-rows: 1
:widths: 2 7 1
* - ``prctl()`` which
- Aspect name
- Aspect index
* - ``PR_PPC_DEXCR_SBHE``
- Speculative Branch Hint Enable (SBHE)
- 0
* - ``PR_PPC_DEXCR_IBRTPD``
- Indirect Branch Recurrent Target Prediction Disable (IBRTPD)
- 3
* - ``PR_PPC_DEXCR_SRAPD``
- Subroutine Return Address Prediction Disable (SRAPD)
- 4
* - ``PR_PPC_DEXCR_NPHIE``
- Non-Privileged Hash Instruction Enable (NPHIE)
- 5
.. flat-table::
:header-rows: 1
:widths: 2 8
* - ``prctl()`` ctrl
- Meaning
* - ``PR_PPC_DEXCR_CTRL_EDITABLE``
- This aspect can be configured with PR_PPC_SET_DEXCR (get only)
* - ``PR_PPC_DEXCR_CTRL_SET``
- This aspect is set / set this aspect
* - ``PR_PPC_DEXCR_CTRL_CLEAR``
- This aspect is clear / clear this aspect
* - ``PR_PPC_DEXCR_CTRL_SET_ONEXEC``
- This aspect will be set after exec / set this aspect after exec
* - ``PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC``
- This aspect will be clear after exec / clear this aspect after exec
Note that
* which is a plain value, not a bitmask. Aspects must be worked with individually.
* ctrl is a bitmask. ``PR_PPC_GET_DEXCR`` returns both the current and onexec
configuration. For example, ``PR_PPC_GET_DEXCR`` may return
``PR_PPC_DEXCR_CTRL_EDITABLE | PR_PPC_DEXCR_CTRL_SET |
PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC``. This would indicate the aspect is currently
set, it will be cleared when you run exec, and you can change this with the
``PR_PPC_SET_DEXCR`` prctl.
* The set/clear terminology refers to setting/clearing the bit in the DEXCR.
For example::
prctl(PR_PPC_SET_DEXCR, PR_PPC_DEXCR_IBRTPD, PR_PPC_DEXCR_CTRL_SET, 0, 0);
will set the IBRTPD aspect bit in the DEXCR, causing indirect branch prediction
to be disabled.
* The status returned by ``PR_PPC_GET_DEXCR`` represents what value the process
would like applied. It does not include any alternative overrides, such as if
the hypervisor is enforcing the aspect be set. To see the true DEXCR state
software should read the appropriate SPRs directly.
* The aspect state when starting a process is copied from the parent's state on
:manpage:`fork(2)`. The state is reset to a fixed value on
:manpage:`execve(2)`. The PR_PPC_SET_DEXCR prctl() can control both of these
values.
* The ``*_ONEXEC`` controls do not change the current process's DEXCR.
Use ``PR_PPC_SET_DEXCR`` with one of ``PR_PPC_DEXCR_CTRL_SET`` or
``PR_PPC_DEXCR_CTRL_CLEAR`` to edit a given aspect.
Common error codes for both getting and setting the DEXCR are as follows:
.. flat-table::
:header-rows: 1
:widths: 2 8
* - Error
- Meaning
* - ``EINVAL``
- The DEXCR is not supported by the kernel.
* - ``ENODEV``
- The aspect is not recognised by the kernel or not supported by the
hardware.
``PR_PPC_SET_DEXCR`` may also report the following error codes:
.. flat-table::
:header-rows: 1
:widths: 2 8
* - Error
- Meaning
* - ``EINVAL``
- The ctrl value contains unrecognised flags.
* - ``EINVAL``
- The ctrl value contains mutually conflicting flags (e.g.,
``PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR``)
* - ``EPERM``
- This aspect cannot be modified with prctl() (check for the
PR_PPC_DEXCR_CTRL_EDITABLE flag with PR_PPC_GET_DEXCR).
* - ``EPERM``
- The process does not have sufficient privilege to perform the operation.
For example, clearing NPHIE on exec is a privileged operation (a process
can still clear its own NPHIE aspect without privileges).
This interface allows a process to control its own DEXCR aspects, and also set
the initial DEXCR value for any children in its process tree (up to the next
child to use an ``*_ONEXEC`` control). This allows fine-grained control over the
default value of the DEXCR, for example allowing containers to run with different
default values.
coredump and ptrace
===================
The userspace values of the DEXCR and HDEXCR (in this order) are exposed under
``NT_PPC_DEXCR``. These are each 64 bits and readonly, and are intended to
assist with core dumps. The DEXCR may be made writable in future. The top 32
bits of both registers (corresponding to the non-userspace bits) are masked off.
If the kernel config ``CONFIG_CHECKPOINT_RESTORE`` is enabled, then
``NT_PPC_HASHKEYR`` is available and exposes the HASHKEYR value of the process
for reading and writing. This is a tradeoff between increased security and
checkpoint/restore support: a process should normally have no need to know its
secret key, but restoring a process requires setting its original key. The key
therefore appears in core dumps, and an attacker may be able to retrieve it from
a coredump and effectively bypass ROP protection on any threads that share this
key (potentially all threads from the same parent that have not run ``exec()``).
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
DEXCR register family와 effective state
1-35SPDX-License-Identifier는 GPL-2.0-or-later입니다. Dynamic Execution Control Register (`DEXCR`)는 PowerPC ISA 3.1B, 즉 POWER10에서 도입된 privileged special-purpose register (`SPR`)입니다. CPU별로 speculation, indirect branch target prediction, return-oriented programming (`ROP`) protection instruction 같은 dynamic execution behavior를 제어합니다.
Hardware는 DEXCR에 최대 32개의 bit, 즉 `aspect`를 노출합니다. 각 aspect는 특정 behavior를 제어하며 bit를 set/clear해 enable/disable합니다.
| Register | Privilege와 제어 범위 |
|---|---|
| `DEXCR` | Privileged SPR. Userspace와 kernel space의 aspect를 제어 |
| `HDEXCR` | Hypervisor-privileged SPR. Hypervisor aspect를 제어하고 kernel/userspace aspect를 강제 |
| `UDEXCR` | Optional ultravisor-privileged SPR. Ultravisor aspect를 제어 |
Userspace는 전용 read-only SPR로 자신의 DEXCR aspect를 non-privileged 방식으로 읽을 수 있습니다. Hypervisor가 강제한 aspect를 보여 주는 별도 read-only SPR도 있으며, 두 view를 OR하면 process의 effective DEXCR state가 됩니다.
Process 요청과 hypervisor 강제 bit를 OR해 실제 적용 상태를 얻습니다.
`prctl()` interface
36-50Process는 `prctl(2)`의 `PR_PPC_GET_DEXCR`와 `PR_PPC_SET_DEXCR` command pair로 자기 userspace 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`는 제어할 aspect를, `ctrl`은 조회하거나 적용할 상태를 지정합니다. `which` 값과 실제 DEXCR aspect index 사이에는 수치상 관계가 없습니다.
`which`와 `ctrl` 값
51-97| `prctl()` which | Aspect 이름 | Aspect index |
|---|---|---|
| `PR_PPC_DEXCR_SBHE` | Speculative Branch Hint Enable (`SBHE`) | 0 |
| `PR_PPC_DEXCR_IBRTPD` | Indirect Branch Recurrent Target Prediction Disable (`IBRTPD`) | 3 |
| `PR_PPC_DEXCR_SRAPD` | Subroutine Return Address Prediction Disable (`SRAPD`) | 4 |
| `PR_PPC_DEXCR_NPHIE` | Non-Privileged Hash Instruction Enable (`NPHIE`) | 5 |
| `prctl()` ctrl | 의미 |
|---|---|
| `PR_PPC_DEXCR_CTRL_EDITABLE` | `PR_PPC_SET_DEXCR`로 이 aspect를 설정할 수 있음. 조회 전용 flag |
| `PR_PPC_DEXCR_CTRL_SET` | Aspect가 현재 set 상태 / aspect를 set |
| `PR_PPC_DEXCR_CTRL_CLEAR` | Aspect가 현재 clear 상태 / aspect를 clear |
| `PR_PPC_DEXCR_CTRL_SET_ONEXEC` | `exec` 뒤 aspect가 set될 예정 / exec 뒤 set |
| `PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC` | `exec` 뒤 aspect가 clear될 예정 / exec 뒤 clear |
Aspect 상태와 process lifecycle
98-131- `which`는 bitmask가 아닌 plain value이므로 aspect를 하나씩 처리해야 합니다.
- `ctrl`은 bitmask입니다. `PR_PPC_GET_DEXCR`는 현재 상태와 on-exec configuration을 함께 반환합니다. 예를 들어 `PR_PPC_DEXCR_CTRL_EDITABLE | PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC`는 현재 set, 다음 exec 때 clear, `PR_PPC_SET_DEXCR`로 변경 가능함을 뜻합니다.
- Set/clear는 DEXCR bit 자체를 set/clear한다는 뜻입니다.
- `PR_PPC_GET_DEXCR`가 반환하는 status는 process가 적용되기를 원하는 값이며 hypervisor override를 포함하지 않습니다. 실제 DEXCR state는 적절한 SPR을 직접 읽어야 합니다.
- Process 시작 시 aspect state는 `fork(2)`에서 parent state를 복사하고 `execve(2)`에서 고정값으로 reset합니다. `PR_PPC_SET_DEXCR`는 현재 값과 on-exec 값을 모두 제어할 수 있습니다.
- `*_ONEXEC` control은 현재 process의 DEXCR을 바꾸지 않습니다.
prctl(PR_PPC_SET_DEXCR, PR_PPC_DEXCR_IBRTPD, PR_PPC_DEXCR_CTRL_SET, 0, 0);
이 call은 DEXCR의 `IBRTPD` aspect bit를 set해 indirect branch prediction을 disable합니다. 특정 aspect를 즉시 바꾸려면 `PR_PPC_SET_DEXCR`와 `PR_PPC_DEXCR_CTRL_SET` 또는 `PR_PPC_DEXCR_CTRL_CLEAR`를 사용합니다.
현재 상태, fork inheritance, exec reset/onexec 적용 관계입니다.
Error code와 container default
132-177DEXCR get/set에 공통으로 적용되는 error는 다음과 같습니다.
| Error | 의미 |
|---|---|
| `EINVAL` | Kernel이 DEXCR을 지원하지 않음 |
| `ENODEV` | Kernel이 aspect를 인식하지 못하거나 hardware가 지원하지 않음 |
`PR_PPC_SET_DEXCR`는 다음 error도 반환할 수 있습니다.
| Error | 의미 |
|---|---|
| `EINVAL` | `ctrl`에 알 수 없는 flag가 포함됨 |
| `EINVAL` | `PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR`처럼 서로 충돌하는 flag가 포함됨 |
| `EPERM` | 이 aspect를 `prctl()`로 수정할 수 없음. `PR_PPC_GET_DEXCR`의 `PR_PPC_DEXCR_CTRL_EDITABLE` 확인 필요 |
| `EPERM` | Process privilege가 부족함. 예를 들어 exec 때 NPHIE를 clear하는 작업은 privileged이지만 process가 자기 현재 NPHIE aspect를 clear하는 것은 privilege 없이 가능 |
이 interface는 process가 자기 DEXCR aspect와 process tree의 child가 시작할 때 사용할 DEXCR 값을 제어하게 합니다. 다음 child가 별도 `*_ONEXEC` control을 사용할 때까지 적용되므로 container마다 서로 다른 DEXCR default를 주는 등 세밀한 정책을 만들 수 있습니다.
Coredump와 ptrace 노출
178-195Userspace DEXCR과 HDEXCR 값은 이 순서로 `NT_PPC_DEXCR` 아래 노출됩니다. 둘 다 64-bit read-only이며 core dump 분석을 돕기 위한 interface입니다. 향후 DEXCR은 writable이 될 수 있습니다. Non-userspace bit에 해당하는 두 register의 상위 32-bit는 mask됩니다.
`CONFIG_CHECKPOINT_RESTORE`가 enable되면 `NT_PPC_HASHKEYR`가 process의 HASHKEYR 값을 read/write로 노출합니다. 일반 process는 secret key를 알 필요가 없지만 process restore에는 원래 key 설정이 필요하므로 security와 checkpoint/restore 사이의 tradeoff입니다.
그 결과 key가 core dump에 나타납니다. Attacker가 coredump에서 key를 얻으면 같은 key를 공유하는 thread, 잠재적으로 같은 parent에서 만들어지고 아직 `exec()`하지 않은 모든 thread의 ROP protection을 사실상 우회할 수 있습니다.
요약과 해설
dexcr.rst:1-195Process는 `PR_PPC_GET_DEXCR`/`PR_PPC_SET_DEXCR`로 aspect를 제어하며 hypervisor 강제 bit와 OR된 값이 실제 상태입니다. Fork/exec inheritance와 coredump secret-key 노출을 함께 고려해야 합니다.