diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2020-03-29 15:14:29 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2020-03-29 15:14:29 +0000 |
commit | 6a6cdeaead733d406ae5a170216575841d2b6ecf (patch) | |
tree | 931e0babe32fe6175b929a91a1d9e3178dca29e8 /sys/arch/arm64 | |
parent | eca2d9b0bc87a6b2c6bce45ae4c457befda7dc75 (diff) |
Prevent stack trace saving from inspecting untrusted data. On amd64,
arm64 and i386, the chain of call frames is continuous from kernel
to userspace. The unwinder has to stop at the latest when it reaches
the start of the kernel stack.
OK mpi@
Diffstat (limited to 'sys/arch/arm64')
-rw-r--r-- | sys/arch/arm64/arm64/db_trace.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/sys/arch/arm64/arm64/db_trace.c b/sys/arch/arm64/arm64/db_trace.c index 46c49fcfa52..8ea1b463e56 100644 --- a/sys/arch/arm64/arm64/db_trace.c +++ b/sys/arch/arm64/arm64/db_trace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_trace.c,v 1.9 2020/01/20 15:58:23 visa Exp $ */ +/* $OpenBSD: db_trace.c,v 1.10 2020/03/29 15:14:28 visa Exp $ */ /* $NetBSD: db_trace.c,v 1.8 2003/01/17 22:28:48 thorpej Exp $ */ /* @@ -152,16 +152,29 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, void stacktrace_save(struct stacktrace *st) { - struct callframe *frame; + struct callframe *frame, *lastframe, *limit; + struct proc *p = curproc; - frame = __builtin_frame_address(0); st->st_count = 0; + + if (p == NULL) + return; + + frame = __builtin_frame_address(0); + KASSERT(INKERNEL(frame)); + limit = (struct callframe *)STACKALIGN(p->p_addr + USPACE - + sizeof(struct trapframe) - 0x10); + while (st->st_count < STACKTRACE_MAX) { st->st_pc[st->st_count++] = frame->f_lr; - if (!INKERNEL(frame->f_frame) || frame->f_frame <= frame) - break; + lastframe = frame; frame = frame->f_frame; + + if (frame <= lastframe) + break; + if (frame >= limit) + break; if (!INKERNEL(frame->f_lr)) break; } |