sample fuzzer: Move fuzzer specific code to sample and fix for native_sim
Move the LLVM fuzzing specific code out of the board main file and into the sample. That way we avoid needing to duplicate it for native_sim and avoid having a very adhoc interface between the fuzzer test and runner code. Also ensure it works for native_sim and not just native_posix Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
This commit is contained in:
parent
09d554b769
commit
f5553004b0
3 changed files with 52 additions and 39 deletions
|
@ -178,6 +178,7 @@ endif()
|
||||||
|
|
||||||
if(CONFIG_ARCH_POSIX_LIBFUZZER)
|
if(CONFIG_ARCH_POSIX_LIBFUZZER)
|
||||||
list(APPEND LLVM_SANITIZERS "fuzzer")
|
list(APPEND LLVM_SANITIZERS "fuzzer")
|
||||||
|
target_compile_options(native_simulator INTERFACE "-DNSI_NO_MAIN=1")
|
||||||
if(NOT CONFIG_64BIT)
|
if(NOT CONFIG_64BIT)
|
||||||
# On i386, libfuzzer seems to dynamically relocate the binary, so
|
# On i386, libfuzzer seems to dynamically relocate the binary, so
|
||||||
# we need to emit PIC code. This limitation is undocumented and
|
# we need to emit PIC code. This limitation is undocumented and
|
||||||
|
|
|
@ -118,40 +118,4 @@ int main(int argc, char *argv[])
|
||||||
return 1; /* LCOV_EXCL_LINE */
|
return 1; /* LCOV_EXCL_LINE */
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* CONFIG_ARCH_POSIX_LIBFUZZER */
|
|
||||||
|
|
||||||
const uint8_t *posix_fuzz_buf;
|
|
||||||
size_t posix_fuzz_sz;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entry point for fuzzing (when enabled). Works by placing the data
|
|
||||||
* into two known symbols, triggering an app-visible interrupt, and
|
|
||||||
* then letting the OS 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 posix_initialized;
|
|
||||||
|
|
||||||
if (!posix_initialized) {
|
|
||||||
posix_init(0, NULL);
|
|
||||||
posix_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Provide the fuzz data to Zephyr as an interrupt, with
|
|
||||||
* "DMA-like" data placed into posix_fuzz_buf/sz
|
|
||||||
*/
|
|
||||||
posix_fuzz_buf = data;
|
|
||||||
posix_fuzz_sz = sz;
|
|
||||||
hw_irq_ctrl_set_irq(CONFIG_ARCH_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_ARCH_POSIX_FUZZ_TICKS));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,6 +4,19 @@
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zephyr/irq.h>
|
#include <zephyr/irq.h>
|
||||||
|
#include <irq_ctrl.h>
|
||||||
|
#if defined(CONFIG_BOARD_NATIVE_SIM)
|
||||||
|
#include <nsi_cpu_if.h>
|
||||||
|
#include <nsi_main_semipublic.h>
|
||||||
|
#elif defined(CONFIG_BOARD_NATIVE_POSIX)
|
||||||
|
/* Note: native_posix will be deprecated soon */
|
||||||
|
extern void posix_init(int argc, char *argv[]);
|
||||||
|
extern void posix_exec_for(uint64_t us);
|
||||||
|
#define nsi_init posix_init
|
||||||
|
#define nsi_exec_for posix_exec_for
|
||||||
|
#else
|
||||||
|
#error "Platform not supported"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Fuzz testing is coverage-based, so we want to hide a failure case
|
/* Fuzz testing is coverage-based, so we want to hide a failure case
|
||||||
* (a write through a null pointer in this case) down inside a call
|
* (a write through a null pointer in this case) down inside a call
|
||||||
|
@ -49,8 +62,8 @@ GEN_CHECK(5, 6)
|
||||||
GEN_CHECK(6, 0)
|
GEN_CHECK(6, 0)
|
||||||
|
|
||||||
/* Fuzz input received from LLVM via "interrupt" */
|
/* Fuzz input received from LLVM via "interrupt" */
|
||||||
extern const uint8_t *posix_fuzz_buf;
|
static const uint8_t *fuzz_buf;
|
||||||
extern size_t posix_fuzz_sz;
|
static size_t fuzz_sz;
|
||||||
|
|
||||||
K_SEM_DEFINE(fuzz_sem, 0, K_SEM_MAX_LIMIT);
|
K_SEM_DEFINE(fuzz_sem, 0, K_SEM_MAX_LIMIT);
|
||||||
|
|
||||||
|
@ -76,7 +89,42 @@ int main(void)
|
||||||
/* Execute the fuzz case we got from LLVM and passed
|
/* Execute the fuzz case we got from LLVM and passed
|
||||||
* through an interrupt to this thread.
|
* through an interrupt to this thread.
|
||||||
*/
|
*/
|
||||||
check0(posix_fuzz_buf, posix_fuzz_sz);
|
check0(fuzz_buf, fuzz_sz);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_BOARD_NATIVE_SIM)
|
||||||
|
NATIVE_SIMULATOR_IF /* We expose this function to the final runner link stage*/
|
||||||
|
#endif
|
||||||
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz)
|
||||||
|
{
|
||||||
|
static bool runner_initialized;
|
||||||
|
|
||||||
|
if (!runner_initialized) {
|
||||||
|
nsi_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
|
||||||
|
*/
|
||||||
|
fuzz_buf = (void *)data;
|
||||||
|
fuzz_sz = sz;
|
||||||
|
|
||||||
|
hw_irq_ctrl_set_irq(CONFIG_ARCH_POSIX_FUZZ_IRQ);
|
||||||
|
|
||||||
|
/* Give the OS time to process whatever happened in that
|
||||||
|
* interrupt and reach an idle state.
|
||||||
|
*/
|
||||||
|
nsi_exec_for(k_ticks_to_us_ceil64(CONFIG_ARCH_POSIX_FUZZ_TICKS));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue