From dcf6b6bde805895ae130751549e779a94502ba58 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Tue, 27 Feb 2024 16:48:37 +0000 Subject: [PATCH] zephyr/wrapper.c: dereference NULL in POSIX for better k_panic() trace As discussed in the alternative approach https://github.com/zephyrproject-rtos/zephyr/pull/68494/, k_panic() in POSIX mode has various shortcomings that do not provide a useful trace. Useless pointers to signal handlers or other cleanup routines are printed instead. Leverage our already existing k_sys_fatal_error_handler() and dereference a NULL pointer there when in POSIX mode. This "fails fast" and provides a complete and relevant stack trace in CI when fuzzing or when using some other static analyzer. Example of how fuzzing failure #8832 would have looked like in CI results thanks to this commit: ``` ./build-fuzz/zephyr/zephyr.exe: Running 1 inputs 1 time(s) each. Running: ./rballoc_align_fuzz_crash *** Booting Zephyr OS build zephyr-v3.5.0-3971-ge07de4e0a167 *** [00:00:00.000,000] main: SOF on native_posix [00:00:00.000,000] main: SOF initialized @ WEST_TOPDIR/sof/zephyr/lib/alloc.c:391 [00:00:00.000,000] os: >>> ZEPHYR FATAL ERROR 4: Kernel panic [00:00:00.000,000] os: Current thread: 0x891f8a0 (unknown) [00:00:00.000,000] zephyr: Halting emulation AddressSanitizer:DEADLYSIGNAL ================================================================= ==1784402==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000 ==1784402==The signal is caused by a WRITE memory access. ==1784402==Hint: address points to the zero page. #0 0x829a77d in k_sys_fatal_error_handler zephyr/wrapper.c:352:19 #1 0x829b8c0 in rballoc_align zephyr/lib/alloc.c:391:3 #2 0x8281438 in buffer_alloc src/audio/buffer.c:58:16 #3 0x826a60a in buffer_new src/ipc/ipc-helper.c:48:11 #4 0x8262107 in ipc_buffer_new src/ipc/ipc3/helper.c:459:11 #5 0x825944d in ipc_glb_tplg_buffer_new src/ipc/ipc3/handler.c:1305:8 #6 0x8257036 in ipc_cmd src/ipc/ipc3/handler.c:1651:9 #7 0x8272e59 in ipc_platform_do_cmd src/platform/posix/ipc.c:162:2 #8 0x826a2ac in ipc_do_cmd src/ipc/ipc-common.c:328:9 #9 0x829b0ab in task_run zephyr/include/rtos/task.h:94:9 #10 0x829abd8 in edf_work_handler zephyr/edf_schedule.c:32:16 #11 0x83560f7 in work_queue_main zephyr/kernel/work.c:688:3 #12 0x82244c2 in z_thread_entry zephyr/lib/os/thread_entry.c:48:2 ``` Signed-off-by: Marc Herbert --- zephyr/wrapper.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c index e2fed0558a43..27e9a16c5b73 100644 --- a/zephyr/wrapper.c +++ b/zephyr/wrapper.c @@ -326,14 +326,32 @@ int poll_for_register_delay(uint32_t reg, uint32_t mask, return 0; } +/* Mutable, volatile and not static to escape optimizers and static + * analyzers. + */ +volatile int *_sof_fatal_null = NULL; + void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) { ARG_UNUSED(esf); + + /* flush and switch to immediate mode */ LOG_PANIC(); ipc_send_panic_notification(); +#if defined(CONFIG_ARCH_POSIX) || defined(CONFIG_ZEPHYR_POSIX) + LOG_ERR("Halting emulation"); + + /* In emulation we want to stop _immediately_ and print a useful stack + * trace; not a useless pointer to some signal handler or Zephyr + * cleanup routine. See Zephyr POSIX limitations discussed in: + * https://github.com/zephyrproject-rtos/zephyr/pull/68494 + */ + *_sof_fatal_null = 42; +#else LOG_ERR("Halting system"); +#endif k_fatal_halt(reason); }