123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- # Specification for the fuzz testing tool
- #
- # Copyright (C) 2014 Maria Kustova <maria.k@catit.be>
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- Image fuzzer
- ============
- Description
- -----------
- The goal of the image fuzzer is to catch crashes of qemu-io/qemu-img
- by providing to them randomly corrupted images.
- Test images are generated from scratch and have valid inner structure with some
- elements, e.g. L1/L2 tables, having random invalid values.
- Test runner
- -----------
- The test runner generates test images, executes tests utilizing generated
- images, indicates their results and collects all test related artifacts (logs,
- core dumps, test images, backing files).
- The test means execution of all available commands under test with the same
- generated test image.
- By default, the test runner generates new tests and executes them until
- keyboard interruption. But if a test seed is specified via the '--seed' runner
- parameter, then only one test with this seed will be executed, after its finish
- the runner will exit.
- The runner uses an external image fuzzer to generate test images. An image
- generator should be specified as a mandatory parameter of the test runner.
- Details about interactions between the runner and fuzzers see "Module
- interfaces".
- The runner activates generation of core dumps during test executions, but it
- assumes that core dumps will be generated in the current working directory.
- For comprehensive test results, please, set up your test environment
- properly.
- Paths to binaries under test (SUTs) qemu-img and qemu-io are retrieved from
- environment variables. If the environment check fails the runner will
- use SUTs installed in system paths.
- qemu-img is required for creation of backing files, so it's mandatory to set
- the related environment variable if it's not installed in the system path.
- For details about environment variables see qemu-iotests/check.
- The runner accepts a JSON array of fields expected to be fuzzed via the
- '--config' argument, e.g.
- '[["feature_name_table"], ["header", "l1_table_offset"]]'
- Each sublist can have one or two strings defining image structure elements.
- In the latter case a parent element should be placed on the first position,
- and a field name on the second one.
- The runner accepts a list of commands under test as a JSON array via
- the '--command' argument. Each command is a list containing a SUT and all its
- arguments, e.g.
- runner.py -c '[["qemu-io", "$test_img", "-c", "write $off $len"]]'
- /tmp/test ../qcow2
- For variable arguments next aliases can be used:
- - $test_img for a fuzzed img
- - $off for an offset in the fuzzed image
- - $len for a data size
- Values for last two aliases will be generated based on a size of a virtual
- disk of the generated image.
- In case when no commands are specified the runner will execute commands from
- the default list:
- - qemu-img check
- - qemu-img info
- - qemu-img convert
- - qemu-io -c read
- - qemu-io -c write
- - qemu-io -c aio_read
- - qemu-io -c aio_write
- - qemu-io -c flush
- - qemu-io -c discard
- - qemu-io -c truncate
- Qcow2 image generator
- ---------------------
- The 'qcow2' generator is a Python package providing 'create_image' method as
- a single public API. See details in 'Test runner/image fuzzer' chapter of
- 'Module interfaces'.
- Qcow2 contains two submodules: fuzz.py and layout.py.
- 'fuzz.py' contains all fuzzing functions, one per image field. It's assumed
- that after code analysis every field will have own constraints for its value.
- For now only universal potentially dangerous values are used, e.g. type limits
- for integers or unsafe symbols as '%s' for strings. For bitmasks random amount
- of bits are set to ones. All fuzzed values are checked on non-equality to the
- current valid value of the field. In case of equality the value will be
- regenerated.
- 'layout.py' creates a random valid image, fuzzes a random subset of the image
- fields by 'fuzz.py' module and writes a fuzzed image to the file specified.
- If a fuzzer configuration is specified, then it has the next interpretation:
- 1. If a list contains a parent image element only, then some random portion
- of fields of this element will be fuzzed every test.
- The same behavior is applied for the entire image if no configuration is
- used. This case is useful for the test specialization.
- 2. If a list contains a parent element and a field name, then a field
- will be always fuzzed for every test. This case is useful for regression
- testing.
- The generator can create header fields, header extensions, L1/L2 tables and
- refcount table and blocks.
- Module interfaces
- -----------------
- * Test runner/image fuzzer
- The runner calls an image generator specifying the path to a test image file,
- path to a backing file and its format and a fuzzer configuration.
- An image generator is expected to provide a
- 'create_image(test_img_path, backing_file_path=None,
- backing_file_format=None, fuzz_config=None)'
- method that creates a test image, writes it to the specified file and returns
- the size of the virtual disk.
- The file should be created if it doesn't exist or overwritten otherwise.
- fuzz_config has a form of a list of lists. Every sublist can have one
- or two elements: first element is a name of a parent image element, second one
- if exists is a name of a field in this element.
- Example,
- [['header', 'l1_table_offset'],
- ['header', 'nb_snapshots'],
- ['feature_name_table']]
- Random seed is set by the runner at every test execution for the regression
- purpose, so an image generator is not recommended to modify it internally.
- Overall fuzzer requirements
- ===========================
- Input data:
- ----------
- - image template (generator)
- - work directory
- - action vector (optional)
- - seed (optional)
- - SUT and its arguments (optional)
- Fuzzer requirements:
- -------------------
- 1. Should be able to inject random data
- 2. Should be able to select a random value from the manually pregenerated
- vector (boundary values, e.g. max/min cluster size)
- 3. Image template should describe a general structure invariant for all
- test images (image format description)
- 4. Image template should be autonomous and other fuzzer parts should not
- rely on it
- 5. Image template should contain reference rules (not only block+size
- description)
- 6. Should generate the test image with the correct structure based on an image
- template
- 7. Should accept a seed as an argument (for regression purpose)
- 8. Should generate a seed if it is not specified as an input parameter.
- 9. The same seed should generate the same image for the same action vector,
- specified or generated.
- 10. Should accept a vector of actions as an argument (for test reproducing and
- for test case specification, e.g. group of tests for header structure,
- group of test for snapshots, etc)
- 11. Action vector should be randomly generated from the pool of available
- actions, if it is not specified as an input parameter
- 12. Pool of actions should be defined automatically based on an image template
- 13. Should accept a SUT and its call parameters as an argument or select them
- randomly otherwise. As far as it's expected to be rarely changed, the list
- of all possible test commands can be available in the test runner
- internally.
- 14. Should support an external cancellation of a test run
- 15. Seed should be logged (for regression purpose)
- 16. All files related to a test result should be collected: a test image,
- SUT logs, fuzzer logs and crash dumps
- 17. Should be compatible with python version 2.4-2.7
- 18. Usage of external libraries should be limited as much as possible.
- Image formats:
- -------------
- Main target image format is qcow2, but support of image templates should
- provide an ability to add any other image format.
- Effectiveness:
- -------------
- The fuzzer can be controlled via template, seed and action vector;
- it makes the fuzzer itself invariant to an image format and test logic.
- It should be able to perform rather complex and precise tests, that can be
- specified via an action vector. Otherwise, knowledge about an image structure
- allows the fuzzer to generate the pool of all available areas can be fuzzed
- and randomly select some of them and so compose its own action vector.
- Also complexity of a template defines complexity of the fuzzer, so its
- functionality can be varied from simple model-independent fuzzing to smart
- model-based one.
- Glossary:
- --------
- Action vector is a sequence of structure elements retrieved from an image
- format, each of them will be fuzzed for the test image. It's a subset of
- elements of the action pool. Example: header, refcount table, etc.
- Action pool is all available elements of an image structure that generated
- automatically from an image template.
- Image template is a formal description of an image structure and relations
- between image blocks.
- Test image is an output image of the fuzzer defined by the current seed and
- action vector.
|