Skip to content

Latest commit

 

History

History

README.md

RISCover - Differential CPU Fuzzing Framework

Note

Refer to the end of the file for instructions for artifact evaluation, but make sure to read these more generic notes first.

This directory provides the implementation of RISCover. RISCover is split into server and client.

The framework largely depends on Nix for package retrieval. If not done already run direnv allow. This should expand FRAMEWORK_ROOT and load the needed packages.

Server

The server generates inputs, receives outputs from the clients, compares them and logs reproducers on differences. The server is implemented in Python and can be started like:

python server/diffuzz-server.py --floats --seq-len 5 --generator RandomDiffFuzzGenerator

The server logs results in results/ as YAML reproducer files. The file format is as follows:

results/reproducers/reproducer-00000100-000001218860.yaml
  • 00000100: 100th reproducer of the current run.
  • 000001218860: Difference (reproducer) occurred after 1218860 inputs.

To quickly skim over these reproducers run:

for dir in results/reproducers/*; do find "$dir" -maxdepth 1 -type f | head -n 1; done | xargs bat --style=header --line-range :50

Client

The main client of RISCover is the diffuzz-client, implemented in client/src/diffuzz-client.c. It runs instructions sequences and sends the resulting state to the server.

The client compilation depends on the flags used by the server. To generate the set of build flags run:

python server/diffuzz-server.py --floats --seq-len 5 --generator RandomDiffFuzzGenerator --print-flags

This prints:

-DMAX_SEQ_LEN=5 -DWITH_REGS -DCOMPRESS_RECV -DFLOATS

This can be used to build the client like:

build-client --build-flags "-DMAX_SEQ_LEN=5 -DWITH_REGS -DCOMPRESS_RECV -DFLOATS" --target diffuzz-client --out diffuzz-client

This produces a static binary diffuzz-client which can be copied to any Linux machine, including Android (e.g., via Termux).

The client can then be started like:

./diffuzz-client <server-ip> <server-port>

Using Reproducers

Reproducer files (yaml) can be compiled to static binaries for quick reproduction. The framework provides multiple commands for that.

init-repro-template produces a C program that can be compiled and run:

init-repro-template results/reproducers/reproducer-00000100-000001218860.yaml

Creates a file results/reproducers/reproducer-00000100-000001218860.c.

This file can then be compiled with:

build-repro results/reproducers/reproducer-00000100-000001218860.c

This produces a static binary results,reproducers,reproducer-00000100-000001218860.

build-repro-run-on allows for quickly building and running on a machine using ssh:

build-repro-run-on results/reproducers/reproducer-00000100-000001218860.c -- <ssh/hostname>

init-build-run-on allows for quickly initializing, building and running on a machine using ssh:

init-build-run-on results/reproducers/reproducer-00000100-000001218860.yaml -- -- <ssh/hostname>

For all these scripts the following flags can be used:

  • --orig-seq: Use the original bytes as sequence and not assemble the recovered assembly instructions.
  • --no-sig: Build the reproducer without signal handling, i.e., plain. This is not that useful for the reproducers generated by architectural-sc-fuzzer.

Other Flags

The server accepts various flags, which can be inspected by calling:

python server/diffuzz-server.py --help

Important

For the offline sequence generation, a server that can execute RISC-V binaries is needed. binfmt is a good option for non-RISC-V machines.

The most relevant ones are:

  • --filter-thead: Filter out halting T-Head sequences and GhostWrite to not crash the machines.
  • --print-flags: Print the flags needed to be used to compile the client via build-client --build-flags "<FLAGS>".
  • --seq-len: The used sequence length.
  • --weighted: If weighted generation should be used.
  • --floats: If FP-support should be enabled.
  • --vector: If vector-support should be enabled.
  • --seed: The RNG seed.
  • --generator: The generator, RandomDiffFuzzGenerator for on-server, OfflineRandomDiffFuzzGenerator for on-device generation.

Artifact Evaluation

To evaluate the artifact we propose a differential fuzzing campaign using T-Head XuanTie C910 and another RISC-V machine. We will initially fuzz without vector support so the C910 does not crash due to GhostWrite.

The following commands must be executed within the directory of this file (RISCover_framework) on the fuzzing server. First, obtain the flags to compile the client:

$ python server/diffuzz-server.py --floats --seq-len 5 --generator RandomDiffFuzzGenerator --print-flags
(...)
-DMAX_SEQ_LEN=5 -DWITH_REGS -DCOMPRESS_RECV -DFLOATS

Then, compile the client:

$ build-client --build-flags "-DMAX_SEQ_LEN=5 -DWITH_REGS -DCOMPRESS_RECV -DFLOATS" --target diffuzz-client --out diffuzz-client-novec
(...)
ELF hash is: cdb6dd0750231c1ccc34ac9ebc04374d

Now, you can copy the diffuzz-client-novec binary to the C910 and the other machine. Once this is done, the server can be started:

$ python server/diffuzz-server.py --floats --seq-len 5 --generator RandomDiffFuzzGenerator
(...)
Press Enter to begin.

When the server is ready, you can ssh to the C910 and the other machine and start the diffuzz-client-novec binary:

$ ./diffuzz-client-novec <ip-of-server> 1337
(...)
Connected!

Now you can press Enter in the server terminal and watch as reproducers start coming in. You can now terminate the server and clients.

To run the reproducers, you can follow the instructions above. If you follow the steps above but compile with vector support (--vector in addition to --floats), the C910 should hang almost instantly after starting the fuzzing campaign, indicating that GhostWrite (in the vector extension) was triggered.