1 /* Copyright (c) 2022 Google, LLC.
2 * SPDX-License-Identifier: Apache-2.0
3 */
4 #include <zephyr/kernel.h>
5 #include <string.h>
6 #include <zephyr/irq.h>
7 #include <zephyr/toolchain.h>
8 #include <irq_ctrl.h>
9 #if defined(CONFIG_BOARD_NATIVE_SIM)
10 #include <nsi_cpu_if.h>
11 #include <nsi_main_semipublic.h>
12 #elif defined(CONFIG_BOARD_NATIVE_POSIX)
13 /* Note: native_posix will be deprecated soon */
14 extern void posix_init(int argc, char *argv[]);
15 extern void posix_exec_for(uint64_t us);
16 #define nsi_init posix_init
17 #define nsi_exec_for posix_exec_for
18 #else
19 #error "Platform not supported"
20 #endif
21
22 /* Fuzz testing is coverage-based, so we want to hide a failure case
23 * (a write through a null pointer in this case) down inside a call
24 * tree in such a way that it would be very unlikely to be found by
25 * randomly-selected input. But the fuzzer can still find it in
26 * linear(-ish) time by discovering each new function along the way
27 * and then probing that new space. The 1 in 2^56 case here would
28 * require months-to-years of work for a large datacenter, but the
29 * fuzzer gets it in 20 seconds or so. This requires that the code for
30 * each case be distinguishable/instrumentable though, which is why we
31 * generate the recursive handler functions this way and disable
32 * inlining to prevent optimization.
33 */
34 int *global_null_ptr;
35 static const uint8_t key[] = { 0x9e, 0x21, 0x0c, 0x18, 0x9d, 0xd1, 0x7d };
36 bool found[ARRAY_SIZE(key)];
37
38 #define LASTKEY (ARRAY_SIZE(key) - 1)
39
40 #define GEN_CHECK(cur, nxt) \
41 void check##nxt(const uint8_t *data, size_t sz); \
42 void __noinline check##cur(const uint8_t *data, size_t sz) \
43 { \
44 if (cur < sz && data[cur] == key[cur]) { \
45 if (!found[cur]) { \
46 printk("#\n# Found key %d\n#\n", cur); \
47 found[cur] = true; \
48 } \
49 if (cur == LASTKEY) { \
50 *global_null_ptr = 0; /* boom! */ \
51 } else { \
52 check##nxt(data, sz); \
53 } \
54 } \
55 }
56
57 GEN_CHECK(0, 1)
58 GEN_CHECK(1, 2)
59 GEN_CHECK(2, 3)
60 GEN_CHECK(3, 4)
61 GEN_CHECK(4, 5)
62 GEN_CHECK(5, 6)
63 GEN_CHECK(6, 0)
64
65 /* Fuzz input received from LLVM via "interrupt" */
66 static const uint8_t *fuzz_buf;
67 static size_t fuzz_sz;
68
69 K_SEM_DEFINE(fuzz_sem, 0, K_SEM_MAX_LIMIT);
70
fuzz_isr(const void * arg)71 static void fuzz_isr(const void *arg)
72 {
73 /* We could call check0() to execute the fuzz case here, but
74 * pass it through to the main thread instead to get more OS
75 * coverage.
76 */
77 k_sem_give(&fuzz_sem);
78 }
79
main(void)80 int main(void)
81 {
82 printk("Hello World! %s\n", CONFIG_BOARD);
83
84 IRQ_CONNECT(CONFIG_ARCH_POSIX_FUZZ_IRQ, 0, fuzz_isr, NULL, 0);
85 irq_enable(CONFIG_ARCH_POSIX_FUZZ_IRQ);
86
87 while (true) {
88 k_sem_take(&fuzz_sem, K_FOREVER);
89
90 /* Execute the fuzz case we got from LLVM and passed
91 * through an interrupt to this thread.
92 */
93 check0(fuzz_buf, fuzz_sz);
94 }
95 return 0;
96 }
97
98 /**
99 * Entry point for fuzzing. Works by placing the data
100 * into two known symbols, triggering an app-visible interrupt, and
101 * then letting the simulator run for a fixed amount of time (intended to be
102 * "long enough" to handle the event and reach a quiescent state
103 * again)
104 */
105 #if defined(CONFIG_BOARD_NATIVE_SIM)
106 NATIVE_SIMULATOR_IF /* We expose this function to the final runner link stage*/
107 #endif
LLVMFuzzerTestOneInput(const uint8_t * data,size_t sz)108 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz)
109 {
110 static bool runner_initialized;
111
112 if (!runner_initialized) {
113 nsi_init(0, NULL);
114 runner_initialized = true;
115 }
116
117 /* Provide the fuzz data to the embedded OS as an interrupt, with
118 * "DMA-like" data placed into native_fuzz_buf/sz
119 */
120 fuzz_buf = (void *)data;
121 fuzz_sz = sz;
122
123 hw_irq_ctrl_set_irq(CONFIG_ARCH_POSIX_FUZZ_IRQ);
124
125 /* Give the OS time to process whatever happened in that
126 * interrupt and reach an idle state.
127 */
128 nsi_exec_for(k_ticks_to_us_ceil64(CONFIG_ARCH_POSIX_FUZZ_TICKS));
129
130 return 0;
131 }
132