34.2.5-7CFI II: Shadow Stacks (Zicfiss)

Part III Linux boot: optional Vol. I (Unprivileged) pp. 569–575 · ~2 min read

  • shadow stack

The backward edge: Zicfiss keeps a second, MMU-protected shadow stack of return-address copies, so an overwritten return address (the ROP primitive) is caught before the return executes.

The Zicfiss instructions (all MOP-encoded except SSAMOSWAP; ssp = shadow-stack pointer, grows down, XLEN entries)
Operation
SSPUSH / C.SSPUSHPush the link register onto the shadow stack (decrement ssp, store) — the non-leaf prologue.
SSPOPCHK / C.SSPOPCHKPop the shadow copy and COMPARE it to the link register; mismatch → software-check fault (ROP detected). The non-leaf epilogue.
SSRDPRead ssp into a register (stack inspection, debug).
SSAMOSWAP.W/DAtomic 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.
Dotted-underlined cells have explanations — click one.

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?

3 questions