Cascade is a RISC-V CPU fuzzer that generates valid, long and complex programs, and relies on a termination cascade-effect for bug detection. It detected 37 new bugs (29 new CVEs) in 5 RISC-V CPUs, which is more than all the existing fuzzers, combined. You can read a paper we wrote on Cascade here and try it out here. Below is a video demo of it finding a bug in CVA6:
Fuzzing CPUs is akin to generating interesting programs, and observing expressions of buggy behaviors. An effective CPU fuzzing campaign must have some fundamental properties.
- Programs must be long to increase fuzzing throughput.
- Programs must be complex to increase the probability of triggering a bug.
- The fuzzer must reliably and efficiently detect bugs, once triggered.
Pitfalls of existing fuzzers
Existing CPU fuzzers do not comply with these fundamental properties. Fuzzers may have the following shortcomings:
- Programs are short by design with trivial control flows.
- The executed portion of the programs are short because the control flow is poorly managed.
- Most instructions are not randomized and correspond to initialization and finalization.
- Only a small part of the ISA is covered.
- The CPU state is checked at instruction granularity, significantly impacting the fuzzing performance.
- Bugs have a high chance of being shadowed because their expression is eventually overwritten in the control flow.
Ultimately, a fuzzer with such pitfalls will suffer from critical weaknesses which will likely make fuzzing campaigns ineffective or inefficient.
Cascade is a RISC-V CPU fuzzer that generates valid, long and complex programs, and relies on a cascade-effect termination for bug detection. Fuzzing proceeds as follows:
- Intermediate program construction: First, Cascade builds an intermediate program with complex data and control flows, the latter being independent of the former.
- Ultimate program construction: Cascade simulates the program using a golden model of the ISA to collect feedback about the behavior of the data flow. From this feedback, it entangles the data flow into the control flow to build the ultimate version of the program.
- Ultimate program execution: Cascade executes the program on the CPU under test. Non-terminations indicate that a bug has been triggered by a program.
Below you can see a design diagram of Cascade:
A common but unsatisfying way of detecting whether a bug has been triggered is to compare, instruction by instruction, whether the CPU state matches with the golden model state. This method is difficult to implement and expensive in terms of performance.
In Cascade-generated programs, due to the entanglement of data and control flow, a bug in the data flow will have a very high chance of altering the control flow, causing non-termination.
Asynchronous ISA pre-simulation
To transform an intermediate program into an ultimate program, i.e., to entangle the data flow into the control flow, Cascade uses the feedback from spike, a golden model of the RISC-V ISA to determine some dependent register values generated by critical points in the program. Knowing these values allows correcting them at a later point of the program to achieve the same control-flow and exceptional behavior as in the intermediate program, while entangling the data flow into the control flow. While there may be many dependent values and control-flow changes in a program, we show that a single careful execution of the ISA golden model suffices to entangle the data flow into the control flow at all points of the program.
Reduction of buggy programs
Cascade found tens of new bugs, but the programs that trigger them are long and complex. Cascade features a new mechanism that reduces bug-triggering programs into very few instructions, while preserving the bug-preserving behavior. Here is the Cascade’s bug reduction mechanism in action:
Cascade found 37 new bugs (29 new CVEs) in 5 RISC-V CPUs. We reported them to their respective maintainers and fixed some of them ourselves. The discovered bugs have many security implications, ranging from information leakage to denial of service from user mode by a specific operation executed under speculation. Please look at the paper if you want to know more about the bugs. The figure below summarizes the security impact of these bugs:
Paper and code:
Cascade will be presented at USENIX Security ‘24, and is readily open-source here! Use it on your CPU if you want to make sure your RISC-V CPU does not suffer from security bugs and let us know if you found new bugs! Bing created the following logo for Cascade:
Frequently Asked Questions
Cascade found many bugs. Is RISC-V insecure?
Given today’s highly manual RTL design flows, the appearance of bugs is very likely, regardless of the ISA. Note that more than 1000 errata were released in Intel Core and AMD CPUs in recent years (see RemembERR). Hence, from Cascade’s findings, there is no reason to consider RISC-V to be inherently less secure than other ISAs.
I am a consumer, should I worry that Cascade finds bugs in my CPU?
At the time of this writing, RISC-V CPUs in commodity computers are rather uncommon. Hence, Cascade will hopefully find the bugs before a CPU is mass-produced.
Is Cascade only for RISC-V?
Yes. While some ideas like AIPS can be ported to other mainstream ISAs, Cascade is at the moment implemented only for RISC-V.
Can I use Cascade in CI/CD?
Yes! On a reasonable server, Cascade finds many bugs in a matter of seconds, hence it is perfectly suited for quick checks as well as long runs.
After fixing all the reported bugs, my CPU is now validated by Cascade. Is my CPU now perfectly safe and functional?
No, Cascade does not offer formal guarantees. You may want to turn to formal methods for such guarantees, but they require more expertise and effort.
What RISC-V extensions are currently being fuzzed by Cascade?
Cascade fuzzes rv[32-64]imfd, including exceptions, MSU privilege transitions and many CSR interactions. We plan to add new fuzzing features such as memory virtualization and compressed instructions in the future. Feel free to contribute?
How can I contribute to Cascade?
Just open a pull request on github and we will have a look.
This work was supported in part by a Microsoft Swiss JRC grant and by the Swiss State Secretariat for Education, Research and Innovation under contract number MB22.00057 (ERC-StG PROMISE).