mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-15 20:19:23 +00:00
refactor(core): adjust system api for syscall verifier
[no changelog]
This commit is contained in:
parent
be59a09a4c
commit
93af056c13
@ -1,27 +1,29 @@
|
||||
mod ffi {
|
||||
extern "C" {
|
||||
// error_handling.h
|
||||
pub fn error_shutdown(msg: *const cty::c_char) -> !;
|
||||
// system.h
|
||||
pub fn system_exit_error_ex(
|
||||
title: *const cty::c_char,
|
||||
title_len: usize,
|
||||
message: *const cty::c_char,
|
||||
message_len: usize,
|
||||
footer: *const cty::c_char,
|
||||
footer_len: usize,
|
||||
) -> !;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_shutdown(msg: &str) -> ! {
|
||||
const MAX_LEN: usize = 63;
|
||||
let mut buffer: [u8; MAX_LEN + 1] = [0; MAX_LEN + 1];
|
||||
|
||||
// Copy the message to the buffer
|
||||
let msg_bytes = msg.as_bytes();
|
||||
let len = if msg_bytes.len() < MAX_LEN {
|
||||
msg_bytes.len()
|
||||
} else {
|
||||
MAX_LEN
|
||||
};
|
||||
buffer[..len].copy_from_slice(&msg_bytes[..len]);
|
||||
|
||||
unsafe {
|
||||
// SAFETY: `buffer` is a valid null-terminated string
|
||||
// and the function never returns.
|
||||
ffi::error_shutdown(buffer.as_ptr() as *const cty::c_char);
|
||||
// SAFETY: we pass a valid string to the C function
|
||||
// and the function does not return.
|
||||
ffi::system_exit_error_ex(
|
||||
core::ptr::null(),
|
||||
0,
|
||||
msg.as_ptr() as *const cty::c_char,
|
||||
msg.len(),
|
||||
core::ptr::null(),
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,17 +76,23 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
|
||||
case SYSCALL_SYSTEM_EXIT_ERROR: {
|
||||
systask_t *task = systask_active();
|
||||
const char *title = (const char *)args[0];
|
||||
const char *message = (const char *)args[1];
|
||||
const char *footer = (const char *)args[2];
|
||||
systask_exit_error(task, title, message, footer);
|
||||
size_t title_len = (size_t)args[1];
|
||||
const char *message = (const char *)args[2];
|
||||
size_t message_len = (size_t)args[3];
|
||||
const char *footer = (const char *)args[4];
|
||||
size_t footer_len = (size_t)args[5];
|
||||
systask_exit_error(task, title, title_len, message, message_len, footer,
|
||||
footer_len);
|
||||
} break;
|
||||
|
||||
case SYSCALL_SYSTEM_EXIT_FATAL: {
|
||||
systask_t *task = systask_active();
|
||||
const char *message = (const char *)args[0];
|
||||
const char *file = (const char *)args[1];
|
||||
int line = (int)args[2];
|
||||
systask_exit_fatal(task, message, file, line);
|
||||
size_t message_len = (size_t)args[1];
|
||||
const char *file = (const char *)args[2];
|
||||
size_t file_len = (size_t)args[3];
|
||||
int line = (int)args[4];
|
||||
systask_exit_fatal(task, message, message_len, file, file_len, line);
|
||||
} break;
|
||||
|
||||
case SYSCALL_SYSTICK_CYCLES: {
|
||||
|
@ -33,17 +33,19 @@ void system_exit(int exit_code) {
|
||||
;
|
||||
}
|
||||
|
||||
void system_exit_error(const char *title, const char *message,
|
||||
const char *footer) {
|
||||
syscall_invoke3((uint32_t)title, (uint32_t)message, (uint32_t)footer,
|
||||
SYSCALL_SYSTEM_EXIT_ERROR);
|
||||
void system_exit_error_ex(const char *title, size_t title_len,
|
||||
const char *message, size_t message_len,
|
||||
const char *footer, size_t footer_len) {
|
||||
syscall_invoke6((uint32_t)title, title_len, (uint32_t)message, message_len,
|
||||
(uint32_t)footer, footer_len, SYSCALL_SYSTEM_EXIT_ERROR);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void system_exit_fatal(const char *message, const char *file, int line) {
|
||||
syscall_invoke3((uint32_t)message, (uint32_t)file, line,
|
||||
SYSCALL_SYSTEM_EXIT_FATAL);
|
||||
void system_exit_fatal_ex(const char *message, size_t message_len,
|
||||
const char *file, size_t file_len, int line) {
|
||||
syscall_invoke5((uint32_t)message, message_len, (uint32_t)file, file_len,
|
||||
line, SYSCALL_SYSTEM_EXIT_FATAL);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "bootutils.h"
|
||||
#include "common.h"
|
||||
#include "irq.h"
|
||||
#include "mpu.h"
|
||||
#include "syscall.h"
|
||||
@ -234,8 +235,9 @@ void systask_exit(systask_t* task, int exit_code) {
|
||||
systask_kill(task);
|
||||
}
|
||||
|
||||
void systask_exit_error(systask_t* task, const char* title, const char* message,
|
||||
const char* footer) {
|
||||
void systask_exit_error(systask_t* task, const char* title, size_t title_len,
|
||||
const char* message, size_t message_len,
|
||||
const char* footer, size_t footer_len) {
|
||||
systask_scheduler_t* scheduler = &g_systask_scheduler;
|
||||
|
||||
if (task == NULL) {
|
||||
@ -250,21 +252,25 @@ void systask_exit_error(systask_t* task, const char* title, const char* message,
|
||||
pminfo->privileged = (task == &scheduler->kernel_task);
|
||||
|
||||
if (title != NULL) {
|
||||
strncpy(pminfo->error.title, title, sizeof(pminfo->error.title) - 1);
|
||||
size_t len = MIN(title_len, sizeof(pminfo->error.title) - 1);
|
||||
strncpy(pminfo->error.title, title, len);
|
||||
}
|
||||
|
||||
if (message != NULL) {
|
||||
strncpy(pminfo->error.message, message, sizeof(pminfo->error.message) - 1);
|
||||
size_t len = MIN(message_len, sizeof(pminfo->error.message) - 1);
|
||||
strncpy(pminfo->error.message, message, len);
|
||||
}
|
||||
|
||||
if (footer != NULL) {
|
||||
strncpy(pminfo->error.footer, footer, sizeof(pminfo->error.footer) - 1);
|
||||
size_t len = MIN(footer_len, sizeof(pminfo->error.footer) - 1);
|
||||
strncpy(pminfo->error.footer, footer, len);
|
||||
}
|
||||
|
||||
systask_kill(task);
|
||||
}
|
||||
|
||||
void systask_exit_fatal(systask_t* task, const char* message, const char* file,
|
||||
void systask_exit_fatal(systask_t* task, const char* message,
|
||||
size_t message_len, const char* file, size_t file_len,
|
||||
int line) {
|
||||
systask_scheduler_t* scheduler = &g_systask_scheduler;
|
||||
|
||||
@ -280,11 +286,13 @@ void systask_exit_fatal(systask_t* task, const char* message, const char* file,
|
||||
pminfo->privileged = (task == &scheduler->kernel_task);
|
||||
|
||||
if (message != NULL) {
|
||||
strncpy(pminfo->fatal.expr, message, sizeof(pminfo->fatal.expr) - 1);
|
||||
size_t len = MIN(message_len, sizeof(pminfo->fatal.expr) - 1);
|
||||
strncpy(pminfo->fatal.expr, message, len);
|
||||
}
|
||||
|
||||
if (file != NULL) {
|
||||
strncpy(pminfo->fatal.file, file, sizeof(pminfo->fatal.file) - 1);
|
||||
size_t len = MIN(file_len, sizeof(pminfo->fatal.file) - 1);
|
||||
strncpy(pminfo->fatal.file, file, len);
|
||||
}
|
||||
|
||||
pminfo->fatal.line = line;
|
||||
|
@ -19,13 +19,19 @@
|
||||
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "system.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "bootutils.h"
|
||||
#include "mpu.h"
|
||||
#include "systask.h"
|
||||
#include "system.h"
|
||||
#include "systick.h"
|
||||
#include "systimer.h"
|
||||
|
||||
#ifndef HardFault_IRQn
|
||||
#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32429xx.h
|
||||
#endif
|
||||
|
||||
#ifdef KERNEL_MODE
|
||||
|
||||
void system_init(systask_error_handler_t error_handler) {
|
||||
@ -38,61 +44,18 @@ void system_init(systask_error_handler_t error_handler) {
|
||||
|
||||
void system_exit(int exitcode) { systask_exit(NULL, exitcode); }
|
||||
|
||||
void system_exit_error(const char* title, const char* message,
|
||||
const char* footer) {
|
||||
systask_exit_error(NULL, title, message, footer);
|
||||
void system_exit_error_ex(const char* title, size_t title_len,
|
||||
const char* message, size_t message_len,
|
||||
const char* footer, size_t footer_len) {
|
||||
systask_exit_error(NULL, title, title_len, message, message_len, footer,
|
||||
footer_len);
|
||||
}
|
||||
|
||||
void system_exit_fatal(const char* message, const char* file, int line) {
|
||||
systask_exit_fatal(NULL, message, file, line);
|
||||
void system_exit_fatal_ex(const char* message, size_t message_len,
|
||||
const char* file, size_t file_len, int line) {
|
||||
systask_exit_fatal(NULL, message, message_len, file, file_len, line);
|
||||
}
|
||||
|
||||
#endif // KERNEL_MODE
|
||||
|
||||
#ifndef HardFault_IRQn
|
||||
#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32429xx.h
|
||||
#endif
|
||||
|
||||
#ifdef STM32U5
|
||||
const char* system_fault_message(const system_fault_t* fault) {
|
||||
switch (fault->irqn) {
|
||||
case HardFault_IRQn:
|
||||
return "(HF)";
|
||||
case MemoryManagement_IRQn:
|
||||
return "(MM)";
|
||||
case BusFault_IRQn:
|
||||
return "(BF)";
|
||||
case UsageFault_IRQn:
|
||||
return (fault->cfsr & SCB_CFSR_STKOF_Msk) ? "(SO)" : "(UF)";
|
||||
case SecureFault_IRQn:
|
||||
return "(SF)";
|
||||
case GTZC_IRQn:
|
||||
return "(IA)";
|
||||
case NonMaskableInt_IRQn:
|
||||
return "(CS)";
|
||||
default:
|
||||
return "(FAULT)";
|
||||
}
|
||||
}
|
||||
#else // STM32U5
|
||||
const char* system_fault_message(const system_fault_t* fault) {
|
||||
switch (fault->irqn) {
|
||||
case HardFault_IRQn:
|
||||
return "(HF)";
|
||||
case MemoryManagement_IRQn:
|
||||
return (fault->sp < fault->sp_lim) ? "(SO)" : "(MM)";
|
||||
case BusFault_IRQn:
|
||||
return "(BF)";
|
||||
case UsageFault_IRQn:
|
||||
return "(UF)";
|
||||
case NonMaskableInt_IRQn:
|
||||
return "(CS)";
|
||||
default:
|
||||
return "(FAULT)";
|
||||
}
|
||||
}
|
||||
#endif // STM32U5
|
||||
|
||||
__attribute__((used)) static void emergency_reset(void) {
|
||||
// TODO: reset peripherals (at least DMA, DMA2D)
|
||||
|
||||
@ -308,3 +271,60 @@ __attribute((naked, no_stack_protector)) void system_emergency_rescue(
|
||||
: // no clobber
|
||||
);
|
||||
}
|
||||
|
||||
#endif // KERNEL_MODE
|
||||
|
||||
#ifdef STM32U5
|
||||
const char* system_fault_message(const system_fault_t* fault) {
|
||||
switch (fault->irqn) {
|
||||
case HardFault_IRQn:
|
||||
return "(HF)";
|
||||
case MemoryManagement_IRQn:
|
||||
return "(MM)";
|
||||
case BusFault_IRQn:
|
||||
return "(BF)";
|
||||
case UsageFault_IRQn:
|
||||
return (fault->cfsr & SCB_CFSR_STKOF_Msk) ? "(SO)" : "(UF)";
|
||||
case SecureFault_IRQn:
|
||||
return "(SF)";
|
||||
case GTZC_IRQn:
|
||||
return "(IA)";
|
||||
case NonMaskableInt_IRQn:
|
||||
return "(CS)";
|
||||
default:
|
||||
return "(FAULT)";
|
||||
}
|
||||
}
|
||||
#else // STM32U5
|
||||
const char* system_fault_message(const system_fault_t* fault) {
|
||||
switch (fault->irqn) {
|
||||
case HardFault_IRQn:
|
||||
return "(HF)";
|
||||
case MemoryManagement_IRQn:
|
||||
return (fault->sp < fault->sp_lim) ? "(SO)" : "(MM)";
|
||||
case BusFault_IRQn:
|
||||
return "(BF)";
|
||||
case UsageFault_IRQn:
|
||||
return "(UF)";
|
||||
case NonMaskableInt_IRQn:
|
||||
return "(CS)";
|
||||
default:
|
||||
return "(FAULT)";
|
||||
}
|
||||
}
|
||||
#endif // STM32U5
|
||||
|
||||
void system_exit_error(const char* title, const char* message,
|
||||
const char* footer) {
|
||||
size_t title_len = title != NULL ? strlen(title) : 0;
|
||||
size_t message_len = message != NULL ? strlen(message) : 0;
|
||||
size_t footer_len = footer != NULL ? strlen(footer) : 0;
|
||||
system_exit_error_ex(title, title_len, message, message_len, footer,
|
||||
footer_len);
|
||||
}
|
||||
|
||||
void system_exit_fatal(const char* message, const char* file, int line) {
|
||||
size_t message_len = message != NULL ? strlen(message) : 0;
|
||||
size_t file_len = file != NULL ? strlen(file) : 0;
|
||||
system_exit_fatal_ex(message, message_len, file, file_len, line);
|
||||
}
|
||||
|
@ -168,13 +168,15 @@ void systask_exit(systask_t* task, int exit_code);
|
||||
// Terminates the task with an error message
|
||||
//
|
||||
// (see `systask_exit()` for more details)
|
||||
void systask_exit_error(systask_t* task, const char* title, const char* message,
|
||||
const char* footer);
|
||||
void systask_exit_error(systask_t* task, const char* title, size_t title_len,
|
||||
const char* message, size_t message_len,
|
||||
const char* footer, size_t footer_len);
|
||||
|
||||
// Terminates the task with a fatal error message
|
||||
//
|
||||
// (see `systask_exit()` for more details)
|
||||
void systask_exit_fatal(systask_t* task, const char* message, const char* file,
|
||||
void systask_exit_fatal(systask_t* task, const char* message,
|
||||
size_t message_len, const char* file, size_t file_len,
|
||||
int line);
|
||||
|
||||
#endif // KERNEL_MODE
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include <systask.h>
|
||||
|
||||
#ifdef KERNEL_MODE
|
||||
|
||||
// Initializes the fundamental system services
|
||||
// (MPU, SysTick, systimer and task scheduler).
|
||||
//
|
||||
@ -29,27 +31,6 @@
|
||||
// with an error
|
||||
void system_init(systask_error_handler_t error_handler);
|
||||
|
||||
// Terminates the current task normally with the given exit code.
|
||||
//
|
||||
// If the current task is the kernel task, the error handler is called with the
|
||||
// postmortem information. If the task is not the kernel task, the task is
|
||||
// terminated immediately and the kernel task is scheduled.
|
||||
void system_exit(int exitcode);
|
||||
|
||||
// Terminates the current task with an error message.
|
||||
//
|
||||
// See the notes for `system_exit` regarding the behavior of the error handler
|
||||
void system_exit_error(const char* title, const char* message,
|
||||
const char* footer);
|
||||
|
||||
// Terminates the current task with a fatal error message.
|
||||
//
|
||||
// See the notes for `system_exit` regarding the behavior of the error handler
|
||||
void system_exit_fatal(const char* message, const char* file, int line);
|
||||
|
||||
// Returns string representation of the system fault.
|
||||
const char* system_fault_message(const system_fault_t* fault);
|
||||
|
||||
// Calls the error handler in the emergency mode.
|
||||
//
|
||||
// This function is called when the system encounters a critical error
|
||||
@ -65,4 +46,36 @@ const char* system_fault_message(const system_fault_t* fault);
|
||||
__attribute__((noreturn)) void system_emergency_rescue(
|
||||
systask_error_handler_t error_handler, const systask_postmortem_t* pminfo);
|
||||
|
||||
#endif // KERNEL_MODE
|
||||
|
||||
// Terminates the current task normally with the given exit code.
|
||||
//
|
||||
// If the current task is the kernel task, the error handler is called with the
|
||||
// postmortem information. If the task is not the kernel task, the task is
|
||||
// terminated immediately and the kernel task is scheduled.
|
||||
void system_exit(int exitcode);
|
||||
|
||||
// Terminates the current task with an error message.
|
||||
//
|
||||
// See the notes for `system_exit` regarding the behavior of the error handler
|
||||
void system_exit_error(const char* title, const char* message,
|
||||
const char* footer);
|
||||
|
||||
// Like `system_exit_error`, but with explicit lengths for the strings.
|
||||
void system_exit_error_ex(const char* title, size_t title_len,
|
||||
const char* message, size_t message_len,
|
||||
const char* footer, size_t footer_len);
|
||||
|
||||
// Terminates the current task with a fatal error message.
|
||||
//
|
||||
// See the notes for `system_exit` regarding the behavior of the error handler
|
||||
void system_exit_fatal(const char* message, const char* file, int line);
|
||||
|
||||
// Like `system_exit_fatal`, but with explicit lengths for the strings.
|
||||
void system_exit_fatal_ex(const char* message, size_t message_len,
|
||||
const char* file, size_t file_len, int line);
|
||||
|
||||
// Returns string representation of the system fault.
|
||||
const char* system_fault_message(const system_fault_t* fault);
|
||||
|
||||
#endif // TREZORHAL_SYSTEM_H
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "bootutils.h"
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
#include "systick.h"
|
||||
#include "systimer.h"
|
||||
@ -49,18 +50,66 @@ void system_exit(int exitcode) {
|
||||
secure_shutdown();
|
||||
}
|
||||
|
||||
void system_exit_error(const char* title, const char* message,
|
||||
const char* footer) {
|
||||
void system_exit_error_ex(const char* title, size_t title_len,
|
||||
const char* message, size_t message_len,
|
||||
const char* footer, size_t footer_len) {
|
||||
fprintf(stderr, "ERROR: %s\n", message);
|
||||
fflush(stderr);
|
||||
|
||||
if (g_error_handler != NULL) {
|
||||
systask_postmortem_t pminfo = {0};
|
||||
size_t len;
|
||||
|
||||
pminfo.reason = TASK_TERM_REASON_ERROR;
|
||||
strncpy(pminfo.error.title, title, sizeof(pminfo.error.title) - 1);
|
||||
strncpy(pminfo.error.message, message, sizeof(pminfo.error.message) - 1);
|
||||
strncpy(pminfo.error.footer, footer, sizeof(pminfo.error.footer) - 1);
|
||||
|
||||
len = MIN(title_len, sizeof(pminfo.error.title) - 1);
|
||||
strncpy(pminfo.error.title, title, len);
|
||||
|
||||
len = MIN(message_len, sizeof(pminfo.error.message) - 1);
|
||||
strncpy(pminfo.error.message, message, len);
|
||||
|
||||
len = MIN(footer_len, sizeof(pminfo.error.footer) - 1);
|
||||
strncpy(pminfo.error.footer, footer, len);
|
||||
|
||||
if (g_error_handler != NULL) {
|
||||
g_error_handler(&pminfo);
|
||||
}
|
||||
}
|
||||
|
||||
secure_shutdown();
|
||||
}
|
||||
|
||||
void system_exit_error(const char* title, const char* message,
|
||||
const char* footer) {
|
||||
size_t title_len = title != NULL ? strlen(title) : 0;
|
||||
size_t message_len = message != NULL ? strlen(message) : 0;
|
||||
size_t footer_len = footer != NULL ? strlen(footer) : 0;
|
||||
|
||||
system_exit_error_ex(title, title_len, message, message_len, footer,
|
||||
footer_len);
|
||||
}
|
||||
|
||||
void system_exit_fatal_ex(const char* message, size_t message_len,
|
||||
const char* file, size_t file_len, int line) {
|
||||
fprintf(stderr, "ERROR: %s\n", message);
|
||||
if (file) {
|
||||
fprintf(stderr, "FILE: %s:%d\n", file, line);
|
||||
}
|
||||
fflush(stderr);
|
||||
|
||||
if (g_error_handler != NULL) {
|
||||
systask_postmortem_t pminfo = {0};
|
||||
size_t len;
|
||||
|
||||
pminfo.reason = TASK_TERM_REASON_FATAL;
|
||||
|
||||
len = MIN(message_len, sizeof(pminfo.fatal.expr) - 1);
|
||||
strncpy(pminfo.fatal.file, file, len);
|
||||
|
||||
len = MIN(file_len, sizeof(pminfo.fatal.file) - 1);
|
||||
strncpy(pminfo.fatal.expr, message, len);
|
||||
|
||||
pminfo.fatal.line = line;
|
||||
|
||||
if (g_error_handler != NULL) {
|
||||
g_error_handler(&pminfo);
|
||||
@ -71,26 +120,9 @@ void system_exit_error(const char* title, const char* message,
|
||||
}
|
||||
|
||||
void system_exit_fatal(const char* message, const char* file, int line) {
|
||||
fprintf(stderr, "ERROR: %s\n", message);
|
||||
if (file) {
|
||||
fprintf(stderr, "FILE: %s:%d\n", file, line);
|
||||
}
|
||||
fflush(stderr);
|
||||
|
||||
if (g_error_handler != NULL) {
|
||||
systask_postmortem_t pminfo = {0};
|
||||
|
||||
pminfo.reason = TASK_TERM_REASON_FATAL;
|
||||
strncpy(pminfo.fatal.file, file, sizeof(pminfo.fatal.file) - 1);
|
||||
strncpy(pminfo.fatal.expr, message, sizeof(pminfo.fatal.expr) - 1);
|
||||
pminfo.fatal.line = line;
|
||||
|
||||
if (g_error_handler != NULL) {
|
||||
g_error_handler(&pminfo);
|
||||
}
|
||||
}
|
||||
|
||||
secure_shutdown();
|
||||
size_t message_len = message != NULL ? strlen(message) : 0;
|
||||
size_t file_len = file != NULL ? strlen(file) : 0;
|
||||
system_exit_fatal_ex(message, message_len, file, file_len, line);
|
||||
}
|
||||
|
||||
const char* system_fault_message(const system_fault_t* fault) {
|
||||
|
Loading…
Reference in New Issue
Block a user