xref: /openbmc/qemu/tests/qtest/fuzz/fuzz.h (revision cdd684b8)
1 /*
2  * fuzzing driver
3  *
4  * Copyright Red Hat Inc., 2019
5  *
6  * Authors:
7  *  Alexander Bulekov   <alxndr@bu.edu>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  *
12  */
13 
14 #ifndef QTEST_FUZZ_H
15 #define QTEST_FUZZ_H
16 
17 #include "qemu/units.h"
18 #include "qapi/error.h"
19 
20 #include "tests/qtest/libqtest.h"
21 
22 /**
23  * A libfuzzer fuzzing target
24  *
25  * The QEMU fuzzing binary is built with all available targets, each
26  * with a unique @name that can be specified on the command-line to
27  * select which target should run.
28  *
29  * A target must implement ->fuzz() to process a random input.  If QEMU
30  * crashes in ->fuzz() then libfuzzer will record a failure.
31  *
32  * Fuzzing targets are registered with fuzz_add_target():
33  *
34  *   static const FuzzTarget fuzz_target = {
35  *       .name = "my-device-fifo",
36  *       .description = "Fuzz the FIFO buffer registers of my-device",
37  *       ...
38  *   };
39  *
40  *   static void register_fuzz_target(void)
41  *   {
42  *       fuzz_add_target(&fuzz_target);
43  *   }
44  *   fuzz_target_init(register_fuzz_target);
45  */
46 typedef struct FuzzTarget {
47     const char *name;         /* target identifier (passed to --fuzz-target=)*/
48     const char *description;  /* help text */
49 
50 
51     /*
52      * Returns the arguments that are passed to qemu/softmmu init(). Freed by
53      * the caller.
54      */
55     GString *(*get_init_cmdline)(struct FuzzTarget *);
56 
57     /*
58      * will run once, prior to running qemu/softmmu init.
59      * eg: set up shared-memory for communication with the child-process
60      * Can be NULL
61      */
62     void(*pre_vm_init)(void);
63 
64     /*
65      * will run once, after QEMU has been initialized, prior to the fuzz-loop.
66      * eg: detect the memory map
67      * Can be NULL
68      */
69     void(*pre_fuzz)(QTestState *);
70 
71     /*
72      * accepts and executes an input from libfuzzer. this is repeatedly
73      * executed during the fuzzing loop. Its should handle setup, input
74      * execution and cleanup.
75      * Cannot be NULL
76      */
77     void(*fuzz)(QTestState *, const unsigned char *, size_t);
78 
79     /*
80      * The fuzzer can specify a "Custom Crossover" function for combining two
81      * inputs from the corpus. This function is sometimes called by libfuzzer
82      * when mutating inputs.
83      *
84      * data1: location of first input
85      * size1: length of first input
86      * data1: location of second input
87      * size1: length of second input
88      * out: where to place the resulting, mutated input
89      * max_out_size: the maximum length of the input that can be placed in out
90      * seed: the seed that should be used to make mutations deterministic, when
91      *       needed
92      *
93      * See libfuzzer's LLVMFuzzerCustomCrossOver API for more info.
94      *
95      * Can be NULL
96      */
97     size_t(*crossover)(const uint8_t *data1, size_t size1,
98                        const uint8_t *data2, size_t size2,
99                        uint8_t *out, size_t max_out_size,
100                        unsigned int seed);
101 
102     void *opaque;
103 } FuzzTarget;
104 
105 void flush_events(QTestState *);
106 void fuzz_reset(QTestState *);
107 
108 /* Use the QTest ASCII protocol or call address_space API directly?*/
109 void fuzz_qtest_set_serialize(bool option);
110 
111 /*
112  * makes a copy of *target and adds it to the target-list.
113  * i.e. fine to set up target on the caller's stack
114  */
115 void fuzz_add_target(const FuzzTarget *target);
116 
117 size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1,
118                                  const uint8_t *data2, size_t size2,
119                                  uint8_t *out, size_t max_out_size,
120                                  unsigned int seed);
121 int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size);
122 int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp);
123 
124 #endif
125