aboutsummaryrefslogtreecommitdiff
path: root/src/priv-cfi.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/priv-cfi.adoc')
-rw-r--r--src/priv-cfi.adoc374
1 files changed, 374 insertions, 0 deletions
diff --git a/src/priv-cfi.adoc b/src/priv-cfi.adoc
new file mode 100644
index 0000000..1b03257
--- /dev/null
+++ b/src/priv-cfi.adoc
@@ -0,0 +1,374 @@
+[[priv-cfi]]
+== Control-flow Integrity (CFI)
+
+Control-flow Integrity (CFI) capabilities help defend against Return-Oriented
+Programming (ROP) and Call/Jump-Oriented Programming (COP/JOP) style
+control-flow subversion attacks. The Zicfiss and Zicfilp extensions provide
+backward-edge and forward-edge control flow integrity respectively. Please see
+the Control-flow Integrity chapter of the Unprivileged ISA specification for further
+details on these CFI capabilities and the associated Unprivileged ISA.
+
+[[priv-forward]]
+=== Landing Pad (Zicfilp)
+
+This section specifies the Privileged ISA for the Zicfilp extension.
+
+[[FCIFIACT]]
+==== Landing-Pad-Enabled (LPE) State
+
+The term `xLPE` is used to determine if forward-edge CFI using landing pads
+provided by the Zicfilp extension is enabled at a privilege mode.
+
+When S-mode is implemented, it is determined as follows:
+
+.`xLPE` determination when S-mode is implemented
+[width=100%]
+[%header, cols="^4,^12"]
+|===
+|Privilege Mode| xLPE
+| M | `mseccfg.MLPE`
+| S or HS | `menvcfg.LPE`
+| VS | `henvcfg.LPE`
+| U or VU | `senvcfg.LPE`
+|===
+
+When S-mode is not implemented, it is determined as follows:
+
+.`xLPE` determination when S-mode is not implemented
+[width=100%]
+[%header, cols="^4,^12"]
+|===
+|Privilege Mode| xLPE
+| M | `mseccfg.MLPE`
+| U | `menvcfg.LPE`
+|===
+
+[NOTE]
+====
+The Zicfilp must be explicitly enabled for use at each privilege mode.
+
+Programs compiled with the `LPAD` instruction continue to function correctly,
+but without forward-edge CFI protection, when the Zicfilp extension is not
+implemented or is not enabled.
+====
+
+<<<
+
+[[ZICFILP_FORWARD_TRAPS]]
+==== Preserving Expected Landing Pad State on Traps
+
+A trap may need to be delivered to the same or to a higher privilege mode upon
+completion of `JALR`/`C.JALR`/`C.JR`, but before the instruction at the target
+of indirect call/jump was decoded, due to:
+
+* Asynchronous interrupts.
+* Synchronous exceptions with priority higher than that of a software-check
+ exception with `__x__tval` set to "landing pad fault (code=2)" (See
+ <<exception-priority>> of Privileged Specification).
+
+The software-check exception caused by Zicfilp has higher priority than an
+illegal-instruction exception but lower priority than instruction access-fault.
+
+The software-check exception due to the instruction not being an `LPAD`
+instruction when `ELP` is `LP_EXPECTED` or an software-check exception caused by
+the `LPAD` instruction itself (See <<LP_INST>>) leads to a trap being delivered
+to the same or to a higher privilege mode.
+
+In such cases, the `ELP` prior to the trap, the previous `ELP`, must be
+preserved by the trap delivery such that it can be restored on a return from the
+trap. To store the previous `ELP` state on trap delivery to M-mode, an `MPELP`
+bit is provided in the `mstatus` CSR. To store the previous `ELP` state on trap
+delivery to S/HS-mode, an `SPELP` bit is provided in the `mstatus` CSR. The
+`SPELP` bit in `mstatus` can be accessed through the `sstatus` CSR. To store
+the previous `ELP` state on traps to VS-mode, a `SPELP` bit is defined in the
+`vsstatus` (VS-modes version of `sstatus`). To store the previous `ELP` state on
+transition to Debug Mode, a `pelp` bit is defined in the `dcsr` register.
+
+When a trap is taken into privilege mode `x`, the `__x__PELP` is set to `ELP`
+and `ELP` is set to `NO_LP_EXPECTED`.
+
+An `MRET` or `SRET` instruction is used to return from a trap in M-mode or
+S-mode, respectively. When executing an `__x__RET` instruction, if `__x__PP`
+holds the value `y`, then `ELP` is set to the value of `__x__PELP` if `__y__LPE`
+is 1; otherwise, it is set to `NO_LP_EXPECTED`; `__x__PELP` is set to
+`NO_LP_EXPECTED`.
+
+Upon entry into Debug Mode, the `pelp` bit in `dcsr` is updated with the `ELP`
+at the privilege level the hart was previously in, and the `ELP` is set to
+`NO_LP_EXPECTED`. When a hart resumes from Debug Mode, if `dcsr.prv` holds the
+value `y`, then `ELP` is set to the value of `pelp` if `__y__LPE` is 1;
+otherwise, it is set to `NO_LP_EXPECTED`.
+
+When the Smrnmi extension is implemented, a `MNPELP` field (bit 9)
+is provided in the `mnstatus` CSR to hold the previous `ELP` state on a trap to
+the RNMI handler. When a RNMI trap is delivered, the `MNPELP` is set to `ELP`
+and `ELP` set to `NO_LP_EXPECTED`. Upon a `MNRET`, if the `mnstatus.MNPP` holds
+the value `y`, then `ELP` is set to the value of `MNPELP` if `yLPE` is 1;
+otherwise, it is set to `NO_LP_EXPECTED`.
+
+[NOTE]
+====
+The trap handler in privilege mode `x` must save the `__x__PELP` bit and the
+`x7` register before performing an indirect call/jump if `xLPE=1`. If the
+privilege mode `x` can respond to interrupts and `xLPE=1`, then the trap handler
+should also save these values before enabling interrupts.
+
+The trap handler in privilege mode `x` must restore the saved `__x__PELP` bit
+and the `x7` register before executing the `__x__RET` instruction to return from
+a trap.
+====
+
+<<<
+
+[[priv-backward]]
+=== Shadow Stack (Zicfiss)
+
+This section specifies the Privileged ISA for the Zicfiss extension.
+
+==== Shadow Stack Pointer (`ssp`) CSR access control
+
+Attempts to access the `ssp` CSR may result in either an illegal-instruction
+exception or a virtual instruction exception, contingent upon the state of the
+*__x__*`envcfg.SSE` fields. The conditions are specified as follows:
+
+* If the privilege mode is less than M and `menvcfg.SSE` is 0, an
+ illegal-instruction exception is raised.
+* Otherwise, if in U-mode and `senvcfg.SSE` is 0, an illegal-instruction
+ exception is raised.
+* Otherwise, if in VS-mode and `henvcfg.SSE` is 0, a virtual instruction
+ exception is raised.
+* Otherwise, if in VU-mode and either `henvcfg.SSE` or `senvcfg.SSE` is 0,
+ a virtual instruction exception is raised.
+* Otherwise, the access is allowed.
+
+==== Shadow-Stack-Enabled (SSE) State
+
+The term `xSSE` is used to determine if backward-edge CFI using shadow stacks
+provided by the Zicfiss extension is enabled at a privilege mode.
+
+When S-mode is implemented, it is determined as follows:
+
+.`xSSE` determination when S-mode is implemented
+[width=100%]
+[%header, cols="^4,^12"]
+|===
+|Privilege Mode| `xSSE`
+| M | `0`
+| S or HS | `menvcfg.SSE`
+| VS | `henvcfg.SSE`
+| U or VU | `senvcfg.SSE`
+|===
+
+When S-mode is not implemented, then `xSSE` is 0 at both M and U privilege modes.
+
+[NOTE]
+====
+Activating Zicfiss in U-mode must be done explicitly per process. Not activating
+Zicfiss at U-mode for a process when that application is not compiled with
+Zicfiss allows it to invoke shared libraries that may contain Zicfiss
+instructions. The Zicfiss instructions in the shared library revert to their
+Zimop/Zcmop-defined behavior in this case.
+
+When Zicfiss is enabled in S-mode it is benign to use an operating system that is
+not compiled with Zicfiss instructions. Such an operating system that does
+not use backward-edge CFI for S-mode execution may still activate Zicfiss for
+U-mode applications.
+
+When programs that use Zicfiss instructions are installed on a processor that
+supports the Zicfiss extension but the extension is not enabled at the privilege
+mode where the program executes, the program continues to function correctly but
+without backward-edge CFI protection as the Zicfiss instructions will revert to
+their Zimop/Zcmop-defined behavior.
+
+When programs that use Zicfiss instructions are installed on a processor that
+does not support the Zicfiss extension but supports the Zimop and Zcmop
+extensions, the programs continues to function correctly but without
+backward-edge CFI protection as the Zicfiss instructions will revert to their
+Zimop/Zcmop-defined behavior.
+
+On processors that do not support Zimop/Zcmop extensions, all Zimop/Zcmop code
+points including those used for Zicfiss instructions may cause an
+illegal-instruction exception. Execution of programs that use these instructions
+on such machines is not supported.
+
+Activating Zicfiss in M-mode is currently not supported. Additionally, when
+S-mode is not implemented, activation in U-mode is also not supported. These
+functionalities may be introduced in a future standard extension.
+====
+
+[[SSMP]]
+==== Shadow Stack Memory Protection
+
+To protect shadow stack memory, the memory is associated with a new page type –
+the Shadow Stack (SS) page – in the single-stage and VS-stage page tables. The
+encoding `R=0`, `W=1`, and `X=0`, is defined to represent an SS page. When
+`menvcfg.SSE=0`, this encoding remains reserved. Similarly, when `V=1` and
+`henvcfg.SSE=0`, this encoding remains reserved at `VS` and `VU` levels.
+
+If `satp.MODE` (or `vsatp.MODE` when `V=1`) is set to `Bare` and the effective
+privilege mode is below M, shadow stack memory accesses are prohibited, and
+shadow stack instructions will raise a store/AMO access-fault exception. When
+the effective privilege mode is M, any memory access by an `SSAMOSWAP.W/D`
+instruction will result in a store/AMO access-fault exception.
+
+Memory mapped as an SS page cannot be written to by instructions other than
+`SSAMOSWAP.W/D`, `SSPUSH`, and `C.SSPUSH`. Attempts will raise a store/AMO
+access-fault exception. Implicit accesses, including instruction fetches to an SS
+page, are not permitted. Such accesses will raise an access-fault exception
+appropriate to the access type. However, the shadow stack is readable by all
+instructions that only load from memory.
+
+[NOTE]
+====
+Stores to shadow stack pages by instructions other than `SSAMOSWAP`, `SSPUSH`,
+and `C.SSPUSH` will trigger a store/AMO access-fault exception, not a store/AMO
+page-fault exception, signaling a fatal error. A store/AMO page-fault suggests
+that the operating system could address and rectify the fault, which is not
+feasible in this scenario. Hence, the page fault handler must decode the opcode
+of the faulting instruction to discern whether the fault was caused by a
+non-shadow-stack instruction writing to an SS page (a fatal condition) or by a
+shadow stack instruction to a non-resident page (a recoverable condition). The
+performance-critical nature of operating system page fault handlers necessitates
+triggering an access-fault instead of a page fault, allowing for a
+straightforward distinction between fatal conditions and recoverable faults.
+
+Operating systems must ensure that no writable, non-shadow-stack alias virtual
+address mappings exist for the physical memory backing the shadow stack.
+Furthermore, in systems where an address-misaligned exception supersedes the
+access-fault exception, handlers emulating misaligned stores must be designed to
+cause an access-fault exception when the store is directed to a shadow stack
+page.
+
+All instructions that perform load operations are allowed to read from the
+shadow stack. This feature facilitates debugging and performance profiling by
+allowing examination of the link register values backed up in the shadow stack.
+====
+
+[NOTE]
+====
+As of the drafting of this specification, instruction fetches are the sole type
+of implicit access subjected to single- or VS-stage address translation.
+====
+
+If a shadow stack (SS) instruction raises an access-fault, page-fault, or
+guest-page-fault exception that is supposed to indicate the original instruction
+type (load or store/AMO), then the reported exception cause is respectively a
+store/AMO access fault (code 7), a store/AMO page fault (code 15), or a
+store/AMO guest-page fault (code 23). For shadow stack instructions, the
+reported instruction type is always as though it were a store or AMO, even for
+instructions `SSPOPCHK` and `C.SSPOPCHK` that only read from memory and do not
+write to it.
+
+[NOTE]
+====
+When Zicfiss is implemented, the existing "store/AMO" exceptions can be thought
+of as "store/AMO/SS" exceptions, indicating that the trapping instruction is
+either a store, an AMO, or a shadow stack instruction.
+====
+
+[NOTE]
+====
+The H (hypervisor) extension specifies that when a guest-page fault is caused by
+an implicit memory access of VS-stage address translation, the reported
+exception is either a load or store/AMO guest-page fault based not on the
+original instruction type but rather on whether the memory access attempted for
+VS-stage translation was a read or a write of memory. VS-stage address
+translation can thus cause a shadow stack instruction to raise a load
+guest-page-fault exception.
+====
+
+Shadow stack instructions are restricted to accessing shadow stack
+(`pte.xwr=010b`) pages. Should a shadow stack instruction access a page that is
+not designated as a shadow stack page and is not marked as read-only
+(`pte.xwr=001`), a store/AMO access-fault exception will be invoked. Conversely,
+if the page being accessed by a shadow stack instruction is a read-only page, a
+store/AMO page-fault exception will be triggered.
+
+
+[NOTE]
+====
+Shadow stack loads and stores will trigger a store/AMO page-fault if the
+accessed page is read-only, to support copy-on-write (COW) of a shadow stack
+page. If the page has been marked read-only for COW tracking, the page fault
+handler responds by creating a copy of the page and updates the `pte.xwr` to
+`010b`, thereby designating each copy as a shadow stack page. Conversely, if
+the access targets a genuinely read-only page, the fault being reported as a
+store/AMO page-fault signals to the operating system that the fault is fatal
+and non-recoverable. Reporting the fault as a store/AMO page-fault, even for
+`SSPOPCHK` initiated memory access, aids in the determination of fatality; if
+these were reported as load page-faults, access to a truly read-only page
+might be mistakenly treated as a recoverable fault, leading to the faulting
+instruction being retried indefinitely. The PTE does not provide a read-only
+shadow stack encoding.
+
+Attempts by shadow stack instructions to access pages marked as read-write,
+read-write-execute, read-execute, or execute-only result in a store/AMO
+access-fault exception, similarly indicating a fatal condition.
+
+Shadow stacks should be bounded at each end by guard pages to prevent accidental
+underflows or overflows from one shadow stack into another. Conventionally, a
+guard page for a stack is a page that is not accessible by the process that owns
+the stack.
+====
+
+<<<
+
+If the virtual address in `ssp` is not `XLEN` aligned, then the `SSPUSH`/
+`C.SSPUSH`/`SSPOPCHK`/`C.SSPOPCHK` instructions cause a store/AMO access-fault
+exception.
+
+[NOTE]
+====
+Misaligned accesses to shadow stack are not required and enforcing alignment is
+more secure to detect errors in the program. An access-fault exception is raised
+instead of address-misaligned exception in such cases to indicate fatality and
+that the instruction must not be emulated by a trap handler.
+====
+
+Correct execution of shadow stack instructions that access memory requires the
+the accessed memory to be idempotent. If the memory referenced by
+`SSPUSH`/`C.SSPUSH`/`SSPOPCHK`/`C.SSPOPCHK`/`SSAMOSWAP.W/D` instructions is not
+idempotent, then the instructions cause a store/AMO access-fault exception.
+
+[NOTE]
+====
+The `SSPOPCHK` instruction performs a load followed by a check of the loaded
+data value with the link register as source. If the check against the link
+register faults, and the instruction is restarted by the trap handler, then the
+instruction will perform a load again. If the memory from which the load is
+performed is non-idempotent, then the second load may cause unexpected side
+effects. Shadow stack instructions that access the shadow stack require the
+memory referenced by `ssp` to be idempotent to avoid such concerns. Locating
+shadow stacks in non-idempotent memory, such as non-idempotent device memory,
+is not an expected usage, and requiring memory referenced to be idempotent
+does not pose a significant restriction.
+====
+
+The `U` and `SUM` bit enforcement is performed normally for shadow stack
+instruction initiated memory accesses. The state of the `MXR` bit does not
+affect read access to a shadow stack page as the shadow stack page is always
+readable by all instructions that load from memory.
+
+The G-stage address translation and protections remain unaffected by the Zicfiss
+extension. The `xwr == 010b` encoding in the G-stage PTE remains reserved. When
+G-stage page tables are active, the shadow stack instructions that access memory
+require the G-stage page table to have read-write permission for the accessed
+memory; else a store/AMO guest-page fault exception is raised.
+
+[NOTE]
+====
+A future extension may define a shadow stack encoding in the G-stage page table
+to support use cases such as a hypervisor enforcing shadow stack protections for
+its guests.
+====
+
+Svpbmt and Svnapot extensions are supported for shadow stack pages.
+
+The PMA checks are extended to require memory referenced by shadow stack
+instructions to be idempotent. The PMP checks are extended to require read-write
+permission for memory accessed by shadow stack instructions. If the PMP does not
+provide read-write permissions or if the accessed memory is not idempotent then
+a store/AMO access-fault exception is raised.
+
+The `SSAMOSWAP.W/D` instructions require the PMA of the accessed memory range to
+provide AMOSwap level support.