
From: Simon Glass <sjg@chromium.org> Normally sandbox includes a main() function so that it can be started correctly. When fuzzing is enabled, main() is not required. When sandbox is built as a library, the main program will be somewhere else so must not be in the library. Split the main() function out into a new main.c file. Split the fuzzing code into a new fuzz.c file. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/sandbox/cpu/Makefile | 7 +- arch/sandbox/cpu/fuzz.c | 81 +++++++++++++++++++++++ arch/sandbox/cpu/main.c | 11 +++ arch/sandbox/cpu/os.c | 74 --------------------- arch/sandbox/cpu/start.c | 1 + arch/sandbox/include/asm/u-boot-sandbox.h | 5 +- 6 files changed, 102 insertions(+), 77 deletions(-) create mode 100644 arch/sandbox/cpu/fuzz.c create mode 100644 arch/sandbox/cpu/main.c diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index 03cdf2ae0f1..35f853776f7 100644 --- a/arch/sandbox/cpu/Makefile +++ b/arch/sandbox/cpu/Makefile @@ -6,13 +6,18 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y := cache.o cpu.o mem.o state.o os.o +ifdef CONFIG_FUZZ +obj-y += fuzz.o +else +obj-y += main.o +endif extra-y := start.o extra-$(CONFIG_SANDBOX_SDL) += sdl.o obj-$(CONFIG_XPL_BUILD) += spl.o obj-$(CONFIG_ETH_SANDBOX_RAW) += eth-raw-os.o # Compile these files with system headers -CFLAGS_USE_SYSHDRS := eth-raw-os.o os.o sdl.o +CFLAGS_USE_SYSHDRS := eth-raw-os.o fuzz.o main.o os.o sdl.o # sdl.c fails to build with -fshort-wchar using musl cmd_cc_sdl.o = $(CC) $(filter-out -nostdinc -fshort-wchar, \ diff --git a/arch/sandbox/cpu/fuzz.c b/arch/sandbox/cpu/fuzz.c new file mode 100644 index 00000000000..f017c3a33ad --- /dev/null +++ b/arch/sandbox/cpu/fuzz.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022 Google, Inc. + * Written by Andrew Scull <ascull@google.com> + */ + +#include <errno.h> +#include <pthread.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +#include <os.h> +#include <asm/fuzzing_engine.h> +#include <asm/u-boot-sandbox.h> + +static void *fuzzer_thread(void *ptr) +{ + char cmd[64]; + char *argv[5] = {"./u-boot", "-T", "-c", cmd, NULL}; + const char *fuzz_test; + + /* Find which test to run from an environment variable. */ + fuzz_test = getenv("UBOOT_SB_FUZZ_TEST"); + if (!fuzz_test) + os_abort(); + + snprintf(cmd, sizeof(cmd), "fuzz %s", fuzz_test); + + sandbox_main(4, argv); + os_abort(); + return NULL; +} + +static bool fuzzer_initialized; +static pthread_mutex_t fuzzer_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t fuzzer_cond = PTHREAD_COND_INITIALIZER; +static const uint8_t *fuzzer_data; +static size_t fuzzer_size; + +int sandbox_fuzzing_engine_get_input(const uint8_t **data, size_t *size) +{ + if (!fuzzer_initialized) + return -ENOSYS; + + /* Tell the main thread we need new inputs then wait for them. */ + pthread_mutex_lock(&fuzzer_mutex); + pthread_cond_signal(&fuzzer_cond); + pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex); + *data = fuzzer_data; + *size = fuzzer_size; + pthread_mutex_unlock(&fuzzer_mutex); + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + static pthread_t tid; + + pthread_mutex_lock(&fuzzer_mutex); + + /* Initialize the sandbox on another thread. */ + if (!fuzzer_initialized) { + fuzzer_initialized = true; + if (pthread_create(&tid, NULL, fuzzer_thread, NULL)) + os_abort(); + pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex); + } + + /* Hand over the input. */ + fuzzer_data = data; + fuzzer_size = size; + pthread_cond_signal(&fuzzer_cond); + + /* Wait for the inputs to be finished with. */ + pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex); + pthread_mutex_unlock(&fuzzer_mutex); + + return 0; +} diff --git a/arch/sandbox/cpu/main.c b/arch/sandbox/cpu/main.c new file mode 100644 index 00000000000..617295d142c --- /dev/null +++ b/arch/sandbox/cpu/main.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2011 The Chromium OS Authors. + */ + +#include <asm/u-boot-sandbox.h> + +int main(int argc, char *argv[]) +{ + return sandbox_main(argc, argv); +} diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index d1632e6af69..1c4e23cb4eb 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -10,7 +10,6 @@ #include <fcntl.h> #include <pthread.h> #include <getopt.h> -#include <setjmp.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -28,7 +27,6 @@ #include <linux/compiler_attributes.h> #include <linux/types.h> -#include <asm/fuzzing_engine.h> #include <asm/getopt.h> #include <asm/sections.h> #include <asm/state.h> @@ -1151,75 +1149,3 @@ void os_relaunch(char *argv[]) execv(argv[0], argv); os_exit(1); } - -#ifdef CONFIG_FUZZ -static void *fuzzer_thread(void * ptr) -{ - char cmd[64]; - char *argv[5] = {"./u-boot", "-T", "-c", cmd, NULL}; - const char *fuzz_test; - - /* Find which test to run from an environment variable. */ - fuzz_test = getenv("UBOOT_SB_FUZZ_TEST"); - if (!fuzz_test) - os_abort(); - - snprintf(cmd, sizeof(cmd), "fuzz %s", fuzz_test); - - sandbox_main(4, argv); - os_abort(); - return NULL; -} - -static bool fuzzer_initialized = false; -static pthread_mutex_t fuzzer_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t fuzzer_cond = PTHREAD_COND_INITIALIZER; -static const uint8_t *fuzzer_data; -static size_t fuzzer_size; - -int sandbox_fuzzing_engine_get_input(const uint8_t **data, size_t *size) -{ - if (!fuzzer_initialized) - return -ENOSYS; - - /* Tell the main thread we need new inputs then wait for them. */ - pthread_mutex_lock(&fuzzer_mutex); - pthread_cond_signal(&fuzzer_cond); - pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex); - *data = fuzzer_data; - *size = fuzzer_size; - pthread_mutex_unlock(&fuzzer_mutex); - return 0; -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - static pthread_t tid; - - pthread_mutex_lock(&fuzzer_mutex); - - /* Initialize the sandbox on another thread. */ - if (!fuzzer_initialized) { - fuzzer_initialized = true; - if (pthread_create(&tid, NULL, fuzzer_thread, NULL)) - os_abort(); - pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex); - } - - /* Hand over the input. */ - fuzzer_data = data; - fuzzer_size = size; - pthread_cond_signal(&fuzzer_cond); - - /* Wait for the inputs to be finished with. */ - pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex); - pthread_mutex_unlock(&fuzzer_mutex); - - return 0; -} -#else -int main(int argc, char *argv[]) -{ - return sandbox_main(argc, argv); -} -#endif diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 8ee12ed1500..40a3559d244 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -22,6 +22,7 @@ #include <asm/malloc.h> #include <asm/sections.h> #include <asm/state.h> +#include <asm/u-boot-sandbox.h> #include <dm/root.h> #include <linux/ctype.h> #include <linux/log2.h> diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h index 54f0d9832b1..001b00fe41e 100644 --- a/arch/sandbox/include/asm/u-boot-sandbox.h +++ b/arch/sandbox/include/asm/u-boot-sandbox.h @@ -46,8 +46,9 @@ void __noreturn sandbox_exit(void); * * @argc: the number of arguments passed to the program * @argv: array of argc+1 pointers, of which the last one is null - - * This starts sandbox. It does not return unless something goes wrong. + * + * This calls sandbox_init(), then board_init_f/r(). It does not return unless + * something goes wrong. * * Return: 1 on error */ -- 2.43.0