diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 762bedc7931d..5e675315d2a3 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -55,6 +55,28 @@ config ZEPHYR_POSIX and thus able to instrument and test the whole OS environment. +if ZEPHYR_POSIX && ARCH_POSIX_LIBFUZZER + +config ZEPHYR_POSIX_FUZZ_IRQ + int "OS interrupt via which to deliver fuzz cases" + default 31 + help + New fuzz cases are delivered to Zephyr via interrupts. The + IRQ should be otherwise unused, but can be any value desired + by the app. + +config ZEPHYR_POSIX_FUZZ_TICKS + int "Ticks to allow for fuzz case processing" + default 2 + help + Fuzz interrupts are delivered, from the perspective of the + OS, at a steady cadence in simulated time. In general most + apps won't require much time to reach an idle state + following a unit-test style case, so the default is short to + prevent interaction with regular timer workloads. + +endif # ZEPHYR_POSIX && ARCH_POSIX_LIBFUZZER + config IMX8 bool "Build for NXP i.MX8" select XT_HAVE_RESET_VECTOR_ROM diff --git a/src/platform/posix/fuzz.c b/src/platform/posix/fuzz.c new file mode 100644 index 000000000000..c2b02669b0b5 --- /dev/null +++ b/src/platform/posix/fuzz.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2024 Google LLC. All rights reserved. +// Author: Andy Ross + +#include +#include +#include + +#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); + +const uint8_t *posix_fuzz_buf; +size_t posix_fuzz_sz; + +/** + * Entry point for fuzzing. Works by placing the data + * into two known symbols, triggering an app-visible interrupt, and + * then letting the simulator run for a fixed amount of time (intended to be + * "long enough" to handle the event and reach a quiescent state + * again) + */ +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) +{ + static bool runner_initialized; + + if (!runner_initialized) { + posix_init(0, NULL); + runner_initialized = true; + } + + /* Provide the fuzz data to the embedded OS as an interrupt, with + * "DMA-like" data placed into native_fuzz_buf/sz + */ + posix_fuzz_buf = (void *)data; + posix_fuzz_sz = sz; + hw_irq_ctrl_set_irq(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ); + + /* 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)); + return 0; +} diff --git a/src/platform/posix/ipc.c b/src/platform/posix/ipc.c index d5dbcf09e040..ceaa36fecd38 100644 --- a/src/platform/posix/ipc.c +++ b/src/platform/posix/ipc.c @@ -43,7 +43,7 @@ static uint8_t fuzz_in_sz; // synchronously as another message after receipt of "complete_cmd()" // from the SOF engine, etc... Eventually we'll receive another fuzz // input after some amount of simulated time has passed (c.f. -// CONFIG_ARCH_POSIX_FUZZ_TICKS) +// CONFIG_ZEPHYR_POSIX_FUZZ_TICKS) static void fuzz_isr(const void *arg) { size_t rem, i, n = MIN(posix_fuzz_sz, sizeof(fuzz_in) - fuzz_in_sz); @@ -179,7 +179,7 @@ void ipc_platform_complete_cmd(struct ipc *ipc) if (fuzz_in_sz > 0) { posix_fuzz_sz = 0; - posix_sw_set_pending_IRQ(CONFIG_ARCH_POSIX_FUZZ_IRQ); + posix_sw_set_pending_IRQ(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ); } } @@ -203,8 +203,8 @@ void ipc_platform_send_msg_direct(const struct ipc_msg *msg) int platform_ipc_init(struct ipc *ipc) { - IRQ_CONNECT(CONFIG_ARCH_POSIX_FUZZ_IRQ, 0, fuzz_isr, NULL, 0); - irq_enable(CONFIG_ARCH_POSIX_FUZZ_IRQ); + IRQ_CONNECT(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ, 0, fuzz_isr, NULL, 0); + irq_enable(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ); global_ipc = ipc; schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid), diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index e6889be1187b..954c5f1ac63d 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -335,6 +335,7 @@ zephyr_library_sources_ifdef(CONFIG_ZEPHYR_POSIX ${SOF_PLATFORM_PATH}/posix/dai.c ${SOF_PLATFORM_PATH}/posix/ipc.c ${SOF_PLATFORM_PATH}/posix/posix.c + ${SOF_PLATFORM_PATH}/posix/fuzz.c ${SOF_PLATFORM_PATH}/posix/base_fw_platform.c )