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.
Landing Pad (Zicfilp)
This section specifies the Privileged ISA for the Zicfilp extension.
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:
Privilege Mode | xLPE |
---|---|
M |
|
S or HS |
|
VS |
|
U or VU |
|
When S-mode is not implemented, it is determined as follows:
Privilege Mode | xLPE |
---|---|
M |
|
U |
|
The Zicfilp must be explicitly enabled for use at each privilege mode. Programs compiled with the |
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
xtval
set to "landing pad fault (code=2)" (See Synchronous exception priority in decreasing priority order 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 a software-check exception caused by
the LPAD
instruction itself 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 xPELP
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 xRET
instruction, if the new
privilege mode is y
, then ELP
is set to the value of xPELP
if
yLPE
(see Landing-Pad-Enabled (LPE) State) is 1; otherwise, it is set to NO_LP_EXPECTED
;
xPELP
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 the new privilege mode
is y
, then ELP
is set to the value of pelp
if yLPE
(see Landing-Pad-Enabled (LPE) State)
is 1; otherwise, it is set to NO_LP_EXPECTED
.
See also "Smrnmi" Extension for Resumable Non-Maskable Interrupts for semantics added to the RNMI trap and the MNRET instruction when this extension is implemented.
The trap handler in privilege mode The trap handler in privilege mode |
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
xenvcfg.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
orsenvcfg.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:
Privilege Mode | xSSE |
---|---|
M |
|
S or HS |
|
VS |
|
U or VU |
|
When S-mode is not implemented, then xSSE
is 0 at both M and U privilege modes.
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. |
Changes to xSSE take effect immediately; address-translation caches
need not be synchronized with SFENCE.VMA, HFENCE.GVMA, or HFENCE.VVMA
instructions.
|
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. Access to a SS page using cache-block operation
(CBO.*
) instructions is not permitted. Such accesses 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.
Stores to shadow stack pages by instructions other than 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. |
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.
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. |
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.
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 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.
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.
The |
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.
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.