sandbox: add handler for exceptions
Add a handler for SIGILL, SIGBUS, SIGSEGV. When an exception occurs print the program counter and the loaded UEFI binaries and reset the system if CONFIG_SANDBOX_CRASH_RESET=y or exit to the OS otherwise. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
21f9075def
commit
b46f30a378
@ -51,6 +51,15 @@ config HOST_64BIT
|
||||
|
||||
endchoice
|
||||
|
||||
config SANDBOX_CRASH_RESET
|
||||
bool "Reset on crash"
|
||||
help
|
||||
If an illegal instruction or an illegal memory access occurs, the
|
||||
sandbox by default writes a crash dump and exits. If you set this
|
||||
flag, the sandbox is reset instead. This may be useful when running
|
||||
test suites like the UEFI self certification test which continue
|
||||
with the next test after a crash.
|
||||
|
||||
config SANDBOX_BITS_PER_LONG
|
||||
int
|
||||
default 32 if HOST_32BIT
|
||||
|
@ -3,6 +3,8 @@
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -15,11 +17,13 @@
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/compiler_attributes.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/getopt.h>
|
||||
@ -191,6 +195,42 @@ static void os_sigint_handler(int sig)
|
||||
raise(SIGINT);
|
||||
}
|
||||
|
||||
static void os_signal_handler(int sig, siginfo_t *info, void *con)
|
||||
{
|
||||
ucontext_t __maybe_unused *context = con;
|
||||
unsigned long pc;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
pc = context->uc_mcontext.gregs[REG_RIP];
|
||||
#elif defined(__aarch64__)
|
||||
pc = context->uc_mcontext.pc;
|
||||
#elif defined(__riscv)
|
||||
pc = context->uc_mcontext.__gregs[REG_PC];
|
||||
#else
|
||||
const char msg[] =
|
||||
"\nUnsupported architecture, cannot read program counter\n";
|
||||
|
||||
os_write(1, msg, sizeof(msg));
|
||||
pc = 0;
|
||||
#endif
|
||||
|
||||
os_signal_action(sig, pc);
|
||||
}
|
||||
|
||||
int os_setup_signal_handlers(void)
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_sigaction = os_signal_handler;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_SIGINFO | SA_NODEFER;
|
||||
if (sigaction(SIGILL, &act, NULL) ||
|
||||
sigaction(SIGBUS, &act, NULL) ||
|
||||
sigaction(SIGSEGV, &act, NULL))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put tty into raw mode so <tab> and <ctrl+c> work */
|
||||
void os_tty_raw(int fd, bool allow_sigs)
|
||||
{
|
||||
|
@ -451,6 +451,10 @@ int main(int argc, char *argv[])
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = os_setup_signal_handlers();
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
|
||||
gd->malloc_base = CONFIG_MALLOC_F_ADDR;
|
||||
#endif
|
||||
|
@ -6,7 +6,13 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <efi_loader.h>
|
||||
#include <irq_func.h>
|
||||
#include <os.h>
|
||||
#include <asm-generic/signal.h>
|
||||
#include <asm/u-boot-sandbox.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int interrupt_init(void)
|
||||
{
|
||||
@ -21,3 +27,32 @@ int disable_interrupts(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void os_signal_action(int sig, unsigned long pc)
|
||||
{
|
||||
efi_restore_gd();
|
||||
|
||||
switch (sig) {
|
||||
case SIGILL:
|
||||
printf("\nIllegal instruction\n");
|
||||
break;
|
||||
case SIGBUS:
|
||||
printf("\nBus error\n");
|
||||
break;
|
||||
case SIGSEGV:
|
||||
printf("\nSegmentation violation\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("pc = 0x%lx, ", pc);
|
||||
printf("pc_reloc = 0x%lx\n\n", pc - gd->reloc_off);
|
||||
efi_print_image_infos((void *)pc);
|
||||
|
||||
if (IS_ENABLED(CONFIG_SANDBOX_CRASH_RESET)) {
|
||||
printf("resetting ...\n\n");
|
||||
sandbox_reset();
|
||||
} else {
|
||||
sandbox_exit();
|
||||
}
|
||||
}
|
||||
|
17
include/os.h
17
include/os.h
@ -407,4 +407,21 @@ void *os_find_text_base(void);
|
||||
*/
|
||||
void os_relaunch(char *argv[]);
|
||||
|
||||
/**
|
||||
* os_setup_signal_handlers() - setup signal handlers
|
||||
*
|
||||
* Install signal handlers for SIGBUS and SIGSEGV.
|
||||
*
|
||||
* Return: 0 for success
|
||||
*/
|
||||
int os_setup_signal_handlers(void);
|
||||
|
||||
/**
|
||||
* os_signal_action() - handle a signal
|
||||
*
|
||||
* @sig: signal
|
||||
* @pc: program counter
|
||||
*/
|
||||
void os_signal_action(int sig, unsigned long pc);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user