Skip to content

Commit

Permalink
core: make stack trace robust
Browse files Browse the repository at this point in the history
Makes stack trace robust by checking addresses before copying data.
Kernel stack traces are a bit more relaxed as we have crashed already.

Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org>
Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (HiKey960 AArch32, Aarch64)
Tested-by: Jens Wiklander <jens.wiklander@linaro.org> (Juno, QEMU)
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
  • Loading branch information
jenswi-linaro authored and jforissier committed Jun 28, 2018
1 parent a0c3590 commit af8149d
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 70 deletions.
21 changes: 12 additions & 9 deletions core/arch/arm/include/kernel/unwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
struct unwind_state_arm32 {
uint32_t registers[16];
uint32_t start_pc;
uint32_t *insn;
vaddr_t insn;
unsigned entries;
unsigned byte;
uint16_t update_mask;
Expand All @@ -52,9 +52,11 @@ struct unwind_state_arm32 {
* Unwind a 32-bit user or kernel stack.
* @exidx, @exidx_sz: address and size of the binary search index table
* (.ARM.exidx section).
* @stack, @stack_size: the bottom of the stack and its size, respectively.
*/
bool unwind_stack_arm32(struct unwind_state_arm32 *state, uaddr_t exidx,
size_t exidx_sz);
bool unwind_stack_arm32(struct unwind_state_arm32 *state, vaddr_t exidx,
size_t exidx_sz, bool kernel_stack, vaddr_t stack,
size_t stack_size);

#ifdef ARM64
/* The state of the unwind process (64-bit mode) */
Expand All @@ -68,18 +70,19 @@ struct unwind_state_arm64 {
* Unwind a 64-bit user or kernel stack.
* @stack, @stack_size: the bottom of the stack and its size, respectively.
*/
bool unwind_stack_arm64(struct unwind_state_arm64 *state, uaddr_t stack,
size_t stack_size);
bool unwind_stack_arm64(struct unwind_state_arm64 *state, bool kernel_stack,
vaddr_t stack, size_t stack_size);
#endif /*ARM64*/

#if defined(CFG_UNWIND) && (TRACE_LEVEL > 0)

#ifdef ARM64
void print_stack_arm64(int level, struct unwind_state_arm64 *state, uaddr_t exidx,
size_t exidx_sz);
void print_stack_arm64(int level, struct unwind_state_arm64 *state,
bool kernel_stack, vaddr_t stack, size_t stack_size);
#endif
void print_stack_arm32(int level, struct unwind_state_arm32 *state, uaddr_t exidx,
size_t exidx_sz);
void print_stack_arm32(int level, struct unwind_state_arm32 *state,
vaddr_t exidx, size_t exidx_sz, bool kernel_stack,
vaddr_t stack, size_t stack_size);
void print_kernel_stack(int level);

#else /* defined(CFG_UNWIND) && (TRACE_LEVEL > 0) */
Expand Down
36 changes: 28 additions & 8 deletions core/arch/arm/kernel/abort.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ enum fault_type {

#ifdef CFG_UNWIND

static void get_current_ta_exidx(uaddr_t *exidx, size_t *exidx_sz)
static void get_current_ta_exidx_stack(vaddr_t *exidx, size_t *exidx_sz,
vaddr_t *stack, size_t *stack_size)
{
struct tee_ta_session *s;
struct user_ta_ctx *utc;
Expand All @@ -45,6 +46,9 @@ static void get_current_ta_exidx(uaddr_t *exidx, size_t *exidx_sz)
if (*exidx)
*exidx += utc->load_addr;
*exidx_sz = utc->exidx_size;

*stack = utc->stack_addr;
*stack_size = utc->mobj_stack->size;
}

#ifdef ARM32
Expand All @@ -55,21 +59,30 @@ static void get_current_ta_exidx(uaddr_t *exidx, size_t *exidx_sz)
static void __print_stack_unwind_arm32(struct abort_info *ai)
{
struct unwind_state_arm32 state;
uaddr_t exidx;
vaddr_t exidx;
size_t exidx_sz;
uint32_t mode = ai->regs->spsr & CPSR_MODE_MASK;
uint32_t sp;
uint32_t lr;
vaddr_t stack;
size_t stack_size;
bool kernel_stack;

if (abort_is_user_exception(ai)) {
get_current_ta_exidx(&exidx, &exidx_sz);
get_current_ta_exidx_stack(&exidx, &exidx_sz, &stack,
&stack_size);
if (!exidx) {
EMSG_RAW("Call stack not available");
return;
}
kernel_stack = false;
} else {
exidx = (vaddr_t)__exidx_start;
exidx_sz = (vaddr_t)__exidx_end - (vaddr_t)__exidx_start;
/* Kernel stack */
stack = thread_stack_start();
stack_size = thread_stack_size();
kernel_stack = true;
}

if (mode == CPSR_MODE_USR || mode == CPSR_MODE_SYS) {
Expand Down Expand Up @@ -97,20 +110,23 @@ static void __print_stack_unwind_arm32(struct abort_info *ai)
state.registers[14] = lr;
state.registers[15] = ai->pc;

print_stack_arm32(TRACE_ERROR, &state, exidx, exidx_sz);
print_stack_arm32(TRACE_ERROR, &state, exidx, exidx_sz, kernel_stack,
stack, stack_size);
}
#else /* ARM32 */

static void __print_stack_unwind_arm32(struct abort_info *ai __unused)
{
struct unwind_state_arm32 state;
uaddr_t exidx;
vaddr_t exidx;
size_t exidx_sz;
vaddr_t stack;
size_t stack_size;

/* 64-bit kernel, hence 32-bit unwind must be for user mode */
assert(abort_is_user_exception(ai));

get_current_ta_exidx(&exidx, &exidx_sz);
get_current_ta_exidx_stack(&exidx, &exidx_sz, &stack, &stack_size);

memset(&state, 0, sizeof(state));
state.registers[0] = ai->regs->x0;
Expand All @@ -130,14 +146,16 @@ static void __print_stack_unwind_arm32(struct abort_info *ai __unused)
state.registers[14] = ai->regs->x14;
state.registers[15] = ai->pc;

print_stack_arm32(TRACE_ERROR, &state, exidx, exidx_sz);
print_stack_arm32(TRACE_ERROR, &state, exidx, exidx_sz,
false /*!kernel_stack*/, stack, stack_size);
}
#endif /* ARM32 */
#ifdef ARM64
/* Kernel or user mode unwind (64-bit execution state) */
static void __print_stack_unwind_arm64(struct abort_info *ai)
{
struct unwind_state_arm64 state;
bool kernel_stack;
uaddr_t stack;
size_t stack_size;

Expand All @@ -152,17 +170,19 @@ static void __print_stack_unwind_arm64(struct abort_info *ai)
/* User stack */
stack = utc->stack_addr;
stack_size = utc->mobj_stack->size;
kernel_stack = false;
} else {
/* Kernel stack */
stack = thread_stack_start();
stack_size = thread_stack_size();
kernel_stack = true;
}

memset(&state, 0, sizeof(state));
state.pc = ai->regs->elr;
state.fp = ai->regs->x29;

print_stack_arm64(TRACE_ERROR, &state, stack, stack_size);
print_stack_arm64(TRACE_ERROR, &state, kernel_stack, stack, stack_size);
}
#else
static void __print_stack_unwind_arm64(struct abort_info *ai __unused)
Expand Down
Loading

0 comments on commit af8149d

Please sign in to comment.