diff --git a/scripts/fuzz.sh b/scripts/fuzz.sh index 07f9f1b59685..27b671e53a01 100755 --- a/scripts/fuzz.sh +++ b/scripts/fuzz.sh @@ -34,7 +34,7 @@ with the -b option. Simple wrapper around a libfuzzer test run, as much for documentation as direct use. The idea here is really simple: build -for the Zephyr "native_posix" board (which is a just a x86 +for the Zephyr "native_sim" board (which is a just a x86 executable for the build host, not an emulated device) and run the resulting zephyr.exe file. This specifies a "fuzz_corpus" directory to save the seeds that produce useful coverage output for use in @@ -124,7 +124,7 @@ main() (set -x # When passing conflicting -DVAR='VAL UE1' -DVAR='VAL UE2' to CMake, # the last 'VAL UE2' wins. Previous ones are silently ignored. - west build -d build-fuzz -b native_posix "$SOF_TOP"/app/ -- \ + west build -d build-fuzz -b native_sim "$SOF_TOP"/app/ -- \ "${fuzz_configs[@]}" "$@" ) diff --git a/src/platform/posix/fuzz.c b/src/platform/posix/fuzz.c index c2b02669b0b5..7b5e6b33da13 100644 --- a/src/platform/posix/fuzz.c +++ b/src/platform/posix/fuzz.c @@ -9,9 +9,9 @@ #include #include -/* Zephyr arch APIs, not in a header (native_sim has them though) */ -void posix_init(int argc, char *argv[]); -void posix_exec_for(uint64_t us); +/* Zephyr arch APIs, not in a header */ +void nsi_init(int argc, char *argv[]); +void nsi_exec_for(uint64_t us); const uint8_t *posix_fuzz_buf; size_t posix_fuzz_sz; @@ -28,7 +28,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) static bool runner_initialized; if (!runner_initialized) { - posix_init(0, NULL); + nsi_init(0, NULL); runner_initialized = true; } @@ -42,6 +42,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) /* Give the OS time to process whatever happened in that * interrupt and reach an idle state. */ - posix_exec_for(k_ticks_to_us_ceil64(CONFIG_ZEPHYR_POSIX_FUZZ_TICKS)); + nsi_exec_for(k_ticks_to_us_ceil64(CONFIG_ZEPHYR_POSIX_FUZZ_TICKS)); return 0; } diff --git a/src/platform/posix/posix.c b/src/platform/posix/posix.c index f8024cb0dcca..4bc9976e7268 100644 --- a/src/platform/posix/posix.c +++ b/src/platform/posix/posix.c @@ -33,6 +33,17 @@ __asm__(".globl _trace_ctx_start\n" ".globl _trace_ctx_end\n" "_trace_ctx_end:\n"); +/* Sort of a kluge: this is an app-provided symbol, Zephyr doesn't + * know about it. But it's the ENTRY POINT of the binary, so SOF + * doesn't ever reference or call it either. It therefore gets + * dropped by the initial link of zephyr.elf, so isn't present anymore + * in the final link vs. the native_sim runner to link vs. the + * framework code in libfuzzer. Stash its address meaninglessly just + * to be sure the symbol gets referenced. + */ +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz); +void *native_sim_ptr_save; + struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) { return NULL; @@ -81,6 +92,8 @@ int platform_init(struct sof *sof) posix_dma_init(sof); ipc_init(sof); + native_sim_ptr_save = LLVMFuzzerTestOneInput; + return 0; } diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index e691dff9d880..25fc607f3321 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -401,6 +401,14 @@ zephyr_library_sources_ifdef(CONFIG_ZEPHYR_POSIX ${SOF_PLATFORM_PATH}/posix/fuzz.c ) +# When building the fuzzer, the LLVMFuzzerTestOneInput() entry point +# (which is defined here in the app) must be exposed to the secondary +# native_sim "runner" linkage step, which normally hides all +# Zephyr-side symbols to protect against collisions. Somewhat opaque +# cmake interface to this, alas. +set_property(TARGET native_simulator APPEND PROPERTY + LOCALIZE_EXTRA_OPTIONS "--globalize-symbol=LLVMFuzzerTestOneInput") + zephyr_library_sources_ifdef(CONFIG_LIBRARY ${SOF_PLATFORM_PATH}/library/platform.c ${SOF_PLATFORM_PATH}/library/lib/dai.c