summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2020-03-29 15:14:29 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2020-03-29 15:14:29 +0000
commit6a6cdeaead733d406ae5a170216575841d2b6ecf (patch)
tree931e0babe32fe6175b929a91a1d9e3178dca29e8 /sys/arch/i386
parenteca2d9b0bc87a6b2c6bce45ae4c457befda7dc75 (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/i386')
-rw-r--r--sys/arch/i386/i386/db_trace.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/arch/i386/i386/db_trace.c b/sys/arch/i386/i386/db_trace.c
index 97aed9b6097..60787cf2395 100644
--- a/sys/arch/i386/i386/db_trace.c
+++ b/sys/arch/i386/i386/db_trace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_trace.c,v 1.39 2020/03/25 14:59:23 mpi Exp $ */
+/* $OpenBSD: db_trace.c,v 1.40 2020/03/29 15:14:28 visa Exp $ */
/* $NetBSD: db_trace.c,v 1.18 1996/05/03 19:42:01 christos Exp $ */
/*
@@ -263,10 +263,18 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
void
stacktrace_save_at(struct stacktrace *st, unsigned int skip)
{
- struct callframe *frame, *lastframe;
+ struct callframe *frame, *lastframe, *limit;
+ struct pcb *pcb = curpcb;
- frame = __builtin_frame_address(0);
st->st_count = 0;
+
+ if (pcb == NULL)
+ return;
+
+ frame = __builtin_frame_address(0);
+ KASSERT(INKERNEL(frame));
+ limit = (struct callframe *)((struct trapframe *)pcb->pcb_kstack - 1);
+
while (st->st_count < STACKTRACE_MAX) {
if (skip == 0)
st->st_pc[st->st_count++] = frame->f_retaddr;
@@ -276,10 +284,10 @@ stacktrace_save_at(struct stacktrace *st, unsigned int skip)
lastframe = frame;
frame = frame->f_frame;
- if (!INKERNEL(frame))
- break;
if (frame <= lastframe)
break;
+ if (frame >= limit)
+ break;
if (!INKERNEL(frame->f_retaddr))
break;
}