RISC-V: No Longer Emit cm.popret When zcmp + zicfiss Is Enabled
GCC now uses cm.pop + sspopchk + a regular return instead of cm.popret when both zcmp and zicfiss are enabled, for better shadow stack management.
When -fcf-protection=return and zcmp are enabled, GCC previously generated cm.popret instructions, which skip emitting sspopchk. This commit replaces cm.popret with cm.pop + sspopchk + jr ra, ensuring sspopchk is always emitted for improved security with shadow stacks. The change was regtested for rv32g and rv64g.
In Details
The RISC-V backend now avoids cm.popret when shadow stack protection is active alongside the zcmp extension. Instead, it emits a sequence of cm.pop, sspopchk, and jr ra. This ensures stack pointer integrity checks are performed, even though cm.popret would skip them. Interaction with riscv_expand_epilogue is key here.
For Context
Shadow stacks are a security feature that protect against return-oriented programming (ROP) attacks by storing return addresses in a separate stack. The RISC-V architecture, with extensions like zcmp and zicfiss, provides instructions to manage these stacks. This commit changes how GCC emits code when shadow stack protection is enabled, ensuring that stack pointer checks (sspopchk) are always performed before returning from a function, preventing potential security vulnerabilities.