mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
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
5 changed files with 105 additions and 0 deletions
|
@ -51,6 +51,15 @@ config HOST_64BIT
|
||||||
|
|
||||||
endchoice
|
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
|
config SANDBOX_BITS_PER_LONG
|
||||||
int
|
int
|
||||||
default 32 if HOST_32BIT
|
default 32 if HOST_32BIT
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* Copyright (c) 2011 The Chromium OS Authors.
|
* Copyright (c) 2011 The Chromium OS Authors.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -15,11 +17,13 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <ucontext.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <linux/compiler_attributes.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#include <asm/getopt.h>
|
#include <asm/getopt.h>
|
||||||
|
@ -191,6 +195,42 @@ static void os_sigint_handler(int sig)
|
||||||
raise(SIGINT);
|
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 */
|
/* Put tty into raw mode so <tab> and <ctrl+c> work */
|
||||||
void os_tty_raw(int fd, bool allow_sigs)
|
void os_tty_raw(int fd, bool allow_sigs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -451,6 +451,10 @@ int main(int argc, char *argv[])
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
ret = os_setup_signal_handlers();
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
|
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
|
||||||
gd->malloc_base = CONFIG_MALLOC_F_ADDR;
|
gd->malloc_base = CONFIG_MALLOC_F_ADDR;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,7 +6,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <efi_loader.h>
|
||||||
#include <irq_func.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)
|
int interrupt_init(void)
|
||||||
{
|
{
|
||||||
|
@ -21,3 +27,32 @@ int disable_interrupts(void)
|
||||||
{
|
{
|
||||||
return 0;
|
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[]);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue