title | section | header | date |
---|---|---|---|
pmfuzz-fuzz |
1 |
PMFuzz Programmer's Manual |
March 2021 |
pmfuzz-fuzz - Generating high-value testcases for triggering crash-consistency PM programs.
pmfuzz-fuzz [-h] [--force-resp FORCE_RESP] [--cores-stage1 CORES_STAGE1] [--cores-stage2 CORES_STAGE2] [--overwrite] [--disable-stage2] [--dry-run] [--progress-interval PROGRESS_INTERVAL] [--progress-file PROGRESS_FILE] [--checks-only] [--verbose] [--version] indir outdir config
PMFuzz: A Persistent Memory Fuzzer, version 1.0 by ShiftLab
indir : path to directory containing initial test corpus for stage 1. See INPUT-DIRECTORY.
outdir : path to directory for generated test cases for stage 1, works as input for stage 2. See OUTPUT-DIRECTORY.
config : Points to the config file to use, should conform to: configs/default.yaml. See CONFIGURATION-FILE.
--force-resp FORCE_RESP : Forces response to questions
--cores-stage1 CORES_STAGE1, -c1 CORES_STAGE1 : Maximum cores stage 1 fuzzer can use, default: 1. Can be specified in config.
--cores-stage2 CORES_STAGE2, -c2 CORES_STAGE2 : Maximum cores stage 2 fuzzer can use, default: 1. Can be specified in config.
--overwrite, -o : Overwrite the output directory
--disable-stage2, -1 : Disables stage 2. Can be specified in config.
--dry-run : Enables dry run, no actual commands are executed (Deprecated)
--progress-interval PROGRESS_INTERVAL : Interval in seconds for recording progress, default: 60 seconds. Can be specified in config.
--progress-file PROGRESS_FILE : Output file for writing progress to a file. Can be specified in config.
--checks-only : Performs startup checks and exits
--verbose, -v : Enables verbose logging to stdout
--version : show program's version number and exit
To run PMFuzz without any additional output:
pmfuzz-fuzz \
./input_directory ./output_directory ./configs/default.yml
To record fuzzing progress, use:
pmfuzz-fuzz \
--progress-file=/tmp/fuzz_progress
./input_directory ./output_directory ./configs/default.yml
To get verbose output of the PMFuzz´s current step, use:
pmfuzz-fuzz \
--verbose \
./input_directory ./output_directory ./configs/default.yml
PMFuzz needs a non-empty directory with seed inputs for fuzzing. These inputs should be command inputs that PMFuzz can execute using the target program. PMFuzz directly uses these inputs using AFL, see afl-fuzz(1).
On each run, pmfuzz will write to the following files
- <output_dirname>/: Contains all the testcases, pool images, crash sites and other information needed to run PMFuzz.
- <output_dirname>.progress: Tracks the progress of the fuzzing.
- <output_dirname>.progress.events: Tracks events like stage transitions in PMFuzz.
The output directory has the following structure
output directory name
+-- @info
+-- @dedup
| +-- id=001.pm_pool
| +-- id=001.testcase
| +-- id=001.min.testcase
| +-- ...
+-- stage=1,iter=0
| +-- afl-results
| | +-- master_fuzzer
| | +-- queue
| | +-- slave_fuzzer01
| | +-- ...
| +-- testcases
| | +-- id=001.testcase
| | +-- ...
| +-- pm_images
| | +-- id=001.pm_pool
| | +-- ...
| +-- @dedup_sync
| +-- id=001.pm_pool
| +-- id=001.testcase
| +-- id=001.timer
| +-- ...
+-- stage=2,iter=1
+-- afl-results
| +-- id=0001/master_fuzzer/queue
| +-- id=0002/master_fuzzer/queue
| +-- ...
+-- testcases
| +-- id=0001,id=001.testcase
| +-- ...
| +-- id=0002,id=002.testcase
| +-- ...
+-- pm_images
| +-- id=0001,id=001.pm_pool
| +-- ...
| +-- id=0002,id=001.pm_pool
| +-- ...
+-- @dedup_sync
+-- id=001.pm_pool
+-- id=001.testcase
+-- id=001.timer
+-- ...
The output directory is co-located with progress file with the same
name as the output directory but has an file-extension of type
'.progress
'. The columns represent the following values, in-order they
appear:
Current time, Total testcases, Total PM testcases, Total paths, Total
PM paths, Executions/s, internal-execution-parameter
Each testcase/pm_image/crash_site name is a sequence of one or more
id-tags. Each id-tag is of the format id=<value>
and a sequence of
id-tags are connected using the characters .
or ,
. If an id-tag is
after ´.´ this means that the id-tag corresponds to a failure image,
while if an id-tag starts with ',
', then that id-tag is for a PMFuzz
generated testcase.
If a testcase has multiple IDs, they move down the hierarchy from left to right. An example fuzzing round and corresponding file name are:
PMFuzz marks all the testcases in the input directory with a unique sequential id starting from 1:
-
Initial testcases:
id=000001.testcase
,id=000002.testcase
... -
Next round of fuzzing uses the second testcase
id=000002.testcase
to generate 5 new testcases, these testcases will now be named:id=000002,id=000001.testcase
id=000002,id=000002.testcase
id=000002,id=000003.testcase
id=000002,id=000004.testcase
id=000002,id=000005.testcase
-
Next, PMFuzzes uses the testcase
id=00002,id=00003.testcase
to randomly generate the following crash sites:id=000002,id=000002.id=000011.testcase
id=000002,id=000002.id=000035.testcase
(note the use of both kinds separator)Example testcase/pm_pool/crash_site names:
id=000000,id=000199,id=00088.testcase
id=002310.id=000033mid=000002,id=000002.id=000035_pool
map_id=000002,id=010199.id=000004.id=000002.testcase
PMFuzz uses a YAML based file to configure different parameters.
configs/examples directory contains several examples for writing and organizing configurations that PMFuzz can use. If you want to write your own configuration file, include config/default.yml in your new config file and change the values you need.
If you are writing your own configuration, please note the following:
PMFuzz supports including one or more configuration files to allow easier customization.
Syntax for including config files is:
include:
- base-config-1.yaml
- base-config-2.yaml
.
.
- base-config-n.yaml
In case of duplicate keys, values are prioritized (and overwritten) in the order they appear. However, the file including them have highest priority.
Note
Nested includes are not supported.
The following variables are automatically substituted in the config file values:
%ROOT%
Points to the PMFuzz root directory (root of this repository)
%BUILD%
Points to the %ROOT%/build/
%LIB%
Points to the %ROOT%/build/lib
%BIN%
Points to the %ROOT%/build/bin
Here is a simple example that runs PMDK´s RBTree workload in baseline
mode. This configuration overwrites the number of CPU cores used by
the first stage to 4. Note, lines starting with #
are comments.
# Brief:
# Runs the Baseline for rbtree
include:
- configs/base.yml
- configs/workload/mapcli.rbtree.yml
- configs/run_configs/baseline.yml
pmfuzz:
stage:
"1":
cores: 4
This section defines several environment variables that may change PMFuzz´s behavior.
Values set and unset describe the behavior when the environment variable is not set to any value and when the variable is set to any non-empty string (including 0) respectively.
1
Enables fake mmap by copying the contents (using memcpy) of the pool
image to the volatile memory. Mounting the pool to the volatile memory
improves fuzzing performance.
0
Mounts the pool using PMDK´s default mounting functions. Before
invoking the target, PMFuzz would create a copy of the pool image and
call the target on that image. Depending on the output of the
fuzzing,PMFuzz would either save that image for future use, or discard
it.
addr
Address of the mount point of the pool. See libpmem(7).
unset
PMDK decides the mount address of the pool.
1
Disables default PMDK´s behaviour that generates non-identical images for same input.
0
PMFuzz generated images would have random variations that may
negatively affect the fuzzing performance and reproducibility.
"IMG_GEN"
In case the the PMFUZZ_MODE env variable is set to "IMG_GEN", a
failure point is injected and the PM Image is dumped if the PM pool
has changed since the last failure injection. First failure injection
always results in an image dump.
Images dump naming pattern: <pool file name>.<failure id>
If a failure
list file is additionally specified using the env variable, the falure
ids that generate dumps are written to that file, one per line.
"IMG_REP"
Todo
For more information on FI_MODE see libpmfuzz.c.
Path to a file that libpmfuzz would write the failure IDs to.
See libpmfuzz.c
1
Enables debug output from libpmfuzz.
0
unset
Disables debug output from libpmfuzz.
Enables deep paths in PMFuzz
Forces PMFuzz to generate all crash sites. Use with caution.
Deprecated.
set
Disable testcase size check in AFL++.
unset
Enables AFL++´s default behaviour to check testcase size.
See afl-fuzz(1).
set
Makes workload delete image on start if the pool exists.
Raised when AFL cannot bind to a free core or no core is free.
Check if device has any free space left.
Run the following command in your shell to remove all shared memory segments:
$ ipcrm -a
Warning: This removes all user owned shared memory segments, don´t run with superuser privilege or on a machine with other critical applications running.
To modify pmfuzz please look into docs/programming_manual or docs/programming_manual.pdf.
Please report bugs at: ⟨https://github.com/Systems-ShiftLab/pmfuzz/issues⟩
libpmfuzz(7), afl-fuzz(1), afl-cmin(1), afl-tmin(1), afl-gotcpu(1)
PMFuzz was written by ShiftLab, University of Virginia. ⟨https://www.cs.virginia.edu/~smk9u/shiftLab.html⟩
Complete documentation for PMFuzz can be accessed online at ⟨https://github.com/Systems-ShiftLab/pmfuzz/wiki⟩