svn commit: r368240 - in head/sys: cddl/dev/dtrace/amd64 cddl/dev/dtrace/i386 ddb riscv/riscv sys x86/x86
John Baldwin
jhb at FreeBSD.org
Tue Dec 1 17:04:48 UTC 2020
Author: jhb
Date: Tue Dec 1 17:04:46 2020
New Revision: 368240
URL: https://svnweb.freebsd.org/changeset/base/368240
Log:
Add a kstack_contains() helper function.
This is useful for stack unwinders which need to avoid out-of-bounds
reads of a kernel stack which can trigger kernel faults.
Reviewed by: kib, markj
Obtained from: CheriBSD
Sponsored by: DARPA
Differential Revision: https://reviews.freebsd.org/D27356
Modified:
head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
head/sys/cddl/dev/dtrace/i386/dtrace_isa.c
head/sys/ddb/db_ps.c
head/sys/riscv/riscv/stack_machdep.c
head/sys/sys/proc.h
head/sys/x86/x86/stack_machdep.c
Modified: head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c Tue Dec 1 16:44:36 2020 (r368239)
+++ head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c Tue Dec 1 17:04:46 2020 (r368240)
@@ -73,14 +73,10 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, in
frame = (struct amd64_frame *)rbp;
td = curthread;
while (depth < pcstack_limit) {
- if (!INKERNEL((long) frame))
+ if (!kstack_contains(curthread, (vm_offset_t)frame,
+ sizeof(*frame))
break;
- if ((vm_offset_t)frame >=
- td->td_kstack + ptoa(td->td_kstack_pages) ||
- (vm_offset_t)frame < td->td_kstack)
- break;
-
callpc = frame->f_retaddr;
if (!INKERNEL(callpc))
@@ -466,14 +462,11 @@ dtrace_getstackdepth(int aframes)
frame = (struct amd64_frame *)rbp;
depth++;
for(;;) {
- if (!INKERNEL((long) frame))
+ if (!kstack_contains(curthread, (vm_offset_t)frame,
+ sizeof(*frame))
break;
- if (!INKERNEL((long) frame->f_frame))
- break;
depth++;
- if (frame->f_frame <= frame ||
- (vm_offset_t)frame->f_frame >= curthread->td_kstack +
- curthread->td_kstack_pages * PAGE_SIZE)
+ if (frame->f_frame <= frame)
break;
frame = frame->f_frame;
}
Modified: head/sys/cddl/dev/dtrace/i386/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/i386/dtrace_isa.c Tue Dec 1 16:44:36 2020 (r368239)
+++ head/sys/cddl/dev/dtrace/i386/dtrace_isa.c Tue Dec 1 17:04:46 2020 (r368240)
@@ -73,7 +73,8 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, in
frame = (struct i386_frame *)ebp;
while (depth < pcstack_limit) {
- if (!INKERNEL(frame))
+ if (!kstack_contains(curthread, (vm_offset_t)frame,
+ sizeof(*frame))
break;
callpc = frame->f_retaddr;
@@ -91,9 +92,7 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, in
pcstack[depth++] = callpc;
}
- if (frame->f_frame <= frame ||
- (vm_offset_t)frame->f_frame >= curthread->td_kstack +
- curthread->td_kstack_pages * PAGE_SIZE)
+ if (frame->f_frame <= frame)
break;
frame = frame->f_frame;
}
@@ -484,14 +483,10 @@ dtrace_getstackdepth(int aframes)
frame = (struct i386_frame *)ebp;
depth++;
for(;;) {
- if (!INKERNEL((long) frame))
+ if (!kstack_contains((vm_offset_t)frame, sizeof(*frame))
break;
- if (!INKERNEL((long) frame->f_frame))
- break;
depth++;
- if (frame->f_frame <= frame ||
- (vm_offset_t)frame->f_frame >= curthread->td_kstack +
- curthread->td_kstack_pages * PAGE_SIZE)
+ if (frame->f_frame <= frame)
break;
frame = frame->f_frame;
}
Modified: head/sys/ddb/db_ps.c
==============================================================================
--- head/sys/ddb/db_ps.c Tue Dec 1 16:44:36 2020 (r368239)
+++ head/sys/ddb/db_ps.c Tue Dec 1 17:04:46 2020 (r368240)
@@ -527,8 +527,7 @@ db_findstack_cmd(db_expr_t addr, bool have_addr, db_ex
FOREACH_PROC_IN_SYSTEM(p) {
FOREACH_THREAD_IN_PROC(p, td) {
- if (td->td_kstack <= saddr && saddr < td->td_kstack +
- PAGE_SIZE * td->td_kstack_pages) {
+ if (kstack_contains(td, saddr, 1)) {
db_printf("Thread %p\n", td);
return;
}
Modified: head/sys/riscv/riscv/stack_machdep.c
==============================================================================
--- head/sys/riscv/riscv/stack_machdep.c Tue Dec 1 16:44:36 2020 (r368239)
+++ head/sys/riscv/riscv/stack_machdep.c Tue Dec 1 17:04:46 2020 (r368240)
@@ -53,9 +53,8 @@ stack_capture(struct thread *td, struct stack *st, str
stack_zero(st);
while (1) {
- if ((vm_offset_t)frame->fp < td->td_kstack ||
- (vm_offset_t)frame->fp >= td->td_kstack +
- td->td_kstack_pages * PAGE_SIZE)
+ if (!kstack_contains(td, (vm_offset_t)frame->fp -
+ (sizeof(uintptr_t) * 2), sizeof(uintptr_t) * 2))
break;
unwind_frame(frame);
if (!INKERNEL((vm_offset_t)frame->pc))
Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Tue Dec 1 16:44:36 2020 (r368239)
+++ head/sys/sys/proc.h Tue Dec 1 17:04:46 2020 (r368240)
@@ -1198,6 +1198,13 @@ curthread_pflags2_restore(int save)
curthread->td_pflags2 &= save;
}
+static __inline bool
+kstack_contains(struct thread *td, vm_offset_t va, size_t len)
+{
+ return (va >= td->td_kstack && va + len >= va &&
+ va + len <= td->td_kstack + td->td_kstack_pages * PAGE_SIZE);
+}
+
static __inline __pure2 struct td_sched *
td_get_sched(struct thread *td)
{
Modified: head/sys/x86/x86/stack_machdep.c
==============================================================================
--- head/sys/x86/x86/stack_machdep.c Tue Dec 1 16:44:36 2020 (r368239)
+++ head/sys/x86/x86/stack_machdep.c Tue Dec 1 17:04:46 2020 (r368240)
@@ -79,9 +79,7 @@ stack_capture(struct thread *td, struct stack *st, reg
stack_zero(st);
frame = (x86_frame_t)fp;
while (1) {
- if ((vm_offset_t)frame < td->td_kstack ||
- (vm_offset_t)frame >= td->td_kstack +
- td->td_kstack_pages * PAGE_SIZE)
+ if (!kstack_contains(td, (vm_offset_t)frame, sizeof(*frame)))
break;
callpc = frame->f_retaddr;
if (!INKERNEL(callpc))
More information about the svn-src-head
mailing list