DeTRAP: RISC-V Return Address Protection With Debug Triggers
Isaac Richter, Jie Zhou, John Criswell
TL;DR
DeTRAP tackles control-flow hijacking in embedded C/C++ by repurposing RISC-V debug triggers to implement a write-protected shadow stack for return addresses, eliminating the need for memory-protection hardware. It combines a memory-layout strategy, a small set of debug-trigger policies, compiler-assisted prologue/epilogue transformations, and a trusted runtime with a code scanner to enforce return-address integrity and forward-edge control-flow integrity. FPGA-based evaluation shows low runtime overheads ($0.5\%$–$1.9\%$), modest code-size overheads (~$7.9\%$), and minimal hardware-area impact (~$0.14\%$), outperforming prior approaches while avoiding whole-program analysis. By reusing standardized RISC-V debug features, DeTRAP offers a practical, hardware-light path to robust return-address protection suitable for resource-constrained microcontrollers.
Abstract
Modern microcontroller software is often written in C/C++ and suffers from control-flow hijacking vulnerabilities. Previous mitigations suffer from high performance and memory overheads and require either the presence of memory protection hardware or sophisticated program analysis in the compiler. This paper presents DeTRAP (Debug Trigger Return Address Protection). DeTRAP utilizes a full implementation of the RISC-V debug hardware specification to provide a write-protected shadow stack for return addresses. Unlike previous work, DeTRAP requires no memory protection hardware and only minor changes to the compiler toolchain. We tested DeTRAP on an FPGA running a 32-bit RISC-V microcontroller core and found average execution time overheads to be between 0.5% and 1.9% on evaluated benchmark suites with code size overheads averaging 7.9% or less.
