mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-06 13:09:50 +00:00
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
This commit is contained in:
parent
c49747eaf2
commit
5941edfcdc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=368240
@ -73,12 +73,8 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
|
||||
frame = (struct amd64_frame *)rbp;
|
||||
td = curthread;
|
||||
while (depth < pcstack_limit) {
|
||||
if (!INKERNEL((long) frame))
|
||||
break;
|
||||
|
||||
if ((vm_offset_t)frame >=
|
||||
td->td_kstack + ptoa(td->td_kstack_pages) ||
|
||||
(vm_offset_t)frame < td->td_kstack)
|
||||
if (!kstack_contains(curthread, (vm_offset_t)frame,
|
||||
sizeof(*frame))
|
||||
break;
|
||||
|
||||
callpc = frame->f_retaddr;
|
||||
@ -466,14 +462,11 @@ dtrace_getstackdepth(int aframes)
|
||||
frame = (struct amd64_frame *)rbp;
|
||||
depth++;
|
||||
for(;;) {
|
||||
if (!INKERNEL((long) frame))
|
||||
break;
|
||||
if (!INKERNEL((long) frame->f_frame))
|
||||
if (!kstack_contains(curthread, (vm_offset_t)frame,
|
||||
sizeof(*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;
|
||||
}
|
||||
|
@ -73,7 +73,8 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
|
||||
|
||||
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, int aframes,
|
||||
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))
|
||||
break;
|
||||
if (!INKERNEL((long) frame->f_frame))
|
||||
if (!kstack_contains((vm_offset_t)frame, sizeof(*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;
|
||||
}
|
||||
|
@ -527,8 +527,7 @@ db_findstack_cmd(db_expr_t addr, bool have_addr, db_expr_t dummy3 __unused,
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -53,9 +53,8 @@ stack_capture(struct thread *td, struct stack *st, struct unwind_state *frame)
|
||||
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))
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -79,9 +79,7 @@ stack_capture(struct thread *td, struct stack *st, register_t fp)
|
||||
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))
|
||||
|
Loading…
Reference in New Issue
Block a user