Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-only |
2 | | |
3 | | #include <fuzz.h> |
4 | | #include <string.h> |
5 | | #include <common.h> |
6 | | |
7 | | #define for_each_fuzz_test(test) \ |
8 | 26 | for (test = &__barebox_fuzz_tests_start; \ |
9 | 182 | test != &__barebox_fuzz_tests_end; test++) |
10 | | |
11 | | int call_for_each_fuzz_test(int (*fn)(const struct fuzz_test *test, void *ctx), |
12 | | void *ctx) |
13 | 0 | { |
14 | 0 | const struct fuzz_test *test; |
15 | 0 | int ret; |
16 | |
|
17 | 0 | for_each_fuzz_test(test) { |
18 | 0 | ret = fn(test, ctx); |
19 | 0 | if (ret) |
20 | 0 | return ret; |
21 | 0 | } |
22 | | |
23 | 0 | return 0; |
24 | 0 | } |
25 | | |
26 | | static int list_fuzz_test_one(const struct fuzz_test *test, void *ctx) |
27 | 0 | { |
28 | 0 | int (*println)(const char *) = ctx; |
29 | |
|
30 | 0 | println(test->name); |
31 | 0 | return 0; |
32 | 0 | } |
33 | | |
34 | | void list_fuzz_tests(int (*println)(const char *)) |
35 | 0 | { |
36 | 0 | call_for_each_fuzz_test(list_fuzz_test_one, println); |
37 | 0 | } |
38 | | |
39 | | #ifdef CONFIG_FUZZ_EXTERNAL |
40 | | const u8 *fuzzer_get_data(size_t *len); |
41 | | #else |
42 | | static inline const u8 *fuzzer_get_data(size_t *len) |
43 | | { |
44 | | return NULL; |
45 | | } |
46 | | #endif |
47 | | |
48 | | extern int LLVMFuzzerRunDriver(int *argc, char ***argv, |
49 | | int (*cb)(const uint8_t *, size_t)); |
50 | | |
51 | | static const struct fuzz_test *fuzz; |
52 | | static int *saved_argc; |
53 | | static char ***saved_argv; |
54 | | |
55 | | static int fuzzer_run(const uint8_t *buf, size_t len) |
56 | 25.9k | { |
57 | 25.9k | return fuzz_test_once(fuzz, buf, len); |
58 | 25.9k | } |
59 | | |
60 | | /* |
61 | | * barebox supplies its own main() and enters libFuzzer via |
62 | | * LLVMFuzzerRunDriver(), so the fuzzing engine's own main() is never |
63 | | * executed. It is still linked in when an external engine (e.g. |
64 | | * OSS-Fuzz's LIB_FUZZING_ENGINE) is used, because the C runtime's |
65 | | * reference to main() extracts the engine's main object file before |
66 | | * --defsym=main=sandbox_main takes effect. Define the entry point it |
67 | | * references, so the link succeeds. |
68 | | */ |
69 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); |
70 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
71 | 0 | { |
72 | 0 | fuzz_test_setup(fuzz); |
73 | |
|
74 | 0 | return fuzzer_run(data, size); |
75 | 0 | } |
76 | | |
77 | | static int fuzz_main(void) |
78 | 26 | { |
79 | 26 | int ret = -1; |
80 | | |
81 | | /* buffering would make coverage depend on earlier inputs */ |
82 | 26 | log_set_max_messages(-1); |
83 | | |
84 | 26 | fuzz_test_setup(fuzz); |
85 | | |
86 | 26 | if (IS_ENABLED(CONFIG_FUZZ_EXTERNAL)) { |
87 | 26 | ret = LLVMFuzzerRunDriver(saved_argc, saved_argv, fuzzer_run); |
88 | 26 | pr_emerg("libfuzzer unexpectedly ended: %d\n", ret); |
89 | 26 | } else { |
90 | 0 | pr_emerg("libfuzzer not supported in this build\n"); |
91 | 0 | } |
92 | | |
93 | 26 | return ret; |
94 | 26 | } |
95 | | |
96 | | int setup_external_fuzz(const char *fuzz_name, |
97 | | int *argc, char ***argv) |
98 | 26 | { |
99 | 26 | const struct fuzz_test *test; |
100 | | |
101 | 26 | saved_argc = argc; |
102 | 26 | saved_argv = argv; |
103 | | |
104 | 182 | for_each_fuzz_test(test) { |
105 | 182 | if (streq_ptr(test->name, fuzz_name)) { |
106 | 26 | fuzz = test; |
107 | 26 | barebox_main = fuzz_main; |
108 | 26 | barebox_loglevel = MSG_CRIT; |
109 | 26 | return 0; |
110 | 26 | } |
111 | 182 | } |
112 | | |
113 | 0 | return -1; |
114 | 26 | } |
115 | | |
116 | | bool fuzz_external_active(void) |
117 | 0 | { |
118 | 0 | return fuzz != NULL; |
119 | 0 | } |