The backward edge: Zicfiss keeps a second, MMU-protected shadow stack shadow stack Zicfiss backward-edge CFI: a second, MMU-protected stack (pointer in ssp) holding shadow copies of return addresses. Non-leaf prologues SSPUSH the link register; epilogues SSPOPCHK it against the regular stack's copy, faulting on mismatch — detecting return-address overwrites (ROP). Instructions are MOP-encoded so non-CFI cores run them as no-ops. defined in ch. I·34 — open in glossary of return-address copies, so an overwritten return address (the ROP primitive) is caught before the return executes.
| Operation | |
|---|---|
| SSPUSH / C.SSPUSH | Push the link register onto the shadow stack (decrement ssp, store) — the non-leaf prologue. |
| SSPOPCHK / C.SSPOPCHK | Pop the shadow copy and COMPARE it to the link register; mismatch → software-check fault (ROP detected). The non-leaf epilogue. |
| SSRDP | Read ssp into a register (stack inspection, debug). |
| SSAMOSWAP.W/D | Atomic swap on a shadow-stack word — the ONE non-MOP instruction, for atomic shadow-stack switching (thread/context management). Needs the SS page to grant the AMO. |
The prologue/epilogue pattern
foo: # non-leaf function
lpad 0 # (Zicfilp) landing pad, if address-taken
sspush ra # shadow copy of return address
addi sp, sp, -16
sd ra, 8(sp) # regular-stack copy
...
ld ra, 8(sp) # restore from regular stack
sspopchk ra # compare against shadow copy — fault if tampered
addi sp, sp, 16
ret
Hardware Designer Notes
Backward-edge hardware: one ssp CSR, a push (store) and a pop-compare-fault, plus the AMO reuse. The security rests on the MMU page protection (ch. II·16) — the two stacks only help if the attacker can’t reach both. Together with landing pads, this is RISC-V’s answer to ROP/JOP, and the reason RVA23 requires both.
Minimal Linux-boot hart MUST
- ssp as a CSR; SSPUSH = decrement-and-store, SSPOPCHK = load-and-compare-and-fault, both to SS-page-protected memory
- Decode the Zicfiss MOPs from the Zimop/Zcmop encoding space so non-CFI cores no-op them; SSAMOSWAP reuses the AMO datapath
- Enforce the store-type fault reporting (even for the reading SSPOPCHK) per the privileged spec’s fatality rules
MAY simplify / trap-and-emulate
- Skip Zicfiss on a Linux-boot v1 (binaries degrade to unprotected); RVA23 mandates it alongside Zicfilp
- Share SSAMOSWAP with your existing AMO unit — it’s an ordinary atomic swap gated by the SS page type
Check yourself — shadow stacks
1.How does the SSPUSH/SSPOPCHK pair detect a return-address overwrite (ROP)?
2.Why are the Zicfiss instructions (except SSAMOSWAP) encoded as MOPs (Zimop/Zcmop)?
3.What protects the shadow stack from being overwritten by ordinary stores?