Package: revizor-fuzzer
RevizorRevizor is a security-oriented fuzzer for detecting information leaks in CPUs, such asSpectre and Meltdown.
It tests CPUs againstLeakage Contractsand searches for unexpected leaks.For more details, see ourPaper(open accesshere), and thefollow-up paper.InstallationWarning:
Keep in mind that the Revizor runs randomly-generated code in kernel space.
As you can imagine, things could go wrong.
Make sure you're not running Revizor on an important machine.1. Check RequirementsArchitecture: Revizor supports Intel and AMD x86-64 CPUs.
We also have experimental support for ARM CPUs (seearm-portbranch) but it is at very early stages, use it on your own peril.No virtualization: You will need a bare-metal OS installation.
Testing from inside a VM is not (yet) supported.OS: The target machine has to be running Linux v4.15 or later.2. Install Revizor Python PackageIf you usepip, you can install Revizor with:pipinstallrevizor-fuzzerAlternatively, install Revizor from sources:# run from the project root directorymakeinstallIf the installation fails with'revizor-fuzzer' requires a different Python:, you'll have to install Python 3.9 and run Revizor from a virtual environment:sudoaptinstallpython3.9python3.9-venv
/usr/bin/python3.9-mpipinstallvirtualenv
/usr/bin/python3.9-mvirtualenv~/venv-revizorsource~/venv-revizor/bin/activate
pipinstallrevizor-fuzzer3. Install Revizor Executor (kernel module)Then build and install the kernel module:# building a kernel module require kernel headerssudoapt-getinstalllinux-headers-$(uname-r)# get the source codegitclonehttps://github.com/microsoft/sca-fuzzer.git# build the executorcdsca-fuzzer/src/x86/executor
makeuninstall# the command will give an error message, but it's ok!makeclean
make
makeinstall4. Download ISA specrvzrdownload_spec-ax86-64--extensionsBASESSESSE2CLFLUSHOPTCLFSH--outfilebase.json5. (Optional) System ConfigurationFor more stable results, disable hyperthreading (there's usually a BIOS option for it).
If you do not disable hyperthreading, you will see a warning every time you invoke Revizor; you can ignore it.Optionally (and itreallyis optional), you can boot the kernel on a single core by adding-maxcpus=1to the boot parameters (how to add a boot parameter).Command Line InterfaceThe fuzzer is controlled via a single command line interfacervzr(orrevizor.pyif you're running directly from the source directory).It accepts the following arguments:-s, --instruction-set PATH- path to the ISA description file-c, --config PATH- path to the fuzzing configuration file-n , --num-test-cases N- number of test cases to be tested-i , --num-inputs N- number of input classes per test case. The number of actual inputs = input classes * inputs_per_class, which is a configuration option-t , --testcase PATH- use an existing test case instead of generating random test cases--timeout TIMEOUT- run fuzzing with a time limit [seconds]-w- working directory where the detected violations will be storedFor example, this commandrvzrfuzz-sbase.json-n100-i10-cconfig.yaml-w./violationswill run the fuzzer for 100 iterations (i.e., 100 test cases), with 10 inputs per test case.
The fuzzer will use the ISA spec stored in thebase.jsonfile, and will read the configuration fromconfig.yaml. If the fuzzer finds a violation, it will be stored in the./violationsdirectory.Seedocsfor more details.How To Fuzz With RevizorThe fuzzing process is controlled by a configuration file in the YAML format, passed via--configoption. At the very minimum, this file should contain the following fields:contract_observation_clauseandcontract_execution_clausedescribe the contract that the CPU-under-test is tested against. Seethis pagefor a list of available contracts. If you don't know what a contract is, Sec. 3 ofthis paperwill give you a high-level introduction to contracts, andthis paperwill provide a deep dive into contracts.instruction_categoriesis a list of instruction types that will be tested. Effectively, Revizor uses this list to filter out instructions frombase.json(the file you downloaded viarvzr download_spec).For a full list of configuration options, seedocs.Baseline ExperimentAfter a fresh installation, it is normally a good idea to do a quick test run to check that everything works ok.For example, we can create a configuration fileconfig.yamlwith only simple arithmetic instructions. As this instruction set does not include any instructions that would trigger speculation on Intel or AMD CPUs (at least that we know of), the expected contract would beCT-SEQ:# config.yamlinstruction_categories:-BASE-BINARY# arithmetic instructionsmax_bb_per_function:1# no branches!min_bb_per_function:1contract_observation_clause:loads+stores+pc# aka CTcontract_execution_clause:-no_speculation# aka SEQStart the fuzzer:rvzrfuzz-sbase.json-i50-n100-cconfig.yaml-w.This command should terminate with no violations.Detection of a Simple Contract ViolationNext, we could intentionally make a mistake in a contract to check that Revizor can detect it.
To this end, we can modify the config file from the previous example to include instructions that trigger speculation (e.g., conditional branches) but keep the contract the same:# config.yamlinstruction_categories:-BASE-BINARY# arithmetic instructions-BASE-COND_BRmax_bb_per_function:5# up to 5 branches per test casemin_bb_per_function:1contract_observation_clause:loads+stores+pc# aka CTcontract_execution_clause:-no_speculation# aka SEQStart the fuzzer:rvzrfuzz-sbase.json-i50-n1000-cconfig.yaml-w.As your CPU-under-test almost definitely implements branch prediction, Revizor should detect a violation within a few minutes, with a message similar to this:================================ Violations detected ==========================
  Contract trace (hash):

    0111010000011100111000001010010011110101110011110100000111010110
  Hardware traces:
   Inputs [907599882]:
    .....^......^......^...........................................^
   Inputs [2282448906]:
    ...................^.....^...................................^.^You can find the violating test case as well as the violation report in the directory named./violation-*/.
It will contain an assembly fileprogram.asmthat surfaced a violation, a sequence of inputsinput-*.binto this program, and some details about the violation inreport.txt.Full-Scale Fuzzing CampaignTo start a full-scale test, write your own configuration file (see descriptionhereand an example confighere), and launch the fuzzer.Below is a example launch command, which will start a 24-hour fuzzing session, with 100 input classes per test case, and which usesbig-fuzz.yamlconfiguration:rvzrfuzz-sbase.json-csrc/tests/big-fuzz.yaml-i100-n100000000--timeout86400-w`pwd`--nonstopWhen you find a violation, you will have to do some manual investigation to understand the source of it;this guideis an example of how to do such an investigation.Need Help with Revizor?If you find a bug in Revizor, don't hesitate toopen an issue.If something is confusing or you need help in using Revizor, we have adiscussion page.DocumentationFor more details, seethe website.ContributingSeeCONTRIBUTING.md.TrademarksThis project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must followMicrosoft's Trademark & Brand Guidelines.
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.